【问题标题】:Area of coplanar points in 3D - Python3D共面点的面积 - Python
【发布时间】:2020-04-06 09:25:59
【问题描述】:

我在坐标 (x,y,z) 的 3D 中得到了一组共面点,以及它们所属的计划 P 的方程。我想知道如何使用 Python 获取窗格上这些点所占据的区域。我在 3d 中尝试过 Convhull,但我得到一个错误,因为我所有的点确实是共面的。你有什么想法吗?

谢谢!

【问题讨论】:

  • 我将通过将所有点几何投影到平面上以生成平面空间中的二维坐标列表来解决该问题,然后仅在二维中使用凸包函数,看看是否有帮助。
  • this question 的答案就是你所追求的。

标签: python scipy geometry plane


【解决方案1】:

首先,我尝试通过创建一些随机的共面点并尝试拟合凸包来重现您的问题:

import numpy as np
from scipy.spatial import ConvexHull

# 4 random 3D points
points = np.random.rand(4, 3)
# A set of coplanar points where their third dimension is 1.
coplanar = np.array([np.array([x[0], x[1], 1.0]) for x in points])

hull = ConvexHull(coplanar)

这确实会产生错误:

Traceback (most recent call last):
  File "main.py", line 9, in <module>
    hull = ConvexHull(coplanar)
  File "qhull.pyx", line 2428, in scipy.spatial.qhull.ConvexHull.__init__
  File "qhull.pyx", line 357, in scipy.spatial.qhull._Qhull.__init__
scipy.spatial.qhull.QhullError: QH6154 Qhull precision error: Initial simplex is flat (facet 1 is cop
lanar with the interior point)

..... OMITTING SOME LINES ....

If the input is lower dimensional:
  - use 'QJ' to joggle the input and make it full dimensional
  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should
    pick the coordinate with the least range.  The hull will have the
    correct topology.
  - determine the flat containing the points, rotate the points
    into a coordinate plane, and delete the other coordinates.
  - add one or more points to make the input full dimensional.

正如我们所见,底层库 (qhull) 为我们提供了一些建议,以防您的数据为低维数据。正如您所说,您已经知道您的数据是共面的,并且可以将其投影到平面上并由 2D 点表示。

按照错误消息中的建议,投影数据的另一种方法是使用选项QJ 微动输入 (option doc)。如果我理解正确的话,这个“joggle”会通过向您的数据引入随机噪声使您的数据“非共面”,从而允许优化继续进行。

hull = ConvexHull(coplanar, qhull_options="QJ")
hull.area
> 0.3100618849870332

总结:

  • 找出平面与单位xy平面之间的角度,如果您想要一个精确的答案,可以旋转您的数据
  • 如果您想要一个快速的解决方案并且高精度不是问题,请使用选项"QJ"(我实际上不知道答案与事实相差多远)

更新

来自Qhull FAQ

面积是凸包表面的面积,而体积是凸包的总体积。

在二维中,凸包是一个多边形。它的表面是多边形的边缘。所以在二维中,“面积”是多边形边的长度,而“体积”是多边形的面积。

根据这些陈述,我认为您应该使用:

  • hull.area / 2 用于 3D 点(带有选项 QJ 的原始点)
  • hull.volume 用于二维点(如果您旋转点并摆脱一维)

为了帮助阐明ConvexHull 的用法,我使用了一个更简单的示例

square2D = np.array([
    [0.0, 0.0],
    [2.0, 0.0],
    [2.0, 2.0],
    [0.0, 2.0]
])
hull = ConvexHull(square2D)
hull.area
> 8.0
hull.volume
> 4.0

结果与文档一致。

现在,为了了解选项QJ 的效果,我只是在前面的几点上添加了一个维度:

coplanar = np.array([
    [0.0, 0.0, 0.0],
    [2.0, 0.0, 0.0],
    [2.0, 2.0, 0.0],
    [0.0, 2.0, 0.0]
])
hull = ConvexHull(coplanar, qhull_options="QJ")
hull.area
> 8.000000000306578
hull.volume
> 5.719619827513867e-11

对于最后一个示例,我将凸包想象为具有两个大面的近似“平坦”的 3D 对象(由于引入了噪声)。这就是为什么我认为在这种情况下你可以使用hull.area / 2

【讨论】:

  • 感谢您的回答!这确实是我的问题,我会检查QJ是什么!对于投影,您知道任何能够进行投影的 python 模块吗? (我需要什么我得到 convhull 并且错误正确是来自我的共面点(x,y,z)的全局坐标的局部坐标(u,v))
  • @cazator,这是一个快速的想法,我可能需要更好地阐述它(我的数学真的很生疏)。首先,你需要找到平面与单位坐标之间的夹角(你可以使用正切方程);其次,您可以使用scipy.spatial.transform.Rotation 旋转点向量以获得z = 0;最后,您可以重塑您的最终点向量并删除第三个维度。
  • 小心投影,因为投影多边形的面积几乎肯定与原始多边形不同。更好的方法是计算将您的平面转换为 xy 平面的旋转矩阵。
  • 您好,感谢您的回答。在对 (u,v) 坐标进行 ConvHull 之前,我进行了数学运算,并计算了我的点在平面上的局部坐标 (u,v)。我得到以下几点和 ConvHull 结果:imgur.com/a/BhPIBVG。我检查了一下,就数量级和模式而言,坐标似乎还可以。 ConvHull 似乎也适用于该形状。但是 ConvHull(.).area 给出的面积大约是 4000,这似乎很小,因为我预计 sthg 高 2 个数量级。你们知道为什么面积这么小吗?即使算法似乎有效?
  • @DrBwts 是完全正确的。我用了错误的术语试图说同样的话。我会编辑答案。
猜你喜欢
  • 1970-01-01
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
相关资源
最近更新 更多