Compute closed contours.
This commit is contained in:
parent
9719a7b549
commit
1a91a64b2d
5 changed files with 216 additions and 12 deletions
|
@ -18,7 +18,7 @@
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>TRACE;DEBUG;ACAD24</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;BCAD</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -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 V24 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,10 +52,14 @@
|
||||||
<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 V24 en_US\TD_Mgd.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BooleanOperation.cs" />
|
<Compile Include="BooleanOperation.cs" />
|
||||||
<Compile Include="Commands.cs" />
|
<Compile Include="Commands.cs" />
|
||||||
|
<Compile Include="Contour.cs" />
|
||||||
<Compile Include="Region.cs" />
|
<Compile Include="Region.cs" />
|
||||||
<Compile Include="SweepEdge.cs" />
|
<Compile Include="SweepEdge.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|
|
@ -55,6 +55,8 @@ namespace Boprs
|
||||||
segs.Add(new LineSegment2d(asLine.StartPoint.To2d(), asLine.EndPoint.To2d()));
|
segs.Add(new LineSegment2d(asLine.StartPoint.To2d(), asLine.EndPoint.To2d()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asPoly.Erase();
|
||||||
}
|
}
|
||||||
acTrans.Commit();
|
acTrans.Commit();
|
||||||
}
|
}
|
||||||
|
|
84
Contour.cs
Normal file
84
Contour.cs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#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;
|
||||||
|
using AcAp = Bricscad.ApplicationServices;
|
||||||
|
#endif
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Boprs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple closed polygon.
|
||||||
|
/// </summary>
|
||||||
|
public class Contour
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Parent of this contour, null if external.
|
||||||
|
/// </summary>
|
||||||
|
public Contour Parent { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertices of the contour.
|
||||||
|
/// </summary>
|
||||||
|
public List<Point2d> Vertices { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Are the vertices of the contour arranged in clockwise manner?
|
||||||
|
/// </summary>
|
||||||
|
/// <returns><c>true</c> if the contour is clockwise, <c>false</c> if counter-clockwise.</returns>
|
||||||
|
public bool IsClockwise()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reverse the orientation of the contour.
|
||||||
|
/// </summary>
|
||||||
|
public void Reverse()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public Contour()
|
||||||
|
{
|
||||||
|
Vertices = new List<Point2d>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
internal void Draw(Color color = null)
|
||||||
|
{
|
||||||
|
AcAp.Document acDoc = AcAp.Application.DocumentManager.MdiActiveDocument;
|
||||||
|
Database acDb = acDoc.Database;
|
||||||
|
|
||||||
|
using (Transaction acTrans = acDb.TransactionManager.StartTransaction())
|
||||||
|
{
|
||||||
|
// Open the BlockTableRecord
|
||||||
|
BlockTable acBlkTbl = (BlockTable)acTrans.GetObject(acDb.BlockTableId, OpenMode.ForRead);
|
||||||
|
BlockTableRecord acBlkTblRec =
|
||||||
|
(BlockTableRecord)acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
|
||||||
|
|
||||||
|
for(int i = 0; i < Vertices.Count; i++)
|
||||||
|
{
|
||||||
|
Line asLine = new Line(Vertices[i].To3d(), Vertices[(i + 1) % Vertices.Count].To3d());
|
||||||
|
acBlkTblRec.AppendEntity(asLine);
|
||||||
|
acTrans.AddNewlyCreatedDBObject(asLine, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
acTrans.Commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
124
Region.cs
124
Region.cs
|
@ -25,6 +25,8 @@ namespace Boprs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<SweepEdge> Edges { get; set; }
|
private List<SweepEdge> Edges { get; set; }
|
||||||
|
|
||||||
|
private List<Contour> Contours { get; set; }
|
||||||
|
|
||||||
/// <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>
|
||||||
|
@ -97,6 +99,105 @@ namespace Boprs
|
||||||
Edges = processed;
|
Edges = processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find the index of an un-processed vertex with the same position as the one on specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos">Index of the current vertex.</param>
|
||||||
|
/// <param name="vertices">List of vertices.</param>
|
||||||
|
/// <param name="processed">Mask for processed vertices.</param>
|
||||||
|
/// <returns>Index of an unprocessed neighbour with the same position.</returns>
|
||||||
|
private int NextPos(int pos, List<SweepVertex> vertices, bool[] processed)
|
||||||
|
{
|
||||||
|
int newPos = pos + 1;
|
||||||
|
while(newPos < vertices.Count && Utils.DoubleEquals(vertices[pos].Point.GetDistanceTo(vertices[newPos].Point), 0))
|
||||||
|
{
|
||||||
|
if (!processed[newPos])
|
||||||
|
{
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newPos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newPos = pos - 1;
|
||||||
|
while (newPos >= 0 && Utils.DoubleEquals(vertices[pos].Point.GetDistanceTo(vertices[newPos].Point), 0))
|
||||||
|
{
|
||||||
|
if (!processed[newPos])
|
||||||
|
{
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newPos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception("Hit contour dead end (non-connected edge).");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute my closed contours.
|
||||||
|
/// </summary>
|
||||||
|
private void ComputeContours()
|
||||||
|
{
|
||||||
|
// Gather all vertices of the region.
|
||||||
|
List<SweepVertex> vertices = new List<SweepVertex>();
|
||||||
|
foreach (SweepEdge edge in Edges)
|
||||||
|
{
|
||||||
|
vertices.Add(edge.LeftVertex);
|
||||||
|
vertices.Add(edge.RightVertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lexico-graphically sort the vertices.
|
||||||
|
vertices.Sort();
|
||||||
|
|
||||||
|
// Sweepline to keep track of edges.
|
||||||
|
SweepLine sweepLine = new SweepLine();
|
||||||
|
|
||||||
|
bool[] processed = new bool[vertices.Count];
|
||||||
|
List<Contour> contours = new List<Contour>();
|
||||||
|
|
||||||
|
for(int i = 0; i < vertices.Count; i++)
|
||||||
|
{
|
||||||
|
SweepVertex acVx = vertices[i];
|
||||||
|
|
||||||
|
if (acVx.IsLeft())
|
||||||
|
{
|
||||||
|
sweepLine.Add(acVx.Edge, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sweepLine.Remove(acVx.Edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed[i])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
processed[i] = true;
|
||||||
|
|
||||||
|
// We should be guaranteed to always hit left endpoint leading us on a counter clockwise path.
|
||||||
|
Contour contour = new Contour();
|
||||||
|
contours.Add(contour);
|
||||||
|
|
||||||
|
Point2d target = acVx.Point;
|
||||||
|
|
||||||
|
int pos = i;
|
||||||
|
while (!Utils.DoubleEquals(vertices[pos].OtherVertex().Point.GetDistanceTo(target), 0))
|
||||||
|
{
|
||||||
|
int otherPos = vertices.IndexOf(vertices[pos].OtherVertex());
|
||||||
|
pos = NextPos(otherPos, vertices, processed);
|
||||||
|
|
||||||
|
contour.Vertices.Add(vertices[pos].Point);
|
||||||
|
processed[pos] = true;
|
||||||
|
|
||||||
|
processed[otherPos] = true;
|
||||||
|
}
|
||||||
|
processed[vertices.IndexOf(vertices[pos].OtherVertex())] = true;
|
||||||
|
}
|
||||||
|
Contours = contours;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a copy of the regions edges list.
|
/// Get a copy of the regions edges list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -113,6 +214,15 @@ namespace Boprs
|
||||||
return copies;
|
return copies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a copy of the contours of the polygon.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>List of copies of the regions contours.</returns>
|
||||||
|
public List<Contour> GetContourCopies()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiate a region with edges defined by a list of given line segments.
|
/// Instantiate a region with edges defined by a list of given line segments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -133,6 +243,7 @@ namespace Boprs
|
||||||
}
|
}
|
||||||
|
|
||||||
region.SetEdges(vertices);
|
region.SetEdges(vertices);
|
||||||
|
region.ComputeContours();
|
||||||
|
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
@ -140,18 +251,9 @@ namespace Boprs
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
internal void Draw()
|
internal void Draw()
|
||||||
{
|
{
|
||||||
Erase();
|
foreach (Contour contour in Contours)
|
||||||
|
|
||||||
foreach (SweepEdge edge in Edges)
|
|
||||||
{
|
{
|
||||||
edge.Draw();
|
contour.Draw();
|
||||||
}
|
|
||||||
}
|
|
||||||
internal void Erase()
|
|
||||||
{
|
|
||||||
foreach (SweepEdge edge in Edges)
|
|
||||||
{
|
|
||||||
edge.Erase();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -119,6 +119,15 @@ namespace Boprs
|
||||||
return this == Edge.LeftVertex;
|
return this == Edge.LeftVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the other vertex associated with my edge.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Other vertex of my edge.</returns>
|
||||||
|
internal SweepVertex OtherVertex()
|
||||||
|
{
|
||||||
|
return IsLeft() ? Edge.RightVertex : Edge.LeftVertex;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue