Add Region.Area

This commit is contained in:
Zdenek Borovec 2024-09-21 23:13:05 +02:00
parent dff02947c8
commit 2e57f41125
4 changed files with 60 additions and 24 deletions

View file

@ -117,6 +117,8 @@ namespace Boprs
{
contour.Draw();
}
acDoc.Editor.WriteMessage($"\nResult area: {bopr.Result.Area}");
}
}
}

View file

@ -23,19 +23,29 @@ namespace Boprs
{
public object Clone()
{
return new Contour() { Vertices = new List<Point2d>(Vertices) };
return new Contour(new List<Point2d>(Vertices));
}
/// <summary>
/// Vertices of the contour.
/// </summary>
public List<Point2d> Vertices { get; private set; }
private List<Point2d> Vertices { get; }
/// <summary>
/// Signed area of the contour.
/// </summary>
public double SignedArea { get; private set; }
/// <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()
public bool IsClockwise { get => SignedArea < 0; }
/// <summary>
/// Compute the signed area of the contour
/// </summary>
private void ComputeArea()
{
double areaSum = 0;
@ -49,27 +59,31 @@ namespace Boprs
Point2d p1 = Vertices[(i + 1) % Vertices.Count];
// Compute the area under the trapezoid made by the current segment.
// Note that this is actually double the proper value, but we only care about its relation to 0.
// Note that this is actually double the proper value.
areaSum += (p1.X - p0.X) * (p1.Y + p0.Y);
}
return areaSum > 0;
// The above algorithm deems clockwise area to be positive,
// however we consider ccw contours to be positive, so we flip the value.
SignedArea = - areaSum / 2;
}
/// <summary>
/// Reverse the orientation of the contour.
/// </summary>
public void Reverse()
internal void Reverse()
{
Vertices.Reverse();
SignedArea *= -1;
}
/// <summary>
/// Constructor.
/// </summary>
public Contour()
public Contour(List<Point2d> vertices)
{
Vertices = new List<Point2d>();
Vertices = vertices;
ComputeArea();
}
#if DEBUG
@ -88,6 +102,7 @@ namespace Boprs
for(int i = 0; i < Vertices.Count; i++)
{
Line asLine = new Line(Vertices[i].To3d(), Vertices[(i + 1) % Vertices.Count].To3d());
asLine.Color = IsClockwise ? Color.FromRgb(255, 32, 32) : Color.FromRgb(32, 255, 32);
acBlkTblRec.AppendEntity(asLine);
acTrans.AddNewlyCreatedDBObject(asLine, true);
}

View file

@ -25,8 +25,16 @@ namespace Boprs
/// </summary>
private List<SweepEdge> Edges { get; set; }
/// <summary>
/// Contours making up the region.
/// </summary>
private List<Contour> Contours { get; set; }
/// <summary>
/// Area of the positive part of the region (holes subtracted).
/// </summary>
public double Area { get; private set; }
/// <summary>
/// Subdivide my edges, set their inOut tags and validate their non-colinearity.
/// </summary>
@ -163,8 +171,6 @@ namespace Boprs
}
// Otherwise this is an edge on an indiscovered contour, create it.
Contour contour = new Contour();
contours.Add(contour);
// acVx should be guaranteed to be the lowest and leftest vertex of the new polygon.
// Thus it cannot be vertical.
@ -178,8 +184,7 @@ namespace Boprs
int pos = i;
processed[i] = true;
Point2d target = acVx.Point;
contour.Vertices.Add(vertices[pos].Point);
acVx.Edge.ParentContour = contour;
List<Point2d> contourVertices = new List<Point2d>() { vertices[pos].Point };
while (!Utils.DoubleEquals(vertices[pos].OtherVertex().Point.GetDistanceTo(target), 0))
{
int otherPos = vertices.IndexOf(vertices[pos].OtherVertex());
@ -188,13 +193,16 @@ namespace Boprs
processed[pos] = true;
processed[otherPos] = true;
vertices[pos].Edge.ParentContour = contour;
contour.Vertices.Add(vertices[pos].Point);
contourVertices.Add(vertices[pos].Point);
}
processed[vertices.IndexOf(vertices[pos].OtherVertex())] = true;
// Instantiate the contour object from the found vertices.
Contour contour = new Contour(contourVertices);
contours.Add(contour);
// If the contour is a hole and winds ccw, or positive and winds cw, flip it.
if (shouldBeCW != contour.IsClockwise())
if (shouldBeCW != contour.IsClockwise)
{
contour.Reverse();
}
@ -202,6 +210,21 @@ namespace Boprs
Contours = contours;
}
/// <summary>
/// Compute the area of the region.
/// </summary>
/// <remarks>
/// Requires contours to be computed.
/// </remarks>
private void ComputeArea()
{
Area = 0;
foreach(Contour contour in Contours)
{
Area += contour.SignedArea;
}
}
/// <summary>
/// Get a copy of the regions edges list.
/// </summary>
@ -255,6 +278,7 @@ namespace Boprs
region.SetEdges(vertices);
region.ComputeContours();
region.ComputeArea();
return region;
}

View file

@ -137,11 +137,6 @@ namespace Boprs
/// </summary>
internal Region ParentRegion { get; set; }
/// <summary>
/// Contour I belong to.
/// </summary>
internal Contour ParentContour { get; set; }
/// <summary>
/// Is this edge vertical?
/// </summary>