update sweeplineff
This commit is contained in:
@@ -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);
|
||||||
|
@@ -12,8 +12,8 @@ namespace TMI_practicum
|
|||||||
var intersections = new Stack<Intersection>();
|
var intersections = new Stack<Intersection>();
|
||||||
var events = new PriorityQueue<Event>();
|
var events = new PriorityQueue<Event>();
|
||||||
|
|
||||||
var upperActive = new CircleTree<SegmentKey, Segment>();
|
var upperActive = new CircleTree<SegmentKey, Circle>();
|
||||||
var bottomActive = new CircleTree<SegmentKey, Segment>();
|
var bottomActive = new CircleTree<SegmentKey, Circle>();
|
||||||
|
|
||||||
|
|
||||||
foreach (var circle in circles)
|
foreach (var circle in circles)
|
||||||
@@ -29,17 +29,16 @@ namespace TMI_practicum
|
|||||||
switch (e.Type)
|
switch (e.Type)
|
||||||
{
|
{
|
||||||
case Event.EventType.Start:
|
case Event.EventType.Start:
|
||||||
upperActive.Add(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Upper, hash),
|
upperActive.Add(new SegmentKey(e.X, e.Circle.Y + e.Circle.R, SegmentKey.SegmentType.Upper, hash), e.Circle);
|
||||||
new Segment(Segment.SegmentType.Upper, e.Circle.Y, e.Circle));
|
bottomActive.Add(new SegmentKey(e.X, e.Circle.Y - e.Circle.R, SegmentKey.SegmentType.Bottom, hash),
|
||||||
bottomActive.Add(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Bottom, hash),
|
e.Circle);
|
||||||
new Segment(Segment.SegmentType.Bottom, e.Circle.Y, e.Circle));
|
|
||||||
|
|
||||||
CheckIntersections(upperActive, e, intersections, true);
|
CheckIntersections(upperActive, e, intersections, true);
|
||||||
CheckIntersections(bottomActive, e, intersections, false);
|
CheckIntersections(bottomActive, e, intersections, false);
|
||||||
break;
|
break;
|
||||||
case Event.EventType.End:
|
case Event.EventType.End:
|
||||||
upperActive.Remove(new SegmentKey(e.X, e.Circle.Y, Segment.SegmentType.Upper, 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, Segment.SegmentType.Bottom, hash));
|
bottomActive.Remove(new SegmentKey(e.X, e.Circle.Y - e.Circle.R, SegmentKey.SegmentType.Bottom, hash));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
@@ -50,36 +49,38 @@ namespace TMI_practicum
|
|||||||
return intersections;
|
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
|
try
|
||||||
{
|
{
|
||||||
other = upper
|
other = upper? active.FindSuccessor(new SegmentKey(e.X, e.Circle.Y, SegmentKey.SegmentType.Upper, e.GetHashCode()))
|
||||||
? 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()));
|
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)
|
catch (KeyNotFoundException)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var intersects = e.Circle.FindIntersections(other.Circle);
|
if (other != null)
|
||||||
if (intersects == null) return;
|
{
|
||||||
|
var intersects = e.Circle.FindIntersections(other);
|
||||||
|
if (intersects != null)
|
||||||
|
{
|
||||||
|
|
||||||
foreach (var intersection in intersects)
|
foreach (var intersection in intersects)
|
||||||
{
|
{
|
||||||
if (upper)
|
if (upper && e.Circle.Y == intersection.Y) continue;
|
||||||
{
|
|
||||||
if (intersection.Y < e.Circle.Y) continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (intersection.Y > e.Circle.Y) continue;
|
|
||||||
}
|
|
||||||
intersections.Push(intersection);
|
intersections.Push(intersection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private class CircleTree<TKey, TValue> : SortedDictionary<TKey, TValue>
|
private class CircleTree<TKey, TValue> : SortedDictionary<TKey, TValue>
|
||||||
@@ -106,7 +107,6 @@ namespace TMI_practicum
|
|||||||
public enum EventType
|
public enum EventType
|
||||||
{
|
{
|
||||||
Start,
|
Start,
|
||||||
Intersect,
|
|
||||||
End
|
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 struct SegmentKey : IComparable<SegmentKey>
|
||||||
{
|
{
|
||||||
private readonly double _x;
|
private readonly double _x;
|
||||||
private readonly double _y;
|
private readonly double? _y;
|
||||||
private readonly Segment.SegmentType _type;
|
public double Y => _y ?? double.MinValue;
|
||||||
|
private readonly SegmentType _type;
|
||||||
private readonly int _identifier;
|
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;
|
_y = y;
|
||||||
_type = type;
|
_type = type;
|
||||||
@@ -168,7 +142,7 @@ namespace TMI_practicum
|
|||||||
public int CompareTo(SegmentKey other)
|
public int CompareTo(SegmentKey other)
|
||||||
{
|
{
|
||||||
if (_identifier.Equals(other._identifier)) return _type.CompareTo(other._type);
|
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);
|
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();
|
return _identifier.GetHashCode() ^ _type.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum SegmentType
|
||||||
|
{
|
||||||
|
Bottom,
|
||||||
|
Upper
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static class EnumerableExtensions
|
public static class EnumerableExtensions
|
||||||
|
Reference in New Issue
Block a user