176 lines
3.9 KiB
C#
176 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
|
|||
|
}
|
|||
|
}
|