diff --git a/Commands.cs b/Commands.cs index e804ccb..2c1cb19 100644 --- a/Commands.cs +++ b/Commands.cs @@ -117,6 +117,8 @@ namespace Boprs { contour.Draw(); } + + acDoc.Editor.WriteMessage($"\nResult area: {bopr.Result.Area}"); } } } diff --git a/Contour.cs b/Contour.cs index 2509ad2..29b8b6d 100644 --- a/Contour.cs +++ b/Contour.cs @@ -23,19 +23,29 @@ namespace Boprs { public object Clone() { - return new Contour() { Vertices = new List(Vertices) }; + return new Contour(new List(Vertices)); } /// /// Vertices of the contour. /// - public List Vertices { get; private set; } + private List Vertices { get; } /// - /// Are the vertices of the contour arranged in clockwise manner? + /// Signed area of the contour. /// - /// true if the contour is clockwise, false if counter-clockwise. - public bool IsClockwise() + public double SignedArea { get; private set; } + + /// + /// Are the vertices of the contour arranged in clockwise manner? + /// + /// true if the contour is clockwise, false if counter-clockwise. + public bool IsClockwise { get => SignedArea < 0; } + + /// + /// Compute the signed area of the contour + /// + 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; } /// /// Reverse the orientation of the contour. /// - public void Reverse() + internal void Reverse() { Vertices.Reverse(); + SignedArea *= -1; } /// /// Constructor. /// - public Contour() + public Contour(List vertices) { - Vertices = new List(); + 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); } diff --git a/Region.cs b/Region.cs index e678376..09e4e5f 100644 --- a/Region.cs +++ b/Region.cs @@ -25,8 +25,16 @@ namespace Boprs /// private List Edges { get; set; } + /// + /// Contours making up the region. + /// private List Contours { get; set; } + /// + /// Area of the positive part of the region (holes subtracted). + /// + public double Area { get; private set; } + /// /// Subdivide my edges, set their inOut tags and validate their non-colinearity. /// @@ -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 contourVertices = new List() { 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; - - // If the contour is a hole and winds ccw, or positive and winds cw, flip it. - if (shouldBeCW != contour.IsClockwise()) + + // 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) { contour.Reverse(); } @@ -202,6 +210,21 @@ namespace Boprs Contours = contours; } + /// + /// Compute the area of the region. + /// + /// + /// Requires contours to be computed. + /// + private void ComputeArea() + { + Area = 0; + foreach(Contour contour in Contours) + { + Area += contour.SignedArea; + } + } + /// /// Get a copy of the regions edges list. /// @@ -255,6 +278,7 @@ namespace Boprs region.SetEdges(vertices); region.ComputeContours(); + region.ComputeArea(); return region; } diff --git a/SweepEdge.cs b/SweepEdge.cs index 6334ed8..cbd329d 100644 --- a/SweepEdge.cs +++ b/SweepEdge.cs @@ -137,11 +137,6 @@ namespace Boprs /// internal Region ParentRegion { get; set; } - /// - /// Contour I belong to. - /// - internal Contour ParentContour { get; set; } - /// /// Is this edge vertical? ///