如何识别二维中两个矩形重叠区域的边界点?
我希望返回二维中两个任意矩形之间重叠区域的边界点的坐标。解决这个问题的最佳方法是什么,可以处理所有特殊情况,例如:
- 仅在单个顶点上相交的矩形? (程序必须返回单独的顶点)
- 共享整个或部分边的矩形? (程序必须返回公共线段的端点)
为了增加复杂性,它必须以顺时针/逆时针顺序对点进行排序。因此,我可以在报告之前使用凸包算法对它们进行排序,但如果有一种算法可以直接按顺序找出边界点,那就最好了!
我应该考虑哪些途径有什么想法吗?我不是在寻找代码项目等,只是寻找通用算法的一般概念,我不必保留很多 如果“特殊情况”则“执行此操作”
类型的代码。
编辑:矩形是任意的 - 即它们可能/可能不平行于 X/Y 轴...
I'm looking to return the coordinates of the points bounding the area of overlap between 2 arbitrary rectangles in 2D. Whats the best way to approach this that would take care of all the special cases eg:
- Rectangles intersecting only on a single vertex ? (the program would have to return the lone vertex)
- Rectangles which share whole or part of a side ? (the program would have to return the endpoints of the common line segment)
To add to the complexity, it has to order the points in either clockwise/anticlockwise order. As such, I can use a convex hull algorithm to order them before reporting, but if there's an algorithm that can figure out the bounding points in order directly, that'll be the best !!
Any ideas of what avenues I should be looking at ? I'm not looking for code projects etc, only a general idea of a generic algorithm for which I don't have to keep a lot ofif "special case" then "do this"
kind of code.
EDIT: The rectangles are arbitrary - i.e. they may/may not be parallel to X/Y axis...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用一般的凸多边形相交方法即可。查找
相交凸多边形旋转卡尺
。Just use the general convex polygon intersection method. Look up
intersect convex polygons rotating calipers
.好吧,我们再试一次...
考虑两者的并集,由通过从 ABCD(黑色)中的每个顶点到 EFGH(红色)的每个顶点绘制一条线来定义的区域组成:
这里困难的部分是想出由这些线定义的所有形状(灰线和来自 ABCD 的原始线)和 EFGH 矩形。)
一次你弄清楚了,创建这些形状的链接列表,并假设这些形状中的每一个都存在于交叉点内。
第 1 步。 翻译并翻译旋转所有物体,使 ABCD 在 0,0 处有一个顶点,并且其线平行/垂直于 x 轴和 y 轴。
步骤 1A。 找到 ABCD 中 y 值最低的顶点,然后从场景中的所有其他顶点中减去它。为了演示目的,我们假设该顶点是 C。通过从场景中的每个顶点减去 C,我们将有效地将原点 (0,0) 移动到 C,从而使围绕 C 的旋转变得容易。
步骤 1B。围绕原点旋转所有物体,旋转角度等于 C→B 向量与 x 轴之间的角度,使 B 落在 x 轴上:
如果 ABCD 顶点是顺时针标记,ABCD 顶点现在应该如下所示:(
如果它们没有顺时针标记,那么步骤 2 中的“位于”检查将不起作用,因此请确保在
atan2(...)
调用是从最低顶点逆时针计算顶点。)第 2 步。 现在我们可以轻松分析形状是否位于 ABCD 矩形内,例如
if (thisVert.x >= 0 && thisVert.y >= 0 && thisVert.x <= ABCDx && thisVert.y <= ABCDy)
。遍历形状的链接列表,并检查以确保每个形状的每个顶点都位于 ABCD 内。如果形状的一个顶点不在 ABCD 内,则该形状不是 ABCD/EFGH 交集的一部分。将其标记为不属于交叉点并跳到下一个形状。步骤 3. 撤消步骤 1B 中的旋转,然后撤消步骤 1A 中的平移。
步骤 4. 使用 EFGH 而不是 ABCD 重复步骤 1-3,您将设置交集。
如果两个集合之间的唯一交集是一条线,那么上面将不会返回任何交集。如果交集 == NULL,则检查相交的线。
如果交集仍然为 NULL,则检查交点。
Alright, we'll try this again...
Consider a union of the two, made up of areas defined by drawing a line from every vertex in ABCD (in black) to EFGH (in red):
The hard part here is coming up with all of the shapes defined by these lines (both the gray lines and the original lines coming from the ABCD and EFGH rectangles.)
Once you figure that out, create a linked list of these shapes, and assume every one of these shapes exists within the intersection.
Step 1. Translate & rotate everything so that ABCD has one vertex on 0,0 and its lines are parallel/perpendicular to the x and y axes.
Step 1A. Find the lowest y-value vertex in ABCD, and then subtract it from all other verts in the scene. Let's assume for the purposes of demonstration that that vertex is C. By subtracting C from every vertex in the scene, we will effectively move the origin (0,0) to C, making rotation around C easy.
Step 1B. Rotate everything about the origin by an angle equal to the angle between the C->B vector and the x-axis, so that B lands on the x-axis:
If ABCD vertices were labelled clockwise, the ABCD vertices should now look like this:
(If they were not labeled clockwise, then the "lies within" check in Step 2 won't work, so make sure the vert used in the
atan2(...)
call is the vertex counterclockwise from the lowest vertex.)Step 2. Now we can easily analyze whether or not a shape lies within the ABCD rectangle, e.g.
if (thisVert.x >= 0 && thisVert.y >= 0 && thisVert.x <= ABCDx && thisVert.y <= ABCDy)
. Traverse the linked list of shapes, and check to make sure each vertex of each shape lies within ABCD. If one vertex of a shape does not lie within ABCD, then that shape is not part of the ABCD/EFGH intersection. Mark it as not part of the intersection and skip to the next shape.Step 3. Undo the rotation from Step 1B, then undo the translation from Step 1A.
Step 4. Repeat Steps 1-3 with EFGH instead of ABCD, and you will have your intersection set.
If the only intersection between the two sets is a line, then the above will return nothing as an intersection. If the intersection == NULL, then check for lines that intersect.
If the intersection is still NULL, then check for intersecting points.
这可能真的很粗糙但是:
This is probably really rough but:
找到矩形线段的所有交点。结果由其中一些顶点和一些初始顶点组成。要找到它们,只需检查位于两个矩形中的每个点即可。删除不必要的点(如果一条线上有 3 个或更多点)。结果是凸的,并且您得到的点都不是严格位于其内部的,因此(如果至少有 3 个点)按角度对某个内部点进行排序并享受结果。
Find all the intersections of segments of rectangles. The result consists of some of them and some of initial vertices. To find them just check for every point it lies in both rectangles. Remove unnecessary points (if there are 3 or more on one line). The result is convex and no point you get is strictly inside it, so (if there are at least 3 of them) sort points from some inner point by angle and enjoy the result.
我想出了一个合理的方法,应该涵盖所有可能的情况:
我们需要的基本上是 3 个步骤:
步骤 1:
步骤 2:
步骤 3:
现在,对结果数组进行排序,然后返回
对于步骤 2 和步骤 2: 3(如何查找一个点是否位于矩形内)-我会使用 这篇优秀的文章(其中提到的最后一个算法)。
I've come up with a reasonable method that should cover all possible cases:
All we need is basically 3 steps :
Step 1:
Step 2:
Step 3:
Now, order the results array, and return
For step 2 & 3 (how to find if a point lies inside a rectangle) - I'd use this excellent article (the last algorithm stated there).