diff --git a/TMI-practicum/Circle.cs b/TMI-practicum/Circle.cs index 5c4091b..415db43 100644 --- a/TMI-practicum/Circle.cs +++ b/TMI-practicum/Circle.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace TMI_practicum { @@ -17,7 +18,33 @@ namespace TMI_practicum public double Distance(Circle otherCircle) { - return Math.Sqrt(Math.Pow(X - otherCircle.X, 2) + Math.Pow(Y - otherCircle.Y, 2)); + return Math.Round(Math.Sqrt(Math.Pow(X - otherCircle.X, 2) + Math.Pow(Y - otherCircle.Y, 2)), 15); + } + + public IList FindIntersections(Circle c1) + { + var intersections = new List(); + 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; + + + 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 py = Math.Round(Y + a * (c1.Y - Y) / d, 15); + + double htemp = Math.Round(R * R - a * a, 15); + if (htemp == 0) + { + intersections.Add(new Intersection(px, py)); + } + else + { + double h = Math.Round(Math.Sqrt(htemp), 15); + intersections.Add(new Intersection(px + h * (c1.Y - Y) / d, py - h * (c1.X - X) / d)); + intersections.Add(new Intersection(px - h * (c1.Y - Y) / d, py + h * (c1.X - X) / d)); + } + + return intersections; } } } \ No newline at end of file diff --git a/TMI-practicum/Intersection.cs b/TMI-practicum/Intersection.cs index 43382a6..16e354e 100644 --- a/TMI-practicum/Intersection.cs +++ b/TMI-practicum/Intersection.cs @@ -4,7 +4,7 @@ namespace TMI_practicum { public readonly double X; public readonly double Y; - + public Intersection(double x, double y) { X = x; diff --git a/TMI-practicum/Program.cs b/TMI-practicum/Program.cs index 9a82af8..2c9ff53 100644 --- a/TMI-practicum/Program.cs +++ b/TMI-practicum/Program.cs @@ -23,7 +23,7 @@ namespace TMI_practicum } var parsed = ParseFile(args[0]); - + IEnumerable solved; Stopwatch stopwatch = new Stopwatch(); @@ -35,7 +35,8 @@ namespace TMI_practicum solved = SimpleAlgorithm.Solve(parsed.Item3); break; case 2: - throw new NotImplementedException(); + solved = SweepLineAlgorithm.Solve(parsed.Item3); + break; case 3: throw new NotImplementedException(); default: @@ -52,7 +53,7 @@ namespace TMI_practicum byte algoritm = 0; int nbCircles = 0; - var circles = new List(); + Circle[] circles = null; using (StreamReader file = new StreamReader(path)) { @@ -60,12 +61,13 @@ namespace TMI_practicum { algoritm = byte.Parse(file.ReadLine()); nbCircles = int.Parse(file.ReadLine()); - + circles = new Circle[nbCircles]; string line; + int i = 0; while ((line = file.ReadLine()) != null) { double[] parts = line.Split(' ').Select(double.Parse).ToArray(); - circles.Add(new Circle(parts[0], parts[1], parts[2])); + circles[i++] = new Circle(parts[0], parts[1], parts[2]); } } catch (Exception) diff --git a/TMI-practicum/SimpleAlgorithm.cs b/TMI-practicum/SimpleAlgorithm.cs index 65ccc4d..18048b6 100644 --- a/TMI-practicum/SimpleAlgorithm.cs +++ b/TMI-practicum/SimpleAlgorithm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace TMI_practicum @@ -7,7 +6,7 @@ namespace TMI_practicum { public static IEnumerable Solve(IList circles) { - var intersections = new Stack(); + var intersections = new List(); for (int i = 0; i < circles.Count - 1; i++) { @@ -15,35 +14,12 @@ namespace TMI_practicum { var c1 = circles[i]; var c2 = circles[j]; - CalculateIntersection(intersections, c1, c2); + var intersects = c1.FindIntersections(c2); + if (intersects != null) intersections.AddRange(c1.FindIntersections(c2)); } } return intersections; } - - private static void CalculateIntersection(Stack intersections, Circle c1, Circle c2) - { - double d = c1.Distance(c2); - if (d > c1.R + c2.R || d < Math.Abs(c1.R - c2.R)) return; - - if (d == 0.0 && c1.R - c2.R == 0.0) throw new ArgumentException("Circles may not be coincident!"); - - double a = (c1.R * c1.R - c2.R * c2.R + d * d) / (2.0*d); - double px = c1.X + a * (c2.X - c1.X) / d; - double py = c1.Y + a * (c2.Y - c1.Y) / d; - - double htemp = c1.R * c1.R - a * a; - if (htemp == 0) - { - intersections.Push(new Intersection(px, py)); - } - else - { - double h = Math.Sqrt(htemp); - intersections.Push(new Intersection(px + h * (c2.Y - c1.Y) / d, py - h * (c2.X - c1.X) / d)); - intersections.Push(new Intersection(px - h * (c2.Y - c1.Y) / d, py + h * (c2.X - c1.X) / d)); - } - } } } \ No newline at end of file diff --git a/TMI-practicum/SweepLineAlgorithm.cs b/TMI-practicum/SweepLineAlgorithm.cs index fd51f23..b35bcc0 100644 --- a/TMI-practicum/SweepLineAlgorithm.cs +++ b/TMI-practicum/SweepLineAlgorithm.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Priority_Queue; +using Medallion.Collections; namespace TMI_practicum { @@ -8,58 +8,73 @@ namespace TMI_practicum { public static IEnumerable Solve(IList circles) { - // fuck deze priority queue piece of shit.... >:( - SimplePriorityQueue events = new SimplePriorityQueue(); - Stack intersections = new Stack(); - var segments = new List(); - - - + var events = new PriorityQueue(); + var intersections = new List(); + var active = new List(); foreach (var circle in circles) { - events.Enqueue(new Event(Event.EventType.Start, circle.X - circle.R), circle.X - circle.R); - events.Enqueue(new Event(Event.EventType.End, circle.X + circle.R), circle.X + circle.R); + 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(); + + switch (e.Type) + { + case Event.EventType.Start: + active.Add(e.Circle); + CheckIntersections(active, e.Circle, intersections); + break; + case Event.EventType.End: + active.Remove(e.Circle); + break; + default: + throw new ArgumentOutOfRangeException(); + } } - return null; + return intersections; + } + + private static void CheckIntersections(IEnumerable active, Circle circle, List intersections) + { + foreach (var otherCircle in active) + { + if (circle.Equals(otherCircle)) continue; + + var intersects = circle.FindIntersections(otherCircle); + if (intersects == null) continue; + + intersections.AddRange(intersects); + } } - private struct Event + private struct Event : IComparable { public EventType Type { get; } + public Circle Circle { get; } public double X { get; } public enum EventType { Start, - End, - Intersect + End } - public Event(EventType type, double xCoordinate) + public Event(EventType type, double x, Circle circle) { Type = type; - X = xCoordinate; - } - } - - - private struct Segment - { - public SegmentType Type { get; } - public Circle Circle { get; } - public enum SegmentType - { - Top, - Bottom - } - - public Segment(Circle circle, SegmentType type) - { + X = x; Circle = circle; - Type = type; + } + + public int CompareTo(Event other) + { + return X.CompareTo(other.X); } } } diff --git a/TMI-practicum/TMI-practicum.csproj b/TMI-practicum/TMI-practicum.csproj index 61bc847..391d1a6 100644 --- a/TMI-practicum/TMI-practicum.csproj +++ b/TMI-practicum/TMI-practicum.csproj @@ -33,11 +33,11 @@ 4 - - - ..\packages\OptimizedPriorityQueue.4.2.0\lib\net45\Priority Queue.dll + + ..\packages\MedallionPriorityQueue.1.1.0\lib\net45\MedallionPriorityQueue.dll True + diff --git a/TMI-practicum/packages.config b/TMI-practicum/packages.config index 7312d37..ab34aaf 100644 --- a/TMI-practicum/packages.config +++ b/TMI-practicum/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file