C++ 空间中的相交矩形
我需要将100万个空间多边形(使用它们的最小边界矩形指定)与空间中4个完全不相交的MBR(MBR1、MBR2、MBR3、MBR4)相交。MBR1、MBR2、MBR3和MBR4将整个空间划分为4个不相交的部分。为此,我编写了以下代码。然而,事实证明,对于100万点,代码运行速度非常慢。是否有某种方法可以改进代码,使其运行得更快一些。如果是的话,那么有人能帮我做同样的事情吗C++ 空间中的相交矩形,c++,data-structures,spatial,C++,Data Structures,Spatial,我需要将100万个空间多边形(使用它们的最小边界矩形指定)与空间中4个完全不相交的MBR(MBR1、MBR2、MBR3、MBR4)相交。MBR1、MBR2、MBR3和MBR4将整个空间划分为4个不相交的部分。为此,我编写了以下代码。然而,事实证明,对于100万点,代码运行速度非常慢。是否有某种方法可以改进代码,使其运行得更快一些。如果是的话,那么有人能帮我做同样的事情吗 //-------------------------------------------------------------
//---------------------------------------------------------------------------
struct MBR
{
double xRight, xLeft, yBottom, yTop;
};
bool intersects(MBR spatialId,MBR mbr)
{
if (mbr.yBottom > spatialId.yTop || mbr.yTop < spatialId.yBottom) return false;
if (mbr.xLeft > spatialId.xRight || mbr.xRight < spatialId.xLeft) return false;
return true;
}
//---------------------------------------------------------------------------
bool contains(MBR spatialId,MBR mbr)
{
if (mbr.yBottom > spatialId.yBottom || mbr.yTop < spatialId.yTop) return false;
if (mbr.xLeft > spatialId.xLeft || mbr.xRight < spatialId.xRight) return false;
return true;
}
//---------------------------------------------------------------------------
bool touches(MBR spatialId,MBR mbr)
{
if ( (mbr.yBottom >= spatialId.yBottom + std::numeric_limits<double>::epsilon() &&
mbr.yBottom <= spatialId.yBottom - std::numeric_limits<double>::epsilon()) ||
(mbr.yTop >= spatialId.yTop + std::numeric_limits<double>::epsilon() &&
mbr.yTop <= spatialId.yTop - std::numeric_limits<double>::epsilon()))
return true;
if ( (mbr.xLeft >= spatialId.xLeft + std::numeric_limits<double>::epsilon() &&
mbr.xLeft <= spatialId.xLeft - std::numeric_limits<double>::epsilon()) ||
(mbr.xRight >= spatialId.xRight + std::numeric_limits<double>::epsilon() &&
mbr.xRight <= spatialId.xRight - std::numeric_limits<double>::epsilon()))
return true;
return false;
}
//---------------------------------------------------------------------------
MBR MBR1,MBR2,MBR3,MBR4;
vector<unsigned> spatialIds; //contain 1 million spatial identifiers which are intersected with MBR1, MBR2, MBR3, MBR4
//MBR1, MBR2, MBR3, MBR4 are again specified using their Minimum Bounding Rectangles
vector<unsigned> result; //contains the resulting intersecting spatial ids
for(vector<MBR>::iterator itSpatialId=spatialIds.begin(),lSpatialId=spatialIds.end();itSpatialId!=lSpatialId;++itSpatialId)
{
if(intersects((*itSpatialId),MBR1)||contains((*itSpatialId),MBR1)||touches((*itSpatialId),MBR1))
{
result.push_back((*itSpatialId));
}
if(intersects((*itSpatialId),MBR2)||contains((*itSpatialId),MBR2)||touches((*itSpatialId),MBR2))
{
result.push_back((*itSpatialId));
}
if(intersects((*itSpatialId),MBR3)||contains((*itSpatialId),MBR3)||touches((*itSpatialId),MBR3))
{
result.push_back((*itSpatialId));
}
if(intersects((*itSpatialId),MBR4)||contains((*itSpatialId),MBR4)||touches((*itSpatialId),MBR4))
{
result.push_back((*itSpatialId));
}
}
//---------------------------------------------------------------------------
结构MBR
{
双X右,X左,Y右,Y右;
};
布尔交叉点(MBR空间ID,MBR MBR)
{
if(mbr.yBottom>spacealid.yTop | | mbr.yTopspacealid.xRight | | mbr.xRightspacealid.yBottom | | mbr.yTopspacealid.xLeft | | mbr.xRight=spatialId.yBottom+std::numeric_limits::epsilon()&&
mbr.yBottom=spacealid.yTop+std::numeric_limits::epsilon()&&
mbr.yTop=spacealid.xLeft+std::numeric_limits::epsilon()&&
mbr.xLeft=spacealid.xRight+std::numeric_limits::epsilon()&&
mbr.xRight我认为可以简化交叉测试
首先,我认为比较两个值时不需要ε
,比较运算符不会引入任何数值错误
其次,您只需检查以下内容:
bool intersectsContainsOrTouches(MBR spatialId,MBR mbr)
{
return (mbr.yBottom <= spatialId.yTop && mbr.yTop >= patialId.yBottom) &&
(mbr.xLeft <= spatialId.xRight && mbr.xRight >= spatialId.xLeft);
}
bool intersects containsortouches(MBR spatialId,MBR MBR)
{
返回(mbr.yBottom=patialId.yBottom)和
(mbr.xLeft=spacealid.xLeft);
}
通常,您会使用BSP或多维索引来执行空间“连接”操作。但是,由于您只有4个矩形可以连接,因此简单地遍历所有1M矩形并将每个矩形与4个MBR进行比较应该会更快。
我不确定多维索引或二进制空间分区是否有帮助
顺便问一下,需要多长时间?显然应该不到一分钟,这是个问题吗
编辑
如果必须重复执行此操作,我会将数据放入空间索引中,然后可以对每个MBR的索引执行四个窗口查询。
还有专门的算法,例如。
如果您使用的是Java,请查看my(在添加/删除或移动单个矩形时也很好。对于其他语言,请检查R-Tree(R+树、X-Tree等)、kd树或四叉树
< C++ >,你可以看看。这是一个3D游戏物理引擎,内部有几种算法来检测MBR重叠(四叉树,SAP空间,…)。这个问题太宽了。有很多方法可以改善时间。如果你的100万个MBR是相对固定的(我假设小行星或一些这样的),您可以对它们的位置进行排序,并使用二进制空间分区,简单地拒绝大量可能的冲突。StackOverflow适用于有一个确切、具体答案的问题。照目前的情况,没有答案可以标记为“正确”@StevenHansen非常感谢您的帮助。我如何对位置进行排序并应用二进制搜索。我是空间领域的新手。如果可能,如果您能帮我一点忙,我将不胜感激。我自己做了很多尝试,但我无法确定互联网上有大量的文章和教程。请尝试谷歌二进制空间分区教程"如果你在你的实现中停留在一个特定的位置,这将是StAdvExcel中的帖子变得有用的地方,尽管我会认为BSP更像是一个游戏编程主题。我需要对MBR1、MBR2、MBR3和MBR4的不同空间点一遍又一遍地运行测试。因此,它花费了30分钟,然后我会真正使用。空间索引,请参见上面的“我的更新”。