diff --git a/TMI-practicum/Circle.cs b/TMI-practicum/Circle.cs index 34199e0..7c71853 100644 --- a/TMI-practicum/Circle.cs +++ b/TMI-practicum/Circle.cs @@ -25,7 +25,7 @@ namespace TMI_practicum { IList intersections; 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 px = Math.Round(X + a * (c1.X - X) / d, 15); diff --git a/TMI-practicum/SweepLineEffAlgorithm.cs b/TMI-practicum/SweepLineEffAlgorithm.cs index e3491be..c302e11 100644 --- a/TMI-practicum/SweepLineEffAlgorithm.cs +++ b/TMI-practicum/SweepLineEffAlgorithm.cs @@ -12,8 +12,8 @@ namespace TMI_practicum var intersections = new Stack(); var events = new PriorityQueue(); - var upperActive = new CircleTree(); - var bottomActive = new CircleTree(); + var upperActive = new CircleTree(); + var bottomActive = new CircleTree(); foreach (var circle in circles) @@ -29,17 +29,16 @@ namespace TMI_practicum 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)); + upperActive.Add(new SegmentKey(e.X, e.Circle.Y + e.Circle.R, SegmentKey.SegmentType.Upper, hash), e.Circle); + bottomActive.Add(new SegmentKey(e.X, e.Circle.Y - e.Circle.R, SegmentKey.SegmentType.Bottom, hash), + 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)); + upperActive.Remove(new SegmentKey(e.X, e.Circle.Y + e.Circle.R, SegmentKey.SegmentType.Upper, hash)); + bottomActive.Remove(new SegmentKey(e.X, e.Circle.Y - e.Circle.R, SegmentKey.SegmentType.Bottom, hash)); break; default: throw new ArgumentOutOfRangeException(); @@ -50,34 +49,36 @@ namespace TMI_practicum return intersections; } - private static void CheckIntersections(CircleTree active, Event e, Stack intersections, bool upper) + private static void CheckIntersections(CircleTree active, Event e, Stack intersections, bool upper) { - Segment other; + + Circle other = null; + Circle other2 = null; 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())); + other = upper? active.FindSuccessor(new SegmentKey(e.X, e.Circle.Y, SegmentKey.SegmentType.Upper, e.GetHashCode())) + : + active.FindPredecessor(new SegmentKey(e.X, e.Circle.Y, SegmentKey.SegmentType.Bottom, e.GetHashCode())); + other2 = upper? active.FindPredecessor(new SegmentKey(e.X, e.Circle.Y, SegmentKey.SegmentType.Upper, e.GetHashCode())) + : + active.FindSuccessor(new SegmentKey(e.X, e.Circle.Y, SegmentKey.SegmentType.Bottom, e.GetHashCode())); } catch (KeyNotFoundException) { - return; } - var intersects = e.Circle.FindIntersections(other.Circle); - if (intersects == null) return; - - foreach (var intersection in intersects) + if (other != null) { - if (upper) + var intersects = e.Circle.FindIntersections(other); + if (intersects != null) { - if (intersection.Y < e.Circle.Y) continue; + + foreach (var intersection in intersects) + { + if (upper && e.Circle.Y == intersection.Y) continue; + intersections.Push(intersection); + } } - else - { - if (intersection.Y > e.Circle.Y) continue; - } - intersections.Push(intersection); } } @@ -106,7 +107,6 @@ namespace TMI_practicum public enum EventType { Start, - Intersect, End } @@ -123,41 +123,15 @@ namespace TMI_practicum } } - private class Segment : IComparable - { - 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 { private readonly double _x; - private readonly double _y; - private readonly Segment.SegmentType _type; + private readonly double? _y; + public double Y => _y ?? double.MinValue; + private readonly SegmentType _type; private readonly int _identifier; - public SegmentKey(double x, double y, Segment.SegmentType type, int identifier) + public SegmentKey(double x, double y, SegmentType type, int identifier) { _y = y; _type = type; @@ -168,7 +142,7 @@ namespace TMI_practicum 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); + if (!_y.Equals(other._y)) return Y.CompareTo(other.Y); return _type.Equals(other._type) ? _x.CompareTo(other._x) : _type.CompareTo(other._type); } @@ -185,6 +159,12 @@ namespace TMI_practicum { return _identifier.GetHashCode() ^ _type.GetHashCode(); } + + public enum SegmentType + { + Bottom, + Upper + } } } public static class EnumerableExtensions