Это может быть очень простая проблема, но кажется, что я не могу ее увидеть. У меня есть список точек упорядоченных по часовой стрелке и хочу, чтобы вычислить центр тяжести этих точек (выпуклый многоугольник) с помощью следующей функции в соответствии с this:Как Python обрабатывает сложные вычисления?
и
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 показывает, что вычисленное 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)]
Лично я хотел бы найти мой код на * много * легче читать, если я приложил копию первой точки на конце список пунктов, поэтому мне не нужно было повторно (правильно) проверять обертку каждый раз, когда я хотел бы обратиться к (i + 1) -й точке. Вот что сделала Википедия. Кроме того, почему бы не просто перебрать i по длине списка (-1, если вы добавили первую точку в конец) и всегда индексировать с помощью i? Я попытался расшифровать ваши выражения из вашего кода, но сдался. – barny
@barny: вы правы, я могу сделать это другими способами, добавив первую точку в конце списка или добавив ее после завершения цикла for. Но использование понимания в списках упрощает понимание кода (может быть неэффективным), поскольку вам не нужно, как какой-либо дополнительный шаг, просто нужно проверить, находитесь ли вы в листе, подумайте о первом, чтобы закрыть looop. – msc87
Это ваш код, но мои 0,01 доллара говорят, что ваш код практически неразборчивый и неразборчивый код трудно понять, отладить и сохранить. «упрощение» цикла for для итерации по списку точек делает вас a) писать код для инициализации, использования и поддержки счетчика циклов i, b) приходится вручную кодировать обертку вокруг первого узла каждый раз, когда требуется i + 1 - ВОСЕМЬ раз, когда вы набрали «i + 1, если i + 1
barny