【问题标题】:How do I calculate a 3D centroid?如何计算 3D 质心?
【发布时间】:2011-01-28 02:06:45
【问题描述】:

还有 3D 质心这样的东西吗?让我非常清楚 - 过去 2 天我一直在这个网站和整个网络上阅读和阅读关于质心的内容,所以我完全了解有关该主题的现有帖子,包括 Wikipedia

也就是说,让我解释一下我要做什么。基本上,我想选择边和/或顶点,但不是面。然后,我想在 3D 质心位置放置一个对象。

我会告诉你我不想要的:

  • 顶点平均值,这将在任何具有更详细网格的方向上拉得太远。
  • 边界框中心,因为我已经为这个场景准备了一些东西。

我愿意接受有关质心的建议,但我不明白这将如何工作,因为仅顶点或边并不能定义任何类型的质量,尤其是当我只选择了一个边循环时。

为了好玩,我将向您展示一些我处理过的PyMEL,使用@Emile's code 作为参考,但我认为它没有按应有的方式工作:

from pymel.core import ls, spaceLocator
from pymel.core.datatypes import Vector
from pymel.core.nodetypes import NurbsCurve

def get_centroid(node):
    if not isinstance(node, NurbsCurve):
        raise TypeError("Requires NurbsCurve.")
    centroid = Vector(0, 0, 0)
    signed_area = 0.0
    cvs = node.getCVs(space='world')
    v0 = cvs[len(cvs) - 1]
    for i, cv in enumerate(cvs[:-1]):
        v1 = cv
        a = v0.x * v1.y - v1.x * v0.y
        signed_area += a
        centroid += sum([v0, v1]) * a
        v0 = v1
    signed_area *= 0.5
    centroid /= 6 * signed_area
    return centroid

texas = ls(selection=True)[0]
centroid = get_centroid(texas)
print(centroid)
spaceLocator(position=centroid)

【问题讨论】:

    标签: python average maya


    【解决方案1】:

    理论上 centroid = SUM(pos*volume)/SUM(volume) 当您将零件拆分为有限体积时,每个体积都有一个位置 pos 和体积值 volume

    这正是为找到复合零件的重心所做的计算。

    【讨论】:

    • 为简单起见,我将接受这个答案,但我要等到以后才能对其进行测试。我会及时通知你。
    【解决方案2】:

    不只是一个 3D 质心,还有一个 n 维质心,它的公式在您引用的 Wikipedia 文章的“按积分公式”部分给出。

    也许您在设置此积分时遇到问题?你还没有定义你的形状。

    [编辑]我会加强这个答案来回应你的评论。由于您已经根据边和顶点描述了您的形状,所以我假设它是polyhedron。您可以将多面体划分为金字塔,找到金字塔的质心,然后您的形状的质心就是质心的质心(最后的计算是使用 ja72 的公式完成的)。

    我会假设你的形状是凸的(没有空心部分——如果不是这种情况,那么将它分成凸块)。您可以通过在内部选取一个点并将边缘绘制到顶点来将其划分为金字塔(对其进行三角剖分)。然后你的形状的每个面都是金字塔的底部。金字塔的质心有一些公式(你可以查一下,它是从面部质心到内部点的 1/4 距离)。然后如前所述,您的形状的质心是质心的质心——ja72 的有限计算,而不是积分——如另一个答案中给出的那样。

    这与 Hugh Bothwell 的回答中的算法相同,但我相信 1/4 是正确的,而不是 1/3。也许您可以使用此描述中的搜索词找到一些潜伏在某处的代码。

    【讨论】:

    • 是的,好吧...尴尬的是,我什至不知道积分是什么。当我看不到实际代码时,我会迷路。我不明白公式。你是对的。当我只有一组顶点时,我的形状不一定是定义的。你怎么知道如何正确连接这些点?
    【解决方案3】:

    我喜欢这个问题。质心听起来是对的,但问题就变成了,每个顶点的质量是多少?

    为什么不使用包含顶点的每条边的平均长度?这应该可以很好地补偿具有密集网格的区域。

    【讨论】:

    • 你知道,在你发布这篇文章前几分钟我也在想同样的事情。我想知道结果会是什么。因为在这种情况下,数学将非常简单,因为它只是一个加权平均值。我现在需要睡觉,但我明天再看看。
    • 仍在研究此解决方案。我会尽量让你更新。
    • 我很想看看结果。它显然适用于一些简单的测试用例。例如。一个圆柱体,有很多顶点定义一端,而另一端则更少。如果不起作用,哪些测试用例有问题?
    【解决方案4】:

    您必须从顶点重新创建人脸信息(本质上是 Delauney 三角剖分)。

    如果您的顶点定义了一个凸包,您可以选择对象内的任意点 A。将您的对象视为具有顶点 A 且每个面为底的棱锥体的集合。

    对于每个面,求面积 Fa 和二维质心 Fc;那么棱镜的质量与体积成正比(== 1/3 底 * 高度(Fc-A 垂直于面的分量)),只要你对所有棱镜都这样做,你就可以忽略比例常数;质心为 (2/3 A + 1/3 Fc),即从顶点到底部二维质心的三分之一。

    然后,您可以对质心点进行质量加权平均,以找到整个对象的 3d 质心。

    同样的过程应该适用于非凸面船体 - 甚至适用于船体外的 A - 但面计算可能是个问题;你需要小心你的脸的惯用手。

    【讨论】:

    • 我一直在尝试利用我发现(并简化)的一些 Delauney 代码来使其正常工作,但我不能 100% 确定它是否正常工作。不幸的是,我不能依赖 numpy 这个。仍在研究此解决方案。我会及时通知你。
    猜你喜欢
    • 2012-04-06
    • 2011-01-22
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-27
    • 2019-05-12
    相关资源
    最近更新 更多