83 lines
2.5 KiB
C#
83 lines
2.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Medallion.Collections;
|
|
|
|
namespace TMI_practicum
|
|
{
|
|
public static class SweepLineAlgorithm
|
|
{
|
|
public static IEnumerable<Intersection> Solve(IList<Circle> circles)
|
|
{
|
|
var events = new PriorityQueue<Event>();
|
|
var intersections = new HashSet<Intersection>();
|
|
var active = new List<Circle>();
|
|
|
|
foreach (var circle in circles)
|
|
{
|
|
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 intersections;
|
|
}
|
|
|
|
private static void CheckIntersections(IEnumerable<Circle> active, Circle circle, HashSet<Intersection> intersections)
|
|
{
|
|
foreach (var otherCircle in active)
|
|
{
|
|
if (circle.Equals(otherCircle)) continue;
|
|
|
|
var intersects = circle.FindIntersections(otherCircle);
|
|
if (intersects == null) continue;
|
|
|
|
foreach (var intersection in intersects)
|
|
{
|
|
intersections.Add(intersection);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private struct Event : IComparable<Event>
|
|
{
|
|
public EventType Type { get; }
|
|
public Circle Circle { get; }
|
|
public double X { get; }
|
|
|
|
public enum EventType
|
|
{
|
|
Start,
|
|
End
|
|
}
|
|
|
|
public Event(EventType type, double x, Circle circle)
|
|
{
|
|
Type = type;
|
|
X = x;
|
|
Circle = circle;
|
|
}
|
|
|
|
public int CompareTo(Event other)
|
|
{
|
|
return X.CompareTo(other.X);
|
|
}
|
|
}
|
|
}
|
|
} |