我的矩形结构包含以下成员: x,y,宽度,高度。
给出点x,y 知道x,y是否在矩形内部的最快方法是什么?我会做很多这些,所以速度很重要。
答案 0 :(得分:6)
这就是我通常这样做的方式。给定一个在矩形之外的点,这将在4个案例中的3个中进行较少的测试。有时只进行一次测试。
if(point.x < rect.x) return false;
if(point.y < rect.y) return false;
if(point.x >= rect.x + rect.width) return false;
if(point.y >= rect.y + rect.height) return false;
return true;
您使用哪一个应该取决于您是否预期会发生更多碰撞或更多未命中。
答案 1 :(得分:1)
if (p.x > x && p.y > y && p.x < x+width && p.y < y+height)
这应该只是少数装配说明。
假设矩形的x,y始终是矩形的最小值坐标。它还可以折扣矩形边框上的点。
答案 2 :(得分:1)
在C ++中(可以简单地翻译成C):
bool pointInRectangle( Point const & p, Rectangle const & r ) {
return
((r.x <= p.x) && (p.x <= (r.x + r.width ))) &&
((r.y <= p.y) && (p.y <= (r.y + r.height)));
}
答案 3 :(得分:1)
我在编写比赛时找到了两个更好的答案。首先,它使用两个点的坐标,而不是缓慢的高度/宽度,这也假设一个点是两个浮点数,一个矩形是四个浮点数;对于不同的数据类型,可能需要更改此逻辑!
首先,使用了解英特尔SSE指令的编译器,结合&amp; amp;和&amp;&amp;以正确的方式更快。这将两个测试组合成一个,但保持快速进行后两个测试:
if((p.x>=r.lx)&(p.x<=r.hx)&&(p.y>=r.ly)&(p.y<=r.hy))
ptisinrect=true;
目前,使用128位SSE指令进行编译比使用所有&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&nbsp;更快,但使用256位AVX2设置的速度较慢,即使使用全部&amp;&#39; p>
但是,如果将程序设置为测试阵列中的大量点,则可以使其完全向量化并显着提高性能(仍然使用SSE,而不是AVX或AVX2)。矢量化是一种简单的并行化,具有一些严格的要求。例如,循环中不会出现短路,并且您不能多次保存到同一变量。
请看一下这个非矢量化代码的简化示例,该代码可以查找&#39; count&#39;如果找到足够的信息并退出:
for(unsigned a=0;a<n;++a)
{
if((pp[a].x>=r.lx)&&(pp[a].x<=r.hx)&&(pp[a].y>=r.ly)&&(pp[a].y<=r.hy))
{
++found;
if(found>count)
return true;
}
}
下面的代码是同一个例子的例子,只是将0到n个ptinrects的搜索向量化,但是当&#39; count&#39;找到矩形中的点。请注意,此代码可以读取超过n的32个点,因此需要为该数组分配32个额外的空间点:
typedef struct ab
{
int64_t a[4];
};
typedef struct{
union{
ab ab;
int8_t o[32];
};
}xmmb;
xmmb o;
for(unsigned i=0;i<n;i+=32)
{
for(unsigned a=0;a<32;++a)
{
o.o[a]=((pp[i+a].x>=r.lx)&(p[i+a].x<=r.hx)&(p[i+a].y>=r.ly)&(p[i+a].y<=r.hy));
}
for(unsigned kk=0;kk<4;++kk)
{
if(o.ab.a[kk])
for(unsigned a=kk<<3;a<(kk+1)<<3;++a)
{
if(o.o[a])
{
if(i+a<n)
{
++found;
if(found>count)
return true;
}
}
}
}
}
即使看起来很奇怪,这段代码比上一个例子快得多! 它正在做的是在向量并行中运行ptrect测试并将true / false存储在32个8位字节的数组中。然后它一次检查8个(因此使用4个64位的联合)来保存测试。然后查看具有真值的任何值并将它们添加到计数中。
再次注意,这仅适用于128位SSE,并且当编译为256位AVX2时,目前(2015年2月)较慢,因此请使用开关或编译指示来保持SSE 最后,这段代码可能有语法错误之类的东西,因为将它输入这种格式并不容易切割:D
标签:快速ptinrect快速点在矩形中的快点
答案 4 :(得分:0)
如果您要定位特定的CPU,例如x86,您可以使用SIMD(即SSE)进行非常快速的无分支测试。诀窍是使用4 x 32位整数来表示矩形,该矩形映射到SIMD向量(它需要16字节大小和16字节对齐)。