微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用快速“开放空间”查找来表示多维范围的数据结构?

如何解决用快速“开放空间”查找来表示多维范围的数据结构?

所以我希望在 N 维空间中表示非重叠范围。

我认为 Cgal 具有此功能,并有助于快速查询点,如下例所示。

我不确定如何扩展这种查询以查找打开的窗口。

所以在这种情况下,我制作了 2 个矩形,如果有办法找到特定大小的开口就好了。

#include <Cgal/Cartesian.h>
#include <Cgal/Segment_tree_k.h>
#include <Cgal/Range_segment_tree_traits.h>
typedef Cgal::Cartesian<double> K;
typedef Cgal::Segment_tree_map_traits_2<K,char> Traits;
typedef Cgal::Segment_tree_2<Traits > Segment_tree_2_type;
int main()
{
  typedef Traits::Interval Interval;
  typedef Traits::Pure_interval Pure_interval;
  typedef Traits::Key Key;
  std::list<Interval> InputList,OutputList1,OutputList2;
  InputList.push_back(Interval(Pure_interval(Key(1,2),Key(1,2)),'a'));
  InputList.push_back(Interval(Pure_interval(Key(2,3),Key(2,3)),'b'));
  Segment_tree_2_type Segment_tree_2(InputList.begin(),InputList.end());
  // ??? probably has multiple solutions?
  Interval find_me=Interval(Pure_interval(Key(0,Key(0,1)),'');
  Interval opening = Segment_tree_2.find_opening(find_me);
  return 0;
}

解决方法

我认为 CGAL 库中的 Segment Tree 不能帮助您解决这个问题,因为此树旨在仅执行两种类型的查询(window_queryenclosing_query)。在这两种情况下,搜索过程都返回原始 D 维区间集的子集,用于构建树 - 但是您对这些区间“之间”的开放空间感兴趣,该数据结构未明确表示.

问题与您所问的问题类似,在计算几何中研究了很长时间 - 最简单的情况是在平面上的一组点中找到最大(按面积或按周长)的空矩形。这个问题的泛化也被研究过——对于更一般的障碍物(线段、矩形、多边形)和更高的维度。有关详细信息(包括参考资料),请参阅此 Wikipage

但是,查找最大的矩形对您来说可能是多余的 - 任何 大小大于或等于给定大小的矩形就足够了,并且与最大矩形搜索相比,它会为您节省一些时间。如果您的矩形集是静态的,但您希望找到的空矩形的大小各不相同,那么将这个集合预处理为某种数据结构(如上所述)是有意义的。在一些出版物中,他们提出了找到所有最大空矩形并将它们保存在列表中的算法。最大空矩形定义为一个矩形,在不与障碍物相交的情况下不能向任何方向延伸。抱歉,我找不到任何可以免费访问的此类出版物。

我建议使用一个简单的递归算法,它可以找到一个宽度和高度大于或等于请求大小的空矩形。思路是从矩形集合的边界框开始,从这个集合中一个一个处理矩形。从当前的空矩形中减去每个这样的矩形,但是这种减法的结果表示为一组最大的矩形,它们可能重叠。例如,矩形[0,2)x[0,2)减去矩形[1,3)x[1,3)的结果是两个矩形[2,3)[1,3)x[2,3)的集合。该算法返回一个空矩形和一个布尔标志,指示成功或失败。

using RVec = std::vector<Rectangle>;
using Result = std::pair<Rectangle,bool>;

Result find(const RVec& V,double W,double H,const Rectangle& R,unsigned J)
{
  if (R.sizeIsLess(W,H))
  {
    // ------ the empty rectangle R is too small
    return {R,false};
  }
  else if (J < V.size())
  {
    // ------ process the obstacle rectangle with number J
    for (const auto& r: subtract(R,V[J]))
    {
      const auto res = find(V,W,H,r,J + 1);
      if (res.second) return {res.first,true};
    }
    return {R,false};
  }
  else
  {
    // ------ the empty rectangle R is big enough,and all the obstacles are processed
    return {R,true};
  }
}

auto find(const RVec& V,double H)
{
  return find(V,bbox(V),0);
}

我无法证明该算法对于任何可能的矩形障碍物组以及任何请求的宽度和高度都能正常工作,但它在我的所有测试中都运行良好。该算法是递归的,因此对于非常大的矩形集来说,有限的堆栈大小可能是一个问题。

可以通过打乱矩形集和/或矩形减法的结果来随机化算法——然后你可能会得到给定矩形集和给定宽度和高度的多个解决方案。该算法也可以扩展到更高的维度——然后需要修改函数 subtract。如果您有兴趣,我会将这个功能(用于 2D 案例)添加到这个答案中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?