Algorithm 用于查询位于三角形内的点的数据结构

Algorithm 用于查询位于三角形内的点的数据结构,algorithm,optimization,graphics,data-structures,spatial-query,Algorithm,Optimization,Graphics,Data Structures,Spatial Query,我有一些2D数据,其中包含光栅化为像素的边。我想实现一个高效的数据结构,返回位于非轴对齐的2D三角形中的所有边缘像素 该图像显示了问题的可视化,其中白色表示栅格化边,红色表示查询三角形。结果将是位于边界上或红色三角形内部的所有白色像素 当进一步查看图像时,我们注意到我们有稀疏布尔数据,这意味着如果我们用0表示黑色像素,用1表示白色像素,那么数据中的1s数远低于0s数。因此,栅格化红色三角形并检查其内部的每个点是白色还是黑色并不是最有效的方法 除了数据的稀疏性;由于白色像素源自边缘,因此它们本

我有一些2D数据,其中包含光栅化为像素的边。我想实现一个高效的数据结构,返回位于非轴对齐的2D三角形中的所有边缘像素

该图像显示了问题的可视化,其中白色表示栅格化边,红色表示查询三角形。结果将是位于边界上或红色三角形内部的所有白色像素

  • 当进一步查看图像时,我们注意到我们有稀疏布尔数据,这意味着如果我们用0表示黑色像素,用1表示白色像素,那么数据中的1s数远低于0s数。因此,栅格化红色三角形并检查其内部的每个点是白色还是黑色并不是最有效的方法

  • 除了数据的稀疏性;由于白色像素源自边缘,因此它们本质上是连接在一起的。但是,在与其他线路的连接处,它们有两个以上的邻居。交叉点处的像素只应返回一次

  • 数据必须实时处理,但不需要GPU协助。对于不同的三角形内容,将有多个查询,每次查询后,点可能会从数据结构中删除。但是,初始填充数据结构后,将不再插入新点

  • 当光栅化边到达时,查询三角形已为人所知

  • 查询三角形比数据边多

有很多可用的。然而,我想知道,哪一个是最好的一个为我的问题。我愿意实现一个高度优化的数据结构来解决这个问题,因为它将是项目的核心元素。因此,也欢迎混合或缩写数据结构

  • 似乎是迄今为止我发现的解决这个问题的最佳数据结构,因为它们支持基于矩形的查询。我将检查查询三角形的AABB内的所有白色像素,然后检查返回的每个像素是否位于查询矩形内

    然而,我不确定R-树的表现如何,因为基于边缘的数据不容易分组成矩形,因为这些点在窄线上聚集在一起,而不是展开

    我不确定使用有关查询三角形的信息预先构建R树的结构是否有意义,该信息将在结构填充后立即生成(如前所述,数据到达时查询三角形已经已知)

  • 扭转这个问题似乎也是一个有效的解决方案,我使用一棵树为每个白色像素获取包含它的所有三角形的列表。然后,它可以存储在所有这些结果集中,并在查询到达时立即返回。但是,我不确定这是如何执行的,因为三角形的数量高于边的数量,但仍然低于白色像素的数量(因为边大部分被分割为约20-50个像素)

  • 利用白色像素通常具有白色像素作为邻居的数据结构似乎是最有效的。然而,直到现在我才发现关于这样一件事的任何东西


将查询三角形分解为n*3行。对于测试中的每个点,您可以估计它位于每条线的哪一侧。其余的是布尔逻辑

编辑:由于您的点是光栅化的,您可以在扫描线进入或离开特定查询三角形的位置预先计算扫描线上的点(=穿过上面3n条线中的一条,&&位于参与该特定三角形的其他两条线的“内部”)

更新:由另一个主题()触发,我将添加代码来证明非凸情况可以用“点在每一行的哪一侧”来表示。因为我很懒,所以我会用L形。IMHO其他非凸形状也可以进行类似处理。这些线平行于X轴和Y轴,但这同样是懒惰

/*

Y
| +-+
| | |
| | +-+
| |   |
| +---+
|
0------ X
the line pieces:
Horizontal:
(x0,y0) - (x2,y0)
(x1,y1) - (x2,y1)
(x0,y2) - (x1,y2)
Vertical:
(x0,y0) - (x0,y2)
(x1,y1) - (x1,y2)
(x2,y0) - (x2,y1)

The lines:
(x==x0)
(x==x1)
(x==x2)
(y==y0)
(y==y1)
(x==y2)

Combine them:
**/

#define x0 2
#define x1 4
#define x2 6

#define y0 2
#define y1 4
#define y2 6

#include <stdio.h>

int inside(int x, int y)
{   

switch(  (x<x0 ?0:1)
    +(x<x1 ?0:2)
    +(x<x2 ?0:4)
    +(y<y0 ?0:8)
    +(y<y1 ?0:16)
    +(y<y2 ?0:32) ) {

case 1+8:
case 1+2+8:
case 1+8+16:
    return 1;
default: return 0;
    }
}

int main(void)
{
int xx,yy,res;
while (1) {
     res = scanf("%d %d", &xx, &yy);
     if (res < 2) continue;
     res = inside(xx, yy);
     printf("(%d,%d) := %d\n", xx, yy,res);
    }
return 0;
}
/*
Y
| +-+
| | |
| | +-+
| |   |
| +---+
|
0---X
线条部分:
水平:
(x0,y0)-(x2,y0)
(x1,y1)-(x2,y1)
(x0,y2)-(x1,y2)
垂直:
(x0,y0)-(x0,y2)
(x1,y1)-(x1,y2)
(x2,y0)-(x2,y1)
台词:
(x==x0)
(x==x1)
(x==x2)
(y==y0)
(y==y1)
(x==y2)
将它们结合起来:
**/
#定义x02
#定义x14
#定义x2 6
#定义y02
#定义y1 4
#定义y2 6
#包括
内部整数(整数x,整数y)
{   

switch((x有两个计算几何算法,我认为串联起来会得到很好的结果

  • 计算包含所有三角形边的平面细分。(这比计算三角形边的所有交点稍微复杂一些。)对于每个面,列出包含该面的三角形。这是公认的最坏情况立方,但只有当三角形重叠很多时才是如此(我忍不住认为有一种方法可以把它压缩成二次型)

  • 定位细分中的每个像素(即,找出它所属的面)。每个边中的第一个像素将花费O(logn),但如果之后有局部性,可能有一种方法可以将计算简化为平均类似O(1)的值。(例如,如果使用梯形方法,如果存储了包含最后一点的梯形列表,则可以遍历列表,直到找到包含当前点的梯形并向下工作。通过在插入点附近传递迭代器来比较提示到C++ STL集插入。)< /P>

  • 扫描线方法不会很快。想象一下上面示例中的水平扫描线方法。大多数白色像素不会在三角形内。运行时复杂