Compute closed contours.

This commit is contained in:
borovec zdenek 2024-09-04 09:04:07 +02:00
parent 9719a7b549
commit 1a91a64b2d
5 changed files with 216 additions and 12 deletions

View file

@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;ACAD24</DefineConstants>
<DefineConstants>TRACE;DEBUG;BCAD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
@ -41,6 +41,9 @@
<Reference Include="acmgd">
<HintPath>..\..\..\..\..\Program Files\Autodesk\AutoCAD 2024\acmgd.dll</HintPath>
</Reference>
<Reference Include="BrxMgd">
<HintPath>..\..\..\..\..\Program Files\Bricsys\BricsCAD V24 en_US\BrxMgd.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
@ -49,10 +52,14 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="TD_Mgd">
<HintPath>..\..\..\..\..\Program Files\Bricsys\BricsCAD V24 en_US\TD_Mgd.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BooleanOperation.cs" />
<Compile Include="Commands.cs" />
<Compile Include="Contour.cs" />
<Compile Include="Region.cs" />
<Compile Include="SweepEdge.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View file

@ -55,6 +55,8 @@ namespace Boprs
segs.Add(new LineSegment2d(asLine.StartPoint.To2d(), asLine.EndPoint.To2d()));
}
}
asPoly.Erase();
}
acTrans.Commit();
}

84
Contour.cs Normal file
View 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
View file

@ -25,6 +25,8 @@ namespace Boprs
/// </summary>
private List<SweepEdge> Edges { get; set; }
private List<Contour> Contours { get; set; }
/// <summary>
/// Subdivide my edges, set their inOut tags and validate their non-colinearity.
/// </summary>
@ -97,6 +99,105 @@ namespace Boprs
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>
/// Get a copy of the regions edges list.
/// </summary>
@ -113,6 +214,15 @@ namespace Boprs
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>
/// Instantiate a region with edges defined by a list of given line segments.
/// </summary>
@ -133,6 +243,7 @@ namespace Boprs
}
region.SetEdges(vertices);
region.ComputeContours();
return region;
}
@ -140,18 +251,9 @@ namespace Boprs
#if DEBUG
internal void Draw()
{
Erase();
foreach (SweepEdge edge in Edges)
foreach (Contour contour in Contours)
{
edge.Draw();
}
}
internal void Erase()
{
foreach (SweepEdge edge in Edges)
{
edge.Erase();
contour.Draw();
}
}
#endif

View file

@ -119,6 +119,15 @@ namespace Boprs
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>
/// Constructor.
/// </summary>