Non-correct centroid location of closed polyline C#

Non-correct centroid location of closed polyline C#

alselk2016
Explorer Explorer
1,741 Views
2 Replies
Message 1 of 3

Non-correct centroid location of closed polyline C#

alselk2016
Explorer
Explorer

when i run my program i get a different  centroid point , please help me to get the correct  point thanks in advance

my program is : the user select polylines and i Convert Polyline to in-memory Region. but i get wrong centroid point.

this is My Code:

Captureddd.PNG

0 Likes
Accepted solutions (1)
1,742 Views
2 Replies
Replies (2)
Message 2 of 3

_gile
Consultant
Consultant

Hi,

 

Try this one (adapted from GeometryExtensions).

        public static Point3d GetPolylineCentroid(Polyline pline)
        {
            Point2d polar(Point2d org, double angle, double distance) =>
            new Point2d(
                org.X + distance * Math.Cos(angle),
                org.Y + distance * Math.Sin(angle));

            double arcSignedArea(CircularArc2d arc)
            {
                double rad = arc.Radius;
                double ang = arc.IsClockWise ?
                    arc.StartAngle - arc.EndAngle :
                    arc.EndAngle - arc.StartAngle;
                return rad * rad * (ang - Math.Sin(ang)) / 2.0;
            }

            Point2d arcCentroid(CircularArc2d arc)
            {
                Point2d start = arc.StartPoint;
                Point2d end = arc.EndPoint;
                double a = arcSignedArea(arc);
                double chord = start.GetDistanceTo(end);
                double angle = (end - start).Angle;
                return polar(arc.Center, angle - Math.PI / 2.0, chord * chord * chord / (12.0 * a));
            }

            double triangleSignedArea(Point2d pt0, Point2d pt1, Point2d pt2) =>
            ((pt1.X - pt0.X) * (pt2.Y - pt0.Y) -
            (pt2.X - pt0.X) * (pt1.Y - pt0.Y)) / 2.0;

            Point2d triangleCentroid(Point2d pt0, Point2d pt1, Point2d pt2) =>
            (pt0 + pt1.GetAsVector() + pt2.GetAsVector()) / 3.0;

            Point2d cen = new Point2d();
            double tmpArea;
            double area = 0.0;
            int last = pline.NumberOfVertices - 1;
            Point2d p0 = pline.GetPoint2dAt(0);

            if (pline.GetSegmentType(0) == SegmentType.Arc)
            {
                var arc = pline.GetArcSegment2dAt(0);
                area = arcSignedArea(arc);
                cen = arcCentroid(arc) * area;
            }
            for (int i = 1; i < last; i++)
            {
                var p1 = pline.GetPoint2dAt(i);
                var p2 = pline.GetPoint2dAt(i + 1);
                tmpArea = triangleSignedArea(p0, p1, p2);
                cen += (triangleCentroid(p0, p1, p2) * tmpArea).GetAsVector();
                area += tmpArea;
                if (pline.GetSegmentType(i) == SegmentType.Arc)
                {
                    var arc = pline.GetArcSegment2dAt(i);
                    tmpArea = arcSignedArea(arc);
                    area += tmpArea;
                    cen += (arcCentroid(arc) * tmpArea).GetAsVector();
                }
            }
            if ((pline.GetSegmentType(0) == SegmentType.Arc) && (pline.Closed == true))
            {
                var arc = pline.GetArcSegment2dAt(last);
                tmpArea = arcSignedArea(arc);
                area += tmpArea;
                cen += (arcCentroid(arc) * tmpArea).GetAsVector();
            }
            var pt = cen.DivideBy(area);
            return new Point3d(pt.X, pt.Y, pline.Elevation)
                .TransformBy(Matrix3d.PlaneToWorld(pline.Normal));
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 3

_gile
Consultant
Consultant
Accepted solution

If you want to go through the construction of a Region way, the code below should work but, unlike the one above, only if the polyline lies on the WCS XY plane.

        public static Point2d GetPolylineCentroidByRegion(Polyline pline)
        {
            var curves = new DBObjectCollection();
            curves.Add(pline);
            var regions = Region.CreateFromCurves(curves);
            using(var region = (Region)regions[0])
            {
                var origin = Point3d.Origin;
                var xAxis = Vector3d.XAxis;
                var yAxis = Vector3d.YAxis;
                var props = region.AreaProperties(ref origin, ref xAxis, ref yAxis);
                return props.Centroid;
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub