2015-08-25 55 views
4

這可能是一個非常簡單的問題,但似乎我無法看到它。 我有順時針點有序的列表,並希望根據this使用下面的函數來計算這些點的重心(凸多邊形):Python如何處理複雜的計算?

enter image description here enter image description here

enter image description here

def calculateCentroid(raLinks,raNodes, links, nodes): 

orderedPointsOfLinks = orderClockwise(raLinks,raNodes, links, nodes) 

arg1 = 0 
arg2 = 0 
Xc = 0 
Yc = 0 
i = 0 
for point in orderedPointsOfLinks: 
    arg1 += point.Y*(orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].X) 
    arg2 += (orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].Y)*point.X 
    Xc += (point.X+(orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].X))*(((orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].Y)*point.X)-(point.Y*(orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].X))) 
    Yc += (point.Y+(orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].Y))*(((orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].Y)*point.X)-(point.Y*(orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].X)))  
    i+=1 

area = (arg1-arg2)*0.5 
print area 

X = -Xc/(6*area) 
Y = -Yc/(6*area) 
print X , " ", Y 

使用Arcpy計算面積和centorid表明計算的ar ea通過上述函數是正確的,但質心是錯誤的。

Xc和Yc有什麼問題,我無法修復它?

如果我以下列方式改變爲循環工作原理:

for point in orderedPointsOfLinks: 
     y0 = point.Y 
     x0 = point.X 
     x1 = orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].X 
     y1 = orderedPointsOfLinks[i+1 if i+1<len(orderedPointsOfLinks) else 0].Y 
     a = x0*y1 - x1*y0 
     area += a 
     Xc += (x0+x1)*a 
     Yc += (y0+y1)*a 
     i+=1 
    area *= 0.5 
    print area 

    X = Xc/(6*area) 
    Y = Yc/(6*area) 
    print X , " ", Y 

這裏是節點的列表來檢查代碼:

[(371623.876, 6159668.714),(371625.994, 6159661.094), (371624.319, 6159654.634), (371619.654, 6159649.86), (371614.194, 6159647.819), (371608.401, 6159648.449), (371601.544, 6159652.652), (371598.77, 6159658.058), (371599.318, 6159665.421), (371603.025, 6159671.805), (371611.372, 6159674.882), (371619.417, 6159673.065)] 
+1

個人而言,我會找到我的代碼*很多*更容易閱讀,如果我附加了第一點的副本到的結束所以我不必在每次想參考第(i + 1)點時重新輸入(正確)那個環繞測試。這就是維基百科所做的。另外,爲什麼不迭代我的列表長度(-1,如果你追加第一個點到最後),並始終使用我的索引?我試圖從你的代碼中解碼你的表達式,但放棄了。 – barny

+0

@ barny:你說得對,我可以用其他方式做,在列表末尾添加第一個點或在for循環結束後添加它。但是使用列表理解可以更容易地理解代碼(可能效率更高),因爲您不需要額外的步驟,只需要檢查是否在代碼中,考慮第一個關閉德路。 – msc87

+1

這是您的代碼,但我的0.01美元表示您的代碼幾乎難以辨認,難以辨認的代碼難以理解,調試和維護。 「簡化」for循環遍歷點列表使您可以:a)編寫代碼來初始化,使用和維護循環計數器i,b)每次需要i + 1時必須手動將代碼繞回到第一個節點 - 如果i + 1 barny

回答

2

source

嘗試:

import numpy 

tp = [(371623.876, 6159668.714),(371625.994, 6159661.094), (371624.319, 6159654.634), (371619.654, 6159649.86),\ 
     (371614.194, 6159647.819), (371608.401, 6159648.449), (371601.544, 6159652.652), (371598.77, 6159658.058), \ 
     (371599.318, 6159665.421), (371603.025, 6159671.805), (371611.372, 6159674.882), (371619.417, 6159673.065),(371623.876, 6159668.714)] 



# cx = sigma (x[i]+x[i+1])*((x[i]*y[i+1]) - (x[i+1]*y[i])) 
# cy = sigma (y[i]+y[i+1])*((x[i]*y[i+1]) - (x[i+1]*y[i])) 
cx = 0 
cy = 0 

p = numpy.array(tp) 

x = p[:, 0] 
y = p[:, 1] 

a = x[:-1] * y[1:] 
b = y[:-1] * x[1:] 

cx = x[:-1] + x[1:] 
cy = y[:-1] + y[1:] 



tp = tp[:-1] #dont need repeat 


def area(): 
    tox=0 
    toy=0 
    for i in range(len(tp)): 
     if i+1 == len(tp): 
      tox += tp[-1][0]*tp[0][1] 
     else: 
      tox += tp[i][0]*tp[i+1][1] 

    for i in range(len(tp)): 
     if i+1 == len(tp): 
      toy += tp[-1][1]*tp[0][0] 
     else: 
      toy += tp[i][1]*tp[i+1][0] 
    return abs(tox-toy)*0.5 

ar = area() 
Cx = abs(numpy.sum(cx * (a - b))/(6. * ar)) 
Cy = abs(numpy.sum(cy * (a - b))/(6. * ar)) 
print Cx,Cy 

警告!

tp[0] == tp[-1] 

所以:第一和最後一個座標是相同的值...

+0

我對這個地區沒有問題。問題在於計算座標,因爲它在區域正確時返回錯誤值。我懷疑python處理複雜方程式的方式是個問題,因爲現在和接下來座標值的變化都是不合理的,如果點列表被修復的話! – msc87

+0

@ msc87更新代碼! – dsgdfg

+0

@ msc87在立陶宛的地方? – dsgdfg