update sweeplineff
This commit is contained in:
@@ -25,7 +25,7 @@ namespace TMI_practicum
|
||||
{
|
||||
IList<Intersection> 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);
|
||||
|
@@ -12,8 +12,8 @@ namespace TMI_practicum
|
||||
var intersections = new Stack<Intersection>();
|
||||
var events = new PriorityQueue<Event>();
|
||||
|
||||
var upperActive = new CircleTree<SegmentKey, Segment>();
|
||||
var bottomActive = new CircleTree<SegmentKey, Segment>();
|
||||
var upperActive = new CircleTree<SegmentKey, Circle>();
|
||||
var bottomActive = new CircleTree<SegmentKey, Circle>();
|
||||
|
||||
|
||||
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<SegmentKey, Segment> active, Event e, Stack<Intersection> intersections, bool upper)
|
||||
private static void CheckIntersections(CircleTree<SegmentKey, Circle> active, Event e, Stack<Intersection> 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<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 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
|
||||
|
Reference in New Issue
Block a user