#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 { /// /// Geometric region used for boolean operations calculations. /// public class Region { /// /// Vertices belonging to this polygon. /// private List Vertices { get; } /// /// Subdivide my edges, set their inOut tags and validate their non-colinearity. /// 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 newVertices = acVx.Edge.TrySubdivideBy(prevEdge); foreach (SweepVertex vertex in newVertices) { Utils.InsertVertexSorted(Vertices, vertex); numVertices++; } } if (nextEdge != null) { List 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 newVertices = prevEdge.TrySubdivideBy(nextEdge); foreach (SweepVertex vertex in newVertices) { Utils.InsertVertexSorted(Vertices, vertex); numVertices++; } } } } } /// /// Get a copy of the regions vertex list. /// /// Copy of the regions vertex list. internal List GetSegments() { List segments = new List(); foreach(SweepVertex sweepVertex in Vertices) { if (sweepVertex.IsLeft()) { segments.Add( new LineSegment2d(sweepVertex.Edge.LeftVertex.Point, sweepVertex.Edge.RightVertex.Point)); } } return segments; } /// /// Instantiate a region with edges defined by a list of given line segments. /// /// /// public static Region FromSegments(List 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; } /// /// Constructor. /// private Region() { Vertices = new List(); } #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 } }