检测矩形棱柱的重叠

发布于 2024-11-07 07:58:05 字数 257 浏览 1 评论 0原文

给定一个 3D 坐标系和具有非负起点和非负尺寸的直角棱柱(例如,从 (0, 2, 5) 开始,尺寸为 (9, 20, 5)):如何最好地检查另一个直角棱镜是否与坐标系中已有的棱镜之一相交?最终,目标是对存在的所有棱镜执行此检查,能够测试一个棱镜应该足以完成此任务。

信息:起始点和大小是非负长整型的三元组。我正在寻找一种速度适中的优雅解决方案。

我的项目是用java编写的,但是任何数学公式、伪代码或描述都绰绰有余。

Given a 3D coordinate system and rectangular prisms with a non-negative starting point and a non-negative size (e.g. starts at (0, 2, 5) and has a size of (9, 20, 5)): how can I best check if another rectangular prism intersects with one of the prisms already in the coordinate system? Eventually, the goal would be to perform this check for all prisms present, being able to test one should be sufficient to complete this task.

Info: starting points and sizes are 3-tuples of non-negative longs. I am looking for an elegant solution that is moderately fast.

My project is in java, but any math formula, pseudo code or description is more than enough.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦一生花开无言 2024-11-14 07:58:05

适用于大型数据集的良好算法方法

将棱镜存储在 R-Tree 中。对于直角同轴棱镜,搜索和插入的顺序应为log(n)

R-Tree (wikipedia)

有一些用于 R-Tree 的 Python 包。使用 Rtree 0.6.0,您的代码将非常简单:

>>> from rtree import Rtree
>>> idx = Rtree()
>>> minx, miny, maxx, maxy = (0.0, 0.0, 1.0, 1.0)
>>> idx.add(0, (minx, miny, maxx, maxy))
>>> list(idx.intersection((1.0, 1.0, 2.0, 2.0)))
[0L]
>>> list(idx.intersection((1.0000001, 1.0000001, 2.0, 2.0)))
[]

实用而快速的

方法sqlite 数据库中的数据,可以在文件或在内存使用很少的代码行(有许多java实现)。创建名为 prisms 的表,其列为 idmin_xmin_ymin_zmax_xmax_ymax_z。为每一行建立索引。

插入是O(1),检查交集遵循Magnus Skog 的方法,给定 new_min_x, new_min_y, new_min_z, new_max_x, new_max_y,new_max_z

SELECT COUNT(*) FROM prisms
   WHERE (new_min_x BETWEEN min_x and max_x OR new_max_x BETWEEN min_x and max_x)
   AND   (new_min_y BETWEEN min_y and max_y OR new_max_y BETWEEN min_y and max_y)
   AND   (new_min_z BETWEEN min_z and max_z OR new_max_z BETWEEN min_z and max_z)

Nice algorithmic approach for large data sets

Store your prisms in an R-Tree. For rectangular co-axial prisms, the search and insertion should be in the order of log(n).

R-Tree (wikipedia)

There are some Python packages for R-Trees. Using Rtree 0.6.0, your code would be as simple as:

>>> from rtree import Rtree
>>> idx = Rtree()
>>> minx, miny, maxx, maxy = (0.0, 0.0, 1.0, 1.0)
>>> idx.add(0, (minx, miny, maxx, maxy))
>>> list(idx.intersection((1.0, 1.0, 2.0, 2.0)))
[0L]
>>> list(idx.intersection((1.0000001, 1.0000001, 2.0, 2.0)))
[]

Practical yet fast approach

Store your data in a sqlite database, which can be created in a file or in memory using very few lines of code (there are many java implementations). Create table called, say, prisms, whose columns would be id, min_x, min_y, min_z, max_x, max_y, max_z. Index each row.

Insertion is O(1), and checking for intersection follows Magnus Skog's approach, Given new_min_x, new_min_y, new_min_z, new_max_x, new_max_y, new_max_z:

SELECT COUNT(*) FROM prisms
   WHERE (new_min_x BETWEEN min_x and max_x OR new_max_x BETWEEN min_x and max_x)
   AND   (new_min_y BETWEEN min_y and max_y OR new_max_y BETWEEN min_y and max_y)
   AND   (new_min_z BETWEEN min_z and max_z OR new_max_z BETWEEN min_z and max_z)
深海蓝天 2024-11-14 07:58:05

假设你有两个棱镜 A 和 B。如果 B 与 A 相交,则不能完全向右、向左、向上、向下等。

if not (B.x > A.x+A.dx or B.x+B.dx < A.x or
        B.y > A.y+A.dy or B.y+B.dy < A.y or
        B.z > A.z+A.dz or B.z+B.dz < A.z)
        // B intersects A

Lets say you have two prisms A and B. If B intersects A it's the negation of not being completely to the right, left, up, down etc.

if not (B.x > A.x+A.dx or B.x+B.dx < A.x or
        B.y > A.y+A.dy or B.y+B.dy < A.y or
        B.z > A.z+A.dz or B.z+B.dz < A.z)
        // B intersects A
小梨窩很甜 2024-11-14 07:58:05

(0, 2, 5) 开始、尺寸为 (9, 20, 5) 的棱柱以 (9, 22, 10 )

要检查重叠棱镜(A 和 B),请使用它们的起点和终点。两个棱镜必须在所有维度上重叠。

要检查 X 维度上的重叠,请使用以下命令:

If (A.startX <= B.endX) and (B.startX <= A.endX) 

因此:

If 
      (A.startX <= B.endX) and (B.startX <= A.endX) 
  and (A.startY <= B.endY) and (B.startY <= A.endY) 
  and (A.startZ <= B.endZ) and (B.startZ <= A.endZ) 
Then
    (A and B overlap)

当两个棱镜只有一个公共点时,上述检查将得出True结果。如果您不希望这样,并且希望重叠空间不仅仅是一个点、一条线段或一个矩形表面,而是一个棱柱,则将 <= 替换为 < ; .

The prism that starts at (0, 2, 5) and has a size of (9, 20, 5) is ending at (9, 22, 10).

To check for overlapping prisms (A and B), use the start and end points of these. The two prisms have to overlap in all dimensions.

To check overlapping in X dimension, use this:

If (A.startX <= B.endX) and (B.startX <= A.endX) 

Therefore:

If 
      (A.startX <= B.endX) and (B.startX <= A.endX) 
  and (A.startY <= B.endY) and (B.startY <= A.endY) 
  and (A.startZ <= B.endZ) and (B.startZ <= A.endZ) 
Then
    (A and B overlap)

The above check will result True when the two prisms have even only one point in common. If you don't want that and you want the overlapping space to be more than just a point or a line segment or a rectangular surface, but a prism, then replace <= with < .

一口甜 2024-11-14 07:58:05

与检查线上的线段的方法相同。如果 B 的起点或终点位于 A 的起点和终点之间,则它们重叠。

唯一的区别是它们必须在所有三个维度上重叠。

The same way you'd do to check segments on a line. If the start or end of B is between the start and end of A, they overlap.

The only difference is that they have to overlap in all three dimensions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文