Boprs/SweepLine.cs

129 lines
3.4 KiB
C#
Raw Normal View History

2024-09-01 13:10:19 +02:00
#if ACAD24
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Colors;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
#elif BCAD
using Bricscad.EditorInput;
using Teigha.Geometry;
using Teigha.DatabaseServices;
using Teigha.Colors;
#endif
using System;
using System.Collections.Generic;
namespace Boprs
{
/// <summary>
/// Line to sweep through sorted vertices, keeps track of currently intersecting edges.
/// </summary>
internal class SweepLine
{
/// <summary>
/// Edges the line is currently intersecting.
/// </summary>
/// TODO: Change this into a BST when optimizing.
private List<SweepEdge> IntersectingEdges { get; }
/// <summary>
/// Start tracking an edge identified by its left vertex.
/// </summary>
/// <param name="edge">Edge to start tracking.</param>
/// <param name="allowCollinearity">
/// If <c>false</c> and the edge is collinear with one of the edges in the sweep line,
/// an exception will get thrown.
/// </param>
internal void Add(SweepEdge edge, bool allowCollinearity)
{
int i = 0;
if (IntersectingEdges.Contains(edge))
{
throw new Exception("inserting contained edge");
}
// Go through all the edges, find my index for insertion.
for(; i < IntersectingEdges.Count; i++)
{
int comparison = edge.CompareTo(IntersectingEdges[i], edge.LeftVertex.Point.X);
// If we are below the current edge, that is the correct index.
if (comparison < 0)
{
break;
}
// If edges are collinear and it is not allowed, throw an exception
else if(!allowCollinearity && comparison == 0)
{
throw new Exception($"Collinear edges detected. [{edge} & {IntersectingEdges[i]}]");
}
// If we are above the last edge, set inserttion index after it.
else if (i == IntersectingEdges.Count)
{
i++;
}
}
// Insert the edge to the correct place.
IntersectingEdges.Insert(i, edge);
}
/// <summary>
/// Remove an edge from being tracked by the sweep line.
/// </summary>
/// <param name="edge">Edge to remove.</param>
internal void Remove(SweepEdge edge)
{
IntersectingEdges.Remove(edge);
}
/// <summary>
/// Returns the edge below curr, or null if curr is the lowest.
/// </summary>
/// <param name="curr">Current edge.</param>
/// <returns>Edge below curr, or null.</returns>
internal SweepEdge PrevEdge(SweepEdge curr)
{
// Get the index of the current edge
int currIdx = IntersectingEdges.IndexOf(curr);
// If the current edge isn't the lowest, return the edge below it.
if(currIdx != 0)
{
return IntersectingEdges[currIdx - 1];
}
// Otherwise return null.
return null;
}
/// <summary>
/// Returns the edge above curr, or null if curr is the highest.
/// </summary>
/// <param name="curr">Current edge.</param>
/// <returns>Edge above curr, or null.</returns>
internal SweepEdge NextEdge(SweepEdge curr)
{
// Get the index of the current edge
int currIdx = IntersectingEdges.IndexOf(curr);
// If the current edge isn't the highest, return the edge above it.
if (currIdx != IntersectingEdges.Count - 1)
{
return IntersectingEdges[currIdx + 1];
}
// Otherwise return null.
return null;
}
/// <summary>
/// Constructor.
/// </summary>
internal SweepLine()
{
IntersectingEdges = new List<SweepEdge>();
}
}
}