159 lines
3.6 KiB
C#
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
|
|
}
|
|
}
|