1
0

initial implementation sweeplineff

This commit is contained in:
2019-05-18 18:34:20 +02:00
parent d0151ca13a
commit ec65d0d925
4 changed files with 201 additions and 10 deletions

View File

@@ -25,7 +25,7 @@ namespace TMI_practicum
{ {
IList<Intersection> intersections; IList<Intersection> intersections;
double d = Distance(c1); double d = Distance(c1);
if (d > R + c1.R || d < Math.Abs(R - c1.R) || (d == 0.0 && R - c1.R == 0.0)) return null; if (d > R + c1.R || d < Math.Abs(R - c1.R) || d == 0.0 && R - c1.R == 0.0) return null;
double a = Math.Round((R * R - c1.R * c1.R + d * d) / (2.0*d), 15); double a = Math.Round((R * R - c1.R * c1.R + d * d) / (2.0*d), 15);
double px = Math.Round(X + a * (c1.X - X) / d, 15); double px = Math.Round(X + a * (c1.X - X) / d, 15);

View File

@@ -10,6 +10,8 @@ namespace TMI_practicum
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
//SweepLineEffAlgorithm.Solve(null);
if (args.Length < 1) if (args.Length < 1)
{ {
Console.WriteLine("Please enter a file."); Console.WriteLine("Please enter a file.");
@@ -22,26 +24,26 @@ namespace TMI_practicum
Environment.Exit(1); Environment.Exit(1);
} }
var parsed = ParseFile(args[0]); var (algorithm, _, circles) = ParseFile(args[0]);
IEnumerable<Intersection> solved; IEnumerable<Intersection> solved;
Stopwatch stopwatch = new Stopwatch(); Stopwatch stopwatch = new Stopwatch();
stopwatch.Start(); stopwatch.Start();
switch (parsed.Algorithm) switch (algorithm)
{ {
case 1: case 1:
solved = SimpleAlgorithm.Solve(parsed.Circles); solved = SimpleAlgorithm.Solve(circles);
break; break;
case 2: case 2:
solved = SweepLineAlgorithm.Solve(parsed.Circles); solved = SweepLineAlgorithm.Solve(circles);
break; break;
case 3: case 3:
solved = SweepLineEffAlgorithm.Solve(parsed.Circles); solved = SweepLineEffAlgorithm.Solve(circles);
break; break;
default: default:
throw new ArgumentException("Algorithm with id: " + parsed.Algorithm + " is not defined!"); throw new ArgumentException("Algorithm with id: " + algorithm + " is not defined!");
} }
stopwatch.Stop(); stopwatch.Stop();
@@ -95,7 +97,7 @@ namespace TMI_practicum
{ {
foreach (var intersection in intersections) foreach (var intersection in intersections)
{ {
sw.WriteLine("{0}\t{1}", intersection.X, intersection.Y); sw.WriteLine("{0:0.000000000000000}\t{1:0.000000000000000}", intersection.X, intersection.Y);
} }
sw.WriteLine("\r\n{0}", time); sw.WriteLine("\r\n{0}", time);

View File

@@ -1,5 +1,7 @@
using System.Collections; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Medallion.Collections;
namespace TMI_practicum namespace TMI_practicum
{ {
@@ -7,7 +9,193 @@ namespace TMI_practicum
{ {
public static IEnumerable<Intersection> Solve(IEnumerable<Circle> circles) public static IEnumerable<Intersection> Solve(IEnumerable<Circle> circles)
{ {
return null; var intersections = new Stack<Intersection>();
var events = new PriorityQueue<Event>();
var upperActive = new CircleTree<SegmentKey, Segment>();
var bottomActive = new CircleTree<SegmentKey, Segment>();
foreach (var circle in circles)
{
events.Enqueue(new Event(Event.EventType.Start, circle.X - circle.R, circle));
events.Enqueue(new Event(Event.EventType.End, circle.X + circle.R, circle));
}
while (events.Count != 0)
{
Event e = events.Dequeue();
int hash = e.GetHashCode();
switch (e.Type)
{
case Event.EventType.Start:
upperActive.Add(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Upper, hash),
new Segment(Segment.SegmentType.Upper, e.Circle.Y, e.Circle));
bottomActive.Add(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Bottom, hash),
new Segment(Segment.SegmentType.Bottom, e.Circle.Y, e.Circle));
CheckIntersections(upperActive, e, intersections, true);
CheckIntersections(bottomActive, e, intersections, false);
break;
case Event.EventType.End:
upperActive.Remove(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Upper, hash));
bottomActive.Remove(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Bottom, hash));
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return intersections;
}
private static void CheckIntersections(CircleTree<SegmentKey, Segment> active, Event e, Stack<Intersection> intersections, bool upper)
{
Segment other;
try
{
other = upper
? active.FindSuccessor(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Upper, e.GetHashCode()))
: active.FindPredecessor(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Bottom, e.GetHashCode()));
}
catch (KeyNotFoundException)
{
return;
}
var intersects = e.Circle.FindIntersections(other.Circle);
if (intersects == null) return;
foreach (var intersection in intersects)
{
if (upper)
{
if (intersection.Y < e.Circle.Y) continue;
}
else
{
if (intersection.Y > e.Circle.Y) continue;
}
intersections.Push(intersection);
}
}
private class CircleTree<TKey, TValue> : SortedDictionary<TKey, TValue>
{
public TValue FindSuccessor(TKey key)
{
var other = this.Keys.Where(s => this.Comparer.Compare(s, key) > 0).MinOrDefault();
return this[other];
}
public TValue FindPredecessor(TKey key)
{
var other = this.Keys.Where(s => this.Comparer.Compare(s, key) < 0).MaxOrDefault();
return this[other];
}
}
private struct Event : IComparable<Event>
{
public EventType Type { get; }
public Circle Circle { get; }
public double X { get; }
public enum EventType
{
Start,
Intersect,
End
}
public Event(EventType type, double x, Circle circle)
{
Type = type;
X = x;
Circle = circle;
}
public int CompareTo(Event other)
{
return X.CompareTo(other.X);
}
}
private class Segment : IComparable<Segment>
{
public Segment(SegmentType type, double y, Circle circle)
{
_type = type;
_y = y;
Circle = circle;
}
private readonly SegmentType _type;
private readonly double _y;
public Circle Circle { get; }
public int CompareTo(Segment other)
{
throw new NotImplementedException();
}
public enum SegmentType
{
Bottom,
Upper,
Null
}
}
private struct SegmentKey : IComparable<SegmentKey>
{
private readonly double _x;
private readonly double _y;
private readonly Segment.SegmentType _type;
private readonly int _identifier;
public SegmentKey(double x, double y, Segment.SegmentType type, int identifier)
{
_y = y;
_type = type;
_identifier = identifier;
_x = x;
}
public int CompareTo(SegmentKey other)
{
if (_identifier.Equals(other._identifier)) return _type.CompareTo(other._type);
if (!_y.Equals(other._y)) return _y.CompareTo(other._y);
return _type.Equals(other._type) ? _x.CompareTo(other._x) : _type.CompareTo(other._type);
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType()) return false;
SegmentKey r = (SegmentKey) obj;
return _identifier.Equals(r._identifier) && _type.Equals(r._type);
}
public override int GetHashCode()
{
return _identifier.GetHashCode() ^ _type.GetHashCode();
}
}
}
public static class EnumerableExtensions
{
public static T MinOrDefault<T>(this IEnumerable<T> sequence)
{
return sequence.Any() ? sequence.Min() : default(T);
}
public static T MaxOrDefault<T>(this IEnumerable<T> sequence)
{
return sequence.Any() ? sequence.Max() : default(T);
} }
} }
} }

View File

@@ -46,6 +46,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Circle.cs" /> <Compile Include="Circle.cs" />