C++ 空间中的相交矩形

C++ 空间中的相交矩形,c++,data-structures,spatial,C++,Data Structures,Spatial,我需要将100万个空间多边形(使用它们的最小边界矩形指定)与空间中4个完全不相交的MBR(MBR1、MBR2、MBR3、MBR4)相交。MBR1、MBR2、MBR3和MBR4将整个空间划分为4个不相交的部分。为此,我编写了以下代码。然而,事实证明,对于100万点,代码运行速度非常慢。是否有某种方法可以改进代码,使其运行得更快一些。如果是的话,那么有人能帮我做同样的事情吗 //-------------------------------------------------------------

我需要将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分钟,然后我会真正使用。空间索引,请参见上面的“我的更新”。