Boprs/Region.cs
2024-09-01 13:10:19 +02:00

175 lines
3.9 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>
/// Vertices belonging to this polygon.
/// </summary>
private List<SweepVertex> Vertices { get; }
/// <summary>
/// Subdivide my edges, set their inOut tags and validate their non-colinearity.
/// </summary>
private void ValidateEdges()
{
// Lexico-graphically sort my vertices.
Vertices.Sort();
// Sweepline to keep track of edges.
SweepLine sweepLine = new SweepLine();
// Current number of vertices in the list.
// Will be increased if subdivision occurs.
int numVertices = Vertices.Count;
// Go through all the sorted vertices, test for intersections when appropriate and,
// if needed, subdivide the edges.
for (int i = 0; i < numVertices; i++)
{
SweepVertex acVx = Vertices[i];
if (acVx.IsLeft())
{
sweepLine.Add(acVx.Edge, false);
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);
numVertices++;
}
}
if (nextEdge != null)
{
List<SweepVertex> newVertices = acVx.Edge.TrySubdivideBy(nextEdge);
foreach (SweepVertex vertex in newVertices)
{
Utils.InsertVertexSorted(Vertices, vertex);
numVertices++;
}
}
}
else
{
SweepEdge prevEdge = sweepLine.PrevEdge(acVx.Edge);
SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge);
sweepLine.Remove(acVx.Edge);
if (prevEdge != null && nextEdge != null)
{
List<SweepVertex> newVertices = prevEdge.TrySubdivideBy(nextEdge);
foreach (SweepVertex vertex in newVertices)
{
Utils.InsertVertexSorted(Vertices, vertex);
numVertices++;
}
}
}
}
}
/// <summary>
/// Get a copy of the regions vertex list.
/// </summary>
/// <returns>Copy of the regions vertex list.</returns>
internal List<LineSegment2d> GetSegments()
{
List <LineSegment2d> segments = new List<LineSegment2d>();
foreach(SweepVertex sweepVertex in Vertices)
{
if (sweepVertex.IsLeft())
{
segments.Add(
new LineSegment2d(sweepVertex.Edge.LeftVertex.Point, sweepVertex.Edge.RightVertex.Point));
}
}
return segments;
}
/// <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();
foreach(LineSegment2d segment in segments)
{
SweepEdge newEdge = new SweepEdge(segment.StartPoint, segment.EndPoint);
region.Vertices.Add(newEdge.LeftVertex);
region.Vertices.Add(newEdge.RightVertex);
newEdge.ParentRegion = region;
}
region.ValidateEdges();
return region;
}
/// <summary>
/// Constructor.
/// </summary>
private Region()
{
Vertices = new List<SweepVertex>();
}
#if DEBUG
internal void Draw()
{
Erase();
foreach (SweepVertex vert in Vertices)
{
if (vert.IsLeft())
{
vert.Edge.Draw();
}
}
}
internal void Erase()
{
foreach (SweepVertex vert in Vertices)
{
if (vert.IsLeft())
{
vert.Edge.Erase();
}
}
}
#endif
}
}