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));
}