2012-03-13 91 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