129 lines
3.4 KiB
C#
129 lines
3.4 KiB
C#
|
#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>();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|