私は地理空間形状を扱っており、ここで重心アルゴリズムを見ています。
http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
私はこのようにC#でコードを実装しました(これはまさにこれを適応させたものです)、
class Program
{
static void Main(string[] args)
{
List<Point> vertices = new List<Point>();
vertices.Add(new Point() { X = 1, Y = 1 });
vertices.Add(new Point() { X = 1, Y = 10 });
vertices.Add(new Point() { X = 2, Y = 10 });
vertices.Add(new Point() { X = 2, Y = 2 });
vertices.Add(new Point() { X = 10, Y = 2 });
vertices.Add(new Point() { X = 10, Y = 1 });
vertices.Add(new Point() { X = 1, Y = 1 });
Point centroid = Compute2DPolygonCentroid(vertices);
}
static Point Compute2DPolygonCentroid(List<Point> vertices)
{
Point centroid = new Point() { X = 0.0, Y = 0.0 };
double signedArea = 0.0;
double x0 = 0.0; // Current vertex X
double y0 = 0.0; // Current vertex Y
double x1 = 0.0; // Next vertex X
double y1 = 0.0; // Next vertex Y
double a = 0.0; // Partial signed area
// For all vertices except last
int i=0;
for (i = 0; i < vertices.Count - 1; ++i)
{
x0 = vertices[i].X;
y0 = vertices[i].Y;
x1 = vertices[i+1].X;
y1 = vertices[i+1].Y;
a = x0*y1 - x1*y0;
signedArea += a;
centroid.X += (x0 + x1)*a;
centroid.Y += (y0 + y1)*a;
}
// Do last vertex
x0 = vertices[i].X;
y0 = vertices[i].Y;
x1 = vertices[0].X;
y1 = vertices[0].Y;
a = x0*y1 - x1*y0;
signedArea += a;
centroid.X += (x0 + x1)*a;
centroid.Y += (y0 + y1)*a;
signedArea *= 0.5;
centroid.X /= (6*signedArea);
centroid.Y /= (6*signedArea);
return centroid;
}
}
public class Point
{
public double X { get; set; }
public double Y { get; set; }
}
問題は、この形状 (L 形状) の場合、このアルゴリズムは、
(1,1) (1,10) (2,10) (2,2) (10,2) (10,1) (1,1)
結果(3.62、3.62)が得られます。ポイントが形状の外側にあることを除いて、これは問題ありません。これを考慮した別のアルゴリズムはありますか?
基本的に、人は地図上に形を描くことになります。この形状は複数の道路にまたがる可能性があり (L 字型になる可能性があります)、形状の中心を計算したいと考えています。これは、その時点で道路名を割り出すことができるようにするためです。細く長いL字を描いたのに、それが形の外にあるのは私には意味がありません。