Boprs/Region.cs

159 lines
3.6 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>
/// Geometric region used for boolean operations calculations.
/// </summary>
public class Region
{
/// <summary>
/// Edges belonging to this polygon.
/// </summary>
private List<SweepEdge> Edges { get; set; }
/// <summary>
/// Subdivide my edges, set their inOut tags and validate their non-colinearity.
/// </summary>
private void SetEdges(List<SweepVertex> vertices)
{
// Lexico-graphically sort my vertices.
vertices.Sort();
// Sweepline to keep track of edges.
SweepLine sweepLine = new SweepLine();
// Processed edges will be moved here.
List<SweepEdge> processed = new List<SweepEdge>();
// Go through all the sorted vertices, test for intersections when appropriate and,
// if needed, subdivide the edges.
while (vertices.Count != 0)
{
SweepVertex acVx = vertices[0];
vertices.RemoveAt(0);
if (acVx.IsLeft())
{
sweepLine.Add(acVx.Edge, true);
SweepEdge prevEdge = sweepLine.PrevEdge(acVx.Edge);
SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge);
acVx.Edge.SetTransitionInside(prevEdge);
if (prevEdge != null)
{
List<SweepVertex> newVertices = acVx.Edge.TrySubdivideBy(prevEdge);
foreach (SweepVertex vertex in newVertices)
{
Utils.InsertVertexSorted(vertices, vertex);
}
}
if (nextEdge != null)
{
List<SweepVertex> newVertices = acVx.Edge.TrySubdivideBy(nextEdge);
foreach (SweepVertex vertex in newVertices)
{
Utils.InsertVertexSorted(vertices, vertex);
}
}
}
else
{
SweepEdge prevEdge = sweepLine.PrevEdge(acVx.Edge);
SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge);
sweepLine.Remove(acVx.Edge);
processed.Add(acVx.Edge);
if (prevEdge != null && nextEdge != null)
{
List<SweepVertex> newVertices = prevEdge.TrySubdivideBy(nextEdge);
foreach (SweepVertex vertex in newVertices)
{
Utils.InsertVertexSorted(vertices, vertex);
}
}
}
}
Edges = processed;
}
/// <summary>
/// Get a copy of the regions edges list.
/// </summary>
/// <returns>Copy of the regions edges list.</returns>
internal List<SweepEdge> GetEdgeCopies()
{
List<SweepEdge> copies = new List<SweepEdge>();
foreach (SweepEdge edge in Edges)
{
copies.Add((SweepEdge)edge.Clone());
}
return copies;
}
/// <summary>
/// Instantiate a region with edges defined by a list of given line segments.
/// </summary>
/// <param name="segments"></param>
/// <returns></returns>
public static Region FromSegments(List<LineSegment2d> segments)
{
Region region = new Region();
List<SweepVertex> vertices = new List<SweepVertex>();
foreach(LineSegment2d segment in segments)
{
SweepEdge newEdge = new SweepEdge(segment.StartPoint, segment.EndPoint);
vertices.Add(newEdge.LeftVertex);
vertices.Add(newEdge.RightVertex);
newEdge.ParentRegion = region;
}
region.SetEdges(vertices);
return region;
}
#if DEBUG
internal void Draw()
{
Erase();
foreach (SweepEdge edge in Edges)
{
edge.Draw();
}
}
internal void Erase()
{
foreach (SweepEdge edge in Edges)
{
edge.Erase();
}
}
#endif
}
}