前言
以前使用的是LISP,有现成的计算中心点程序,并且得到的结果非常好,今年开始使用C#语言开发。发现没有现成的方法能得到图形的中心点,我使用的是CAD2015在C#下面域也没有提供取出中心点的方法,只能自己想办法。
以下为用三角剖分法来计算重心点,但是该方法每次计算的结果,会得到两种结果,如果图形是凸形结果会正确,如果是凹形,如果反复运行,会得到两个结果,一个在中心,另一个会靠近图形的边界上,后将算法进行优化后得到的结果,就目前来说都很满意。优化的方法见下面。
该方法只需要CAD下的Point3dCollection点集就可以直接进行计算。
代码如下(示例):
public static Point2d HKCalculateCenter(Point3dCollection points)
{
int count = points.Count;
// 创建一个用于存储三角形的列表
List<Triangle> triangles = new List<Triangle>();
// 将多边形分割成三角形
for (int i = 1; i < count - 1; i++)
{
Triangle triangle = new Triangle(points[0], points[i], points[i + 1]);
triangles.Add(triangle);
}
// 计算面积总和和加权的x、y值之和
double area = 0;
double xSum = 0;
double ySum = 0;
foreach (Triangle triangle in triangles)
{
double triangleArea = triangle.Area;
Point2d triangleCenter = triangle.Center;
xSum += triangleCenter.X * triangleArea;
ySum += triangleCenter.Y * triangleArea;
area += triangleArea;
}
// 计算重心坐标
Point2d center = new Point2d(xSum / area, ySum / area);
// 计算偏移距离
double offset = CalculateOffset(points, center);
// 将偏移距离应用于中心坐标
center = new Point2d(center.X + offset, center.Y + offset);
return center;
}
// 计算偏移距离
public static double CalculateOffset(Point3dCollection points, Point2d center)
{
int count = points.Count;
double area = 0;
double xSum = 0;
double ySum = 0;
// 计算面积总和和加权的x、y值之和
for (int i = 0; i < count; i++)
{
Point3d currentPoint = points[i];
Point3d nextPoint = points[(i + 1) % count];
double xi = currentPoint.X - center.X;
double yi = currentPoint.Y - center.Y;
double xi1 = nextPoint.X - center.X;
double yi1 = nextPoint.Y - center.Y;
double temp = xi * yi1 - xi1 * yi;
area += temp;
xSum += (currentPoint.X + nextPoint.X - 2 * center.X) * temp;
ySum += (currentPoint.Y + nextPoint.Y - 2 * center.Y) * temp;
}
double offset = Math.Sqrt((xSum * xSum + ySum * ySum) / (36 * area * area));
return offset;
}
// 三角形类
public class Triangle
{
public Point2d P1 { get; set; }
public Point2d P2 { get; set; }
public Point2d P3 { get; set; }
public Triangle(Point3d p1, Point3d p2, Point3d p3)
{
this.P1 = new Point2d(p1.X, p1.Y);
this.P2 = new Point2d(p2.X, p2.Y);
this.P3 = new Point2d(p3.X, p3.Y);
}
// 计算三角形面积
public double Area
{
get
{
return Math.Abs((P1.X - P3.X) * (P2.Y - P1.Y) - (P1.X - P2.X) * (P3.Y - P1.Y)) / 2;
}
}
// 计算三角形中心坐标
public Point2d Center
{
get
{
double x = (P1.X + P2.X + P3.X) / 3;
double y = (P1.Y + P2.Y + P3.Y) / 3;
return new Point2d(x, y);
}
}
}
总结
经过反复的验证,得到的结果非常好。