1
0

update sweeplineff

This commit is contained in:
2019-05-18 19:47:28 +02:00
parent ec65d0d925
commit ba2c421e21
2 changed files with 38 additions and 58 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

@@ -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,34 +49,36 @@ 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;
foreach (var intersection in intersects)
{ {
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 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