从 xyz 坐标中查找多边形区域 [英] Find area of polygon from xyz coordinates

查看:26
本文介绍了从 xyz 坐标中查找多边形区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 shapely.geometry.Polygon 模块来查找多边形的面积,但它在 xy 平面上执行所有计算.这对于我的一些多边形来说很好,但其他多边形也有 z 维度,所以它并没有完全按照我的意愿行事.

是否有一个包可以从 xyz 坐标中给我一个平面多边形的面积,或者一个包或算法来将多边形旋转到 xy 平面这样我就可以使用 shapely.geometry.Polygon().area?

多边形表示为形式为 [(x1,y1,z1),(x2,y2,z3),...(xn,yn,zn)] 的元组列表.

解决方案

这里是一个公式的推导用于计算 3D 平面多边形的面积

这是实现它的 Python 代码:

#矩阵a的行列式定义 det(a):返回 a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] + a[0][2]*a[1][0]*a[2][1] - a[0][2]*a[1][1]*a[2][0] - a[0]][1]*a[1][0]*a[2][2] - a[0][0]*a[1][2]*a[2][1]#由点a、b和c定义的平面的单位法向量def unit_normal(a, b, c):x = det([[1,a[1],a[2]],[1,b[1],b[2]],[1,c[1],c[2]]])y = det([[a[0],1,a[2]],[b[0],1,b[2]],[c[0],1,c[2]]])z = det([[a[0],a[1],1],[b[0],b[1],1],[c[0],c[1],1]])幅度 = (x**2 + y**2 + z**2)**.5返回(x/幅度,y/幅度,z/幅度)#向量a和b的点积定义点(a,b):返回 a[0]*b[0] + a[1]*b[1] + a[2]*b[2]#向量a和b的叉积定义交叉(a,b):x = a[1] * b[2] - a[2] * b[1]y = a[2] * b[0] - a[0] * b[2]z = a[0] * b[1] - a[1] * b[0]返回 (x, y, z)#多边形poly的面积定义区域(多边形):如果 len(poly) <3: # 不是飞机 - 没有区域返回 0总计 = [0, 0, 0]对于范围内的 i(len(poly)):vi1 = poly[i]如果我是 len(poly)-1:vi2 = 聚[0]别的:vi2 = poly[i+1]prod = cross(vi1, vi2)总计[0] += 产品[0]总计[1] += 产品[1]总计[2] += 产品[2]结果 = dot(total, unit_normal(poly[0], poly[1], poly[2]))返回绝对值(结果/2)

为了测试它,这里有一个倾斜的 10x5 正方形:

<预><代码>>>>poly = [[0, 0, 0], [10, 0, 0], [10, 3, 4], [0, 3, 4]]>>>poly_translated = [[0+5, 0+5, 0+5], [10+5, 0+5, 0+5], [10+5, 3+5, 4+5], [0+5,3+5, 4+5]]>>>面积(多边形)50.0>>>区域(poly_translated)50.0>>>区域([[0,0,0],[1,1,1]])0

问题最初是我过于简单化了.它需要计算垂直于平面的单位向量.面积是其点积与所有叉积之和的一半,而不是所有叉积大小之和的一半.

这可以稍微清理一下(如果你有矩阵和向量类,或者行列式/交叉积/点积的标准实现,矩阵和向量类会使它更好),但它在概念上应该是合理的.

I'm trying to use the shapely.geometry.Polygon module to find the area of polygons but it performs all calculations on the xy plane. This is fine for some of my polygons but others have a z dimension too so it's not quite doing what I'd like.

Is there a package which will either give me the area of a planar polygon from xyz coordinates, or alternatively a package or algorithm to rotate the polygon to the xy plane so that i can use shapely.geometry.Polygon().area?

The polygons are represented as a list of tuples in the form [(x1,y1,z1),(x2,y2,z3),...(xn,yn,zn)].

解决方案

Here is the derivation of a formula for calculating the area of a 3D planar polygon

Here is Python code that implements it:

#determinant of matrix a
def det(a):
    return a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] + a[0][2]*a[1][0]*a[2][1] - a[0][2]*a[1][1]*a[2][0] - a[0][1]*a[1][0]*a[2][2] - a[0][0]*a[1][2]*a[2][1]

#unit normal vector of plane defined by points a, b, and c
def unit_normal(a, b, c):
    x = det([[1,a[1],a[2]],
             [1,b[1],b[2]],
             [1,c[1],c[2]]])
    y = det([[a[0],1,a[2]],
             [b[0],1,b[2]],
             [c[0],1,c[2]]])
    z = det([[a[0],a[1],1],
             [b[0],b[1],1],
             [c[0],c[1],1]])
    magnitude = (x**2 + y**2 + z**2)**.5
    return (x/magnitude, y/magnitude, z/magnitude)

#dot product of vectors a and b
def dot(a, b):
    return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]

#cross product of vectors a and b
def cross(a, b):
    x = a[1] * b[2] - a[2] * b[1]
    y = a[2] * b[0] - a[0] * b[2]
    z = a[0] * b[1] - a[1] * b[0]
    return (x, y, z)

#area of polygon poly
def area(poly):
    if len(poly) < 3: # not a plane - no area
        return 0

    total = [0, 0, 0]
    for i in range(len(poly)):
        vi1 = poly[i]
        if i is len(poly)-1:
            vi2 = poly[0]
        else:
            vi2 = poly[i+1]
        prod = cross(vi1, vi2)
        total[0] += prod[0]
        total[1] += prod[1]
        total[2] += prod[2]
    result = dot(total, unit_normal(poly[0], poly[1], poly[2]))
    return abs(result/2)

And to test it, here's a 10x5 square that leans over:

>>> poly = [[0, 0, 0], [10, 0, 0], [10, 3, 4], [0, 3, 4]]
>>> poly_translated = [[0+5, 0+5, 0+5], [10+5, 0+5, 0+5], [10+5, 3+5, 4+5], [0+5, 3+5, 4+5]]
>>> area(poly)
50.0
>>> area(poly_translated)
50.0
>>> area([[0,0,0],[1,1,1]])
0

The problem originally was that I had oversimplified. It needs to calculate the unit vector normal to the plane. The area is half of the dot product of that and the total of all the cross products, not half of the sum of all the magnitudes of the cross products.

This can be cleaned up a bit (matrix and vector classes would make it nicer, if you have them, or standard implementations of determinant/cross product/dot product), but it should be conceptually sound.

这篇关于从 xyz 坐标中查找多边形区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆