Compare commits

..

No commits in common. "9719a7b549a9977f1862f620231372e83e7cc8d8" and "0431c3ca2eaf20d085e55c794b8ed4b9bf87cf0d" have entirely different histories.

7 changed files with 71 additions and 64 deletions

View file

@ -190,22 +190,26 @@ namespace Boprs
public BooleanOperation(Region subject, Region clip, BoprType type) public BooleanOperation(Region subject, Region clip, BoprType type)
{ {
List<SweepVertex> sortedVerts = new List<SweepVertex>(); List<SweepVertex> sortedVerts = new List<SweepVertex>();
foreach (SweepEdge edge in subject.GetEdgeCopies()) foreach (LineSegment2d seg in subject.GetSegments())
{ {
SweepEdge edge = new SweepEdge(seg.StartPoint, seg.EndPoint);
sortedVerts.Add(edge.LeftVertex); sortedVerts.Add(edge.LeftVertex);
sortedVerts.Add(edge.RightVertex); sortedVerts.Add(edge.RightVertex);
} }
foreach (SweepEdge edge in clip.GetEdgeCopies()) foreach (LineSegment2d seg in clip.GetSegments())
{ {
SweepEdge edge = new SweepEdge(seg.StartPoint, seg.EndPoint);
sortedVerts.Add(edge.LeftVertex); sortedVerts.Add(edge.LeftVertex);
sortedVerts.Add(edge.RightVertex); sortedVerts.Add(edge.RightVertex);
} }
sortedVerts.Sort(); sortedVerts.Sort();
List<SweepEdge> processed = ProcessEdges(sortedVerts); List<SweepEdge> processed = ProcessEdges(sortedVerts);
Result = BuildResult(processed, subject, type); Result = BuildResult(processed, subject, type);
} }
} }

View file

@ -41,6 +41,9 @@
<Reference Include="acmgd"> <Reference Include="acmgd">
<HintPath>..\..\..\..\..\Program Files\Autodesk\AutoCAD 2024\acmgd.dll</HintPath> <HintPath>..\..\..\..\..\Program Files\Autodesk\AutoCAD 2024\acmgd.dll</HintPath>
</Reference> </Reference>
<Reference Include="BrxMgd">
<HintPath>..\..\..\..\..\Program Files\Bricsys\BricsCAD V23 en_US\BrxMgd.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
@ -49,6 +52,9 @@
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="TD_Mgd">
<HintPath>..\..\..\..\..\Program Files\Bricsys\BricsCAD V23 en_US\TD_Mgd.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BooleanOperation.cs" /> <Compile Include="BooleanOperation.cs" />

View file

@ -96,7 +96,7 @@ namespace Boprs
AcAp.Document acDoc = AcAp.Application.DocumentManager.MdiActiveDocument; AcAp.Document acDoc = AcAp.Application.DocumentManager.MdiActiveDocument;
Region subject = UserCreateRegion("Enter polylines for first polygon:"); Region subject = UserCreateRegion("Enter polylines for first polygon:");
Region clip = UserCreateRegion("Enter polylines for second polygon:"); Region clip = UserCreateRegion("Enter polylines for second polygon:");
if(subject == null || clip == null) if(subject == null || clip == null)
@ -106,7 +106,7 @@ namespace Boprs
} }
BoprType type = UserChooseBoprType(); BoprType type = UserChooseBoprType();
BooleanOperation bopr = new BooleanOperation(subject, clip, type); BooleanOperation bopr = new BooleanOperation(subject, clip, type);
bopr.Result.Draw(); bopr.Result.Draw();

View file

@ -8,9 +8,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Boprs")] [assembly: AssemblyTitle("Boprs")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("DEK")]
[assembly: AssemblyProduct("Boprs")] [assembly: AssemblyProduct("Boprs")]
[assembly: AssemblyCopyright("")] [assembly: AssemblyCopyright("Copyright © DEK 2024")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.1.0")] [assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -21,34 +21,34 @@ namespace Boprs
public class Region public class Region
{ {
/// <summary> /// <summary>
/// Edges belonging to this polygon. /// Vertices belonging to this polygon.
/// </summary> /// </summary>
private List<SweepEdge> Edges { get; set; } private List<SweepVertex> Vertices { get; }
/// <summary> /// <summary>
/// Subdivide my edges, set their inOut tags and validate their non-colinearity. /// Subdivide my edges, set their inOut tags and validate their non-colinearity.
/// </summary> /// </summary>
private void SetEdges(List<SweepVertex> vertices) private void ValidateEdges()
{ {
// Lexico-graphically sort my vertices. // Lexico-graphically sort my vertices.
vertices.Sort(); Vertices.Sort();
// Sweepline to keep track of edges. // Sweepline to keep track of edges.
SweepLine sweepLine = new SweepLine(); SweepLine sweepLine = new SweepLine();
// Processed edges will be moved here. // Current number of vertices in the list.
List<SweepEdge> processed = new List<SweepEdge>(); // Will be increased if subdivision occurs.
int numVertices = Vertices.Count;
// Go through all the sorted vertices, test for intersections when appropriate and, // Go through all the sorted vertices, test for intersections when appropriate and,
// if needed, subdivide the edges. // if needed, subdivide the edges.
while (vertices.Count != 0) for (int i = 0; i < numVertices; i++)
{ {
SweepVertex acVx = vertices[0]; SweepVertex acVx = Vertices[i];
vertices.RemoveAt(0);
if (acVx.IsLeft()) if (acVx.IsLeft())
{ {
sweepLine.Add(acVx.Edge, true); sweepLine.Add(acVx.Edge, false);
SweepEdge prevEdge = sweepLine.PrevEdge(acVx.Edge); SweepEdge prevEdge = sweepLine.PrevEdge(acVx.Edge);
SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge); SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge);
@ -61,7 +61,8 @@ namespace Boprs
foreach (SweepVertex vertex in newVertices) foreach (SweepVertex vertex in newVertices)
{ {
Utils.InsertVertexSorted(vertices, vertex); Utils.InsertVertexSorted(Vertices, vertex);
numVertices++;
} }
} }
if (nextEdge != null) if (nextEdge != null)
@ -70,7 +71,8 @@ namespace Boprs
foreach (SweepVertex vertex in newVertices) foreach (SweepVertex vertex in newVertices)
{ {
Utils.InsertVertexSorted(vertices, vertex); Utils.InsertVertexSorted(Vertices, vertex);
numVertices++;
} }
} }
} }
@ -80,7 +82,6 @@ namespace Boprs
SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge); SweepEdge nextEdge = sweepLine.NextEdge(acVx.Edge);
sweepLine.Remove(acVx.Edge); sweepLine.Remove(acVx.Edge);
processed.Add(acVx.Edge);
if (prevEdge != null && nextEdge != null) if (prevEdge != null && nextEdge != null)
{ {
@ -88,29 +89,32 @@ namespace Boprs
foreach (SweepVertex vertex in newVertices) foreach (SweepVertex vertex in newVertices)
{ {
Utils.InsertVertexSorted(vertices, vertex); Utils.InsertVertexSorted(Vertices, vertex);
numVertices++;
} }
} }
} }
} }
Edges = processed;
} }
/// <summary> /// <summary>
/// Get a copy of the regions edges list. /// Get a copy of the regions vertex list.
/// </summary> /// </summary>
/// <returns>Copy of the regions edges list.</returns> /// <returns>Copy of the regions vertex list.</returns>
internal List<SweepEdge> GetEdgeCopies() internal List<LineSegment2d> GetSegments()
{ {
List<SweepEdge> copies = new List<SweepEdge>(); List <LineSegment2d> segments = new List<LineSegment2d>();
foreach (SweepEdge edge in Edges) foreach(SweepVertex sweepVertex in Vertices)
{ {
copies.Add((SweepEdge)edge.Clone()); if (sweepVertex.IsLeft())
{
segments.Add(
new LineSegment2d(sweepVertex.Edge.LeftVertex.Point, sweepVertex.Edge.RightVertex.Point));
}
} }
return copies; return segments;
} }
/// <summary> /// <summary>
@ -122,36 +126,48 @@ namespace Boprs
{ {
Region region = new Region(); Region region = new Region();
List<SweepVertex> vertices = new List<SweepVertex>();
foreach(LineSegment2d segment in segments) foreach(LineSegment2d segment in segments)
{ {
SweepEdge newEdge = new SweepEdge(segment.StartPoint, segment.EndPoint); SweepEdge newEdge = new SweepEdge(segment.StartPoint, segment.EndPoint);
vertices.Add(newEdge.LeftVertex); region.Vertices.Add(newEdge.LeftVertex);
vertices.Add(newEdge.RightVertex); region.Vertices.Add(newEdge.RightVertex);
newEdge.ParentRegion = region; newEdge.ParentRegion = region;
} }
region.SetEdges(vertices); region.ValidateEdges();
return region; return region;
} }
/// <summary>
/// Constructor.
/// </summary>
private Region()
{
Vertices = new List<SweepVertex>();
}
#if DEBUG #if DEBUG
internal void Draw() internal void Draw()
{ {
Erase(); Erase();
foreach (SweepEdge edge in Edges) foreach (SweepVertex vert in Vertices)
{ {
edge.Draw(); if (vert.IsLeft())
{
vert.Edge.Draw();
}
} }
} }
internal void Erase() internal void Erase()
{ {
foreach (SweepEdge edge in Edges) foreach (SweepVertex vert in Vertices)
{ {
edge.Erase(); if (vert.IsLeft())
{
vert.Edge.Erase();
}
} }
} }
#endif #endif

View file

@ -44,7 +44,7 @@ namespace Boprs
/// <summary> /// <summary>
/// Line segment (edge) used while a sweep line is processing a boolean operation. /// Line segment (edge) used while a sweep line is processing a boolean operation.
/// </summary> /// </summary>
internal class SweepEdge : ICloneable internal class SweepEdge
{ {
/// <summary> /// <summary>
/// String representation of the edge. /// String representation of the edge.
@ -54,20 +54,6 @@ namespace Boprs
return ($"({LeftVertex} -- {RightVertex})"); return ($"({LeftVertex} -- {RightVertex})");
} }
public object Clone()
{
SweepVertex left = (SweepVertex)LeftVertex.Clone();
SweepVertex right = (SweepVertex)RightVertex.Clone();
SweepEdge clone = new SweepEdge(LeftVertex, RightVertex)
{
TransitionInside = TransitionInside,
InsideOther = InsideOther,
Type = Type,
ParentRegion = ParentRegion,
};
return clone;
}
/// <summary> /// <summary>
/// Comparison of edges. /// Comparison of edges.
/// </summary> /// </summary>

View file

@ -18,7 +18,7 @@ namespace Boprs
/// <summary> /// <summary>
/// End point of an edge used while sweep line is processing a boolean operation. /// End point of an edge used while sweep line is processing a boolean operation.
/// </summary> /// </summary>
internal class SweepVertex : IComparable, ICloneable internal class SweepVertex : IComparable
{ {
/// <summary> /// <summary>
/// String representation of the vertex. /// String representation of the vertex.
@ -28,11 +28,6 @@ namespace Boprs
return ($"({Point.X}, {Point.Y})"); return ($"({Point.X}, {Point.Y})");
} }
public object Clone()
{
return new SweepVertex(Point) { Edge = Edge};
}
/// <summary> /// <summary>
/// Comparison of vertices. /// Comparison of vertices.
/// </summary> /// </summary>