2012-03-13 40 views
11

如何找到在JavaScript中给定其顶点的凹形不规则多边形的质心?如何在JavaScript中找到凹形不规则多边形的质心?

我想将一组x,y点传递给JavaScript函数并给出x,y点。

var my_points = [{x:3,y:1},{x:5,y:8},{x:2,y:9}]; 

function get_polygon_centroid(points){ 
    // answer 
} 

var my_centroid = get_polygon_centroid(my_points); 

my_points变量只应该代表点的格式给出,不代表点的特定计数给予

质心返回将是多边形内的某个点。

最终目标是在Google Maps V3应用程序的多边形的质心处添加一个标记。

+0

本文javascript代码:HTTP:// paulbourke。 net/geometry/polyarea/ – Zevan 2012-03-13 21:32:35

+0

你认为'google.maps.LatLngBounds.getCenter()'? – 2012-03-13 21:38:33

+1

我发现这个代码:http://jsfiddle.net/SXde5/ – Joe 2012-03-13 21:40:36

回答

21

对于2D表面的质心(这可能是您需要的), 最好的是以a little bit of maths开头。

我适应这里给自己的符号:

function get_polygon_centroid(pts) { 
    var first = pts[0], last = pts[pts.length-1]; 
    if (first.x != last.x || first.y != last.y) pts.push(first); 
    var twicearea=0, 
    x=0, y=0, 
    nPts = pts.length, 
    p1, p2, f; 
    for (var i=0, j=nPts-1 ; i<nPts ; j=i++) { 
     p1 = pts[i]; p2 = pts[j]; 
     f = p1.x*p2.y - p2.x*p1.y; 
     twicearea += f;   
     x += (p1.x + p2.x) * f; 
     y += (p1.y + p2.y) * f; 
    } 
    f = twicearea * 3; 
    return { x:x/f, y:y/f }; 
} 
+1

正如维基百科在引用的文章中所述,需要注意的是:“假设顶点被编号(x0,y0)被假定为与(x0,y0)相同“ – Fgblanch 2013-08-22 11:07:50

+1

调整后自动关闭多边形如果(x0,y0)!=(xn,yn)按照它们沿多边形周界出现的顺序,并且顶点) – Myobis 2015-06-16 13:34:19

+1

我认为在第一行'var first = t [0]'它意味着'var first = pts [0]' – JoeRocc 2015-06-18 05:11:34

1

这样做相当简单。所述centroid of a finite set of k pointsX ,X ,... X ķ由下式描述的

(X + X + ... + X ķ)/K

这意味着我们可以只添加所有的点起来,然后除以点的数目,这样的:

function getPolygonCentroid(points){ 
    var centroid = {x: 0, y: 0}; 
    for(var i = 0; i < points.length; i++) { 
    var point = points[i]; 
    centroid.x += point.x; 
    centroid.y += point.y; 
    } 
    centroid.x /= points.length; 
    centroid.y /= points.length; 
    return centroid; 
} 
+5

-1:在同一个wiki页面中给出的多边形的质心与形成它的点的质心不同。您对许多点的质心的定义是正确的。但是任何区域的质心都被定义为质心的位置,这通常与顶点的质心不同。 – 2012-03-31 22:07:42

+0

我试图在其中一个“点”引用中更正缺少的“我”,但愚蠢的编辑器要求我更改至少6个字符,所以我将示例中的方法名称更改为camelcased(在JS中更常见无论如何) - 希望没关系Peter Olson? (我不知道如何进行更改,以便示例可以正常工作,而不会因拼写错误而导致错误) – csuwldcat 2013-10-18 16:09:39

1

如果你不随便关于“心”的定义,this是多边形的质心公式。正如你所看到的,它比一组点的质心要复杂得多。如果你可以处理点的质心,那很好,但是如果你想要多边形的质心,你必须实现这个公式,这并不是很困难。请记住,在一般不规则多边形的情况下,这是你的情况,这两个质心将不同(否则这个公式不存在)。

+0

您给出的质心仍然是一组点的质心;这组点是无限的... :) – ellisbben 2012-04-01 21:43:17

+1

当然,我只是不想详细说明它太多。在另一种情况下,我们认为这些点是质量相同的质点,这里我们考虑质量在多边形内均匀分布。 – 2012-04-02 04:56:45

2

接受的答案有一个问题,随着多边形的面积变小而变得显着。它在大多数情况下都不可见,但在非常小的尺寸下会导致一些奇怪的结果。这是解决此问题的解决方案的更新。

function get_polygon_centroid(pts) { 
    var first = pts[0], last = pts[pts.length-1]; 
    if (first.x != last.x || first.y != last.y) pts.push(first); 
    var twicearea=0, 
    x=0, y=0, 
    nPts = pts.length, 
    p1, p2, f; 
    for (var i=0, j=nPts-1 ; i<nPts ; j=i++) { 
     p1 = pts[i]; p2 = pts[j]; 
     f = (p1.y - first.y) * (p2.x - first.x) - (p2.y - first.y) * (p1.x - first.x); 
     twicearea += f; 
     x += (p1.x + p2.x - 2 * first.x) * f; 
     y += (p1.y + p2.y - 2 * first.y) * f; 
    } 
    f = twicearea * 3; 
    return { x:x/f + first.x, y:y/f + first.y }; 
} 

这里有一个质心的小多边形之外结束了对任何人好奇,什么我谈论的例子:

var points = [ 
    {x:78.0001462, y: 40.0008827}, 
    {x:78.0000228, y: 40.0008940}, 
    {x:78.0000242, y: 40.0009264}, 
    {x:78.0001462, y: 40.0008827}, 
]; 
// original get_polygon_centroid(points) 
// results in { x: 77.99957948181007, y: 40.00065236005001 } 
console.log(get_polygon_centroid(points)) 
// result is { x: 78.0000644, y: 40.000901033333335 } 
+1

+1用于处理基本方法的实际问题,在维基百科和我检查过的其他地方出乎意料地没有提及。然而,解决方案中存在一个错误:以'x + =(p1.y + p2.y ...'和'y + =(p1.x + p2.x ...')开头的行当然应该是'x + =(p1.x + p2.x ...'和'y + =(p1.y + p2.y ...'。 – Jonas 2018-01-09 11:23:58

+0

Yikes!谢谢你的注意,Jonas。 – pragmar 2018-01-15 22:51:04