【问题标题】:Given a point and a large number of tetrahedrons, how to efficiently determine in which tetrahedron the point is给定一个点和大量的四面体,如何高效判断该点在哪个四面体中
【发布时间】:2020-09-15 20:12:22
【问题描述】:

假设我们将一个点定义为一个元组 三个浮点数组成,四面体由四个点组成。

假设我们有一个四面体和一个点,我们可以确定是否 点属于下面描述的解决方案的四面体 How to check whether the point is in the tetrahedron or not? 这里的关键思想是确定该点是否在四面体四个侧面的内侧。

我的问题。给定一个点和 N 个四面体,其中 N 约为 700 万,我需要确定该点在哪个四面体中。我们会关心重复测试的表现,有大量的分数。

附加信息:

  1. 可以使用上述方法一一检查这些四面体。但考虑到我有大量的四面体,这可能太慢了。

  2. 问题设置中有一个特定的点。这些四面体是 从 FEM(有限元法)问题中获得,用于求解 医学成像问题(它们构成了患者的大脑)。也许 FEM 本身与这个问题无关,但我们可以利用这些四面体彼此相邻并且在这些四面体模拟的空间中没有“洞”这一事实。

  3. 除了相邻的边界外,四面体没有交点。所以,这个问题应该有一个唯一的解决方案,除非在边界处,在这种情况下,可以让任何一个相交的四面体来解决我的问题。

  4. 四面体的输入没有特定的顺序。四面体的形状是否规则并没有规定。

关于有效解决问题的任何想法?解决这个问题首选 Python。

谢谢!

【问题讨论】:

  • 1.输入时是否有四面体的顺序? (也许机器会分层扫描大脑?) 2. 我是否正确理解我们只关心一个测试的性能,而不是重复测试? (我的第一个想法是八叉树,但构建一次测试可能成本太高) 3. 四面体的形状怎么样 - 大多数是规则的或倾斜的? 4. 我会从琐碎的 (minx, miny, minz)
  • 感谢您考虑这个问题。回答您的问题:在输入上没有给出四面体的特定顺序。四面体的形状是否规则并没有规定。我们确实关心重复测试的性能。

标签: python performance vectorization finite-element-analysis tetrahedra


【解决方案1】:

您可以首先过滤四面体,只保留边界长方体(与 X、Y 和 Z 轴平行)包含 p 的那些。这样测试起来更快:

所以找到四面体 -- 有点 t0、t1、t2t3——关于点p具有以下属性:

  • i,j: tix ≤ px ≤ tjx
  • i,j: tiy ≤ py ≤ tjy
  • i,j: tiz ≤ pz ≤ tjz

平均而言,这只会留下几个四面体(通常只有一两个),然后您可以使用这些四面体来应用四面体中的点测试。

【讨论】:

  • 非常感谢!你的过滤器的状况对我来说很有意义。我只是想知道你是怎么得到的。 “平均而言,这只会留下几个四面体(通常只有一两个)”。你是通过经验还是通过理论得到的?
  • 考虑到这一点时,第一个想法是按所有四面体的最小 x 坐标排序,然后很明显该点的 x 坐标必须至少是属于其包围的 x四面体。通过扩展,您会发现这对于 y 和 z 以及在两个方向上都必须是正确的。至于“一个或两个”的平均值:这只是在可视化这样一个空间时的有根据的猜测。当然,在极端情况下,许多四面体共享同一个点,甚至可能是全部,而要定位的点可能是那个点。但这只是极端情况,而不是一般情况。
  • 我明白了。另外,我认为 Lesiak 在他的 cmets 中提出的过滤约束“(minx, miny, minz)
  • 是的,那是长方体测试。用我的话说,有时可以节省时间:只要在四面体的角中找到一个不大于 px 的 x,就可以移动到下一个要求,而计算 minx,则必须始终查看在所有四个角落。显然,您可以对四面体进行预处理并存储它们的 x、y、z 的最小值/最大值,然后会以一些空间为代价更快。
【解决方案2】:

如果您打算针对同一组四面体测试很多点,我肯定会进行预处理步骤并为四面体构建空间结构。

在我的评论中我提到了八叉树,但是知道四面体填充空间(没有孔)我认为没有必要对空间进行自适应细分,最好将其分成相等的部分。

  1. 将空间分成相等的盒子(让我们将它们命名为SpaceBoxes)。
  2. 在每个SpaceBox 中,保留与框碰撞的四面体列表。
  • 为了加快速度,我会测试四面体的边界框,而不是四面体本身。
  • 请注意,这一步可以相对便宜地完成 - 您知道 SpaceBox 的大小相等,您知道它们的位置,因此给定四面体的边界框,很容易找到 SpaceBox 候选者。

现在,有了这个空间结构:

待测点p

  • 找到对应的SpaceBox O(1)
  • 您有所有与SpaceBox 碰撞的四面体,因此这些是要测试的候选对象
  • p 与每个四面体的边界框的第一次碰撞测试
  • 只有这样,与四面体本身

请注意,测试的性能主要取决于每个 SpaceBox 中四面体的数量。

假设一个空间是一个立方体:

  • 将每条边细分为 16 个部分,得到 16^3 = 4096 个空格框
  • N = 7000000,应该有大约 1709 个候选四面体要测试

此外,在实现方面,预处理和测试多点看起来都像数据并行问题,因此多处理可能会有所帮助。

【讨论】:

  • 非常感谢!您如何将您的过滤方法与下面提出的 trincot 进行比较?我觉得 trincot 似乎更容易实现,并且 trincot 提到过滤后一个只会得到 1-2 个四面体(你会得到。“1709 个候选人”)。您如何比较这两种方法的效率?
  • 此外,“盒子”是指 3D 立方体吗?另外,我不确定您在“将每个边缘细分为 16 个部分”中指的是什么“边缘”?但我想我明白你的想法——首先进行预处理。
  • 顺便说一句,我只是意识到trincot的过滤约束应该和你之前在cmets中提出的一样,即“(minx, miny, minz)
  • 1.盒子是指 3D 立方体(或矩形长方体,取决于整个空间的尺寸)。 2. 将每个边细分为 16 个部分 - 我假设空间是 3D 。您将每个维度细分为 16 个部分,因此您得到 16^3 SpaceBoxes 3。 (minx, miny, minz)
  • 5.我的想法是减少每次重复测试的边界框检查次数 - 因此,对于每个点,您只需进行约 1700 次(有 4096 个框)边界框测试,并到达通过边界框测试的相同筛选的少数候选者。 6. 在添加预处理步骤之前,一定要先从边界框测试开始。正如您所注意到的(我在最初的评论中提到),这很容易实现。也许您通过这个简单的修改获得所需的加速。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-17
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多