【问题标题】:Find nearby rectangles on X-Y plane在 X-Y 平面上查找附近的矩形
【发布时间】:2015-12-14 18:06:08
【问题描述】:

我在 x-y 平面上有几个矩形。有一个参考矩形。参考矩形的位置是可变的。我需要有效的方法来找到

  • 在参考矩形左侧找到的第一个矩形。
  • 在参考矩形右侧找到的第一个矩形。
  • 在参考矩形的顶部找到的第一个矩形。
  • 在参考矩形底部找到的第一个矩形。

伪代码或 Java 代码都可以。 强调的是比占用空间更快的代码。
解决一侧将解决其他 3 个方面。 假设,我们需要找到位于“REFERENCE RECT”左侧的最近矩形列表。 “REFERENCE RECT”是可移动的。 所有其他矩形在计算时都是静止的。

附言。每个框都可以是“REFERENCE RECT”。盒子一次一个地添加到 X-Y 平面。

【问题讨论】:

  • 请详细说明“在参考矩形左侧找到的第一个矩形”究竟是什么。由此,它可能意味着至少 4 个不同的东西。
  • 如果我按照规范进行编码,我通常希望我的时间能够得到报酬。少说一点,这是一个 help 网站,而不是 do-your-homework-for-you 网站。向我们展示代码,告诉我们您遇到的问题。
  • 如果你了解链表的概念,你可以使用它。除了链表中的 nextNode 和 previousNode,您还添加了一个 upperNode 和 lowerNode。
  • @dcsohl ,这不是你为钱解决的家庭作业。这是一个现实世界的问题。我正在询问合适的社区,他们可能会在算法/想法或代码方面提供帮助。如果您认为您有解决问题的想法,欢迎您。
  • 我怀疑您正在寻找类似 R-Tree 或四叉树之类的东西。

标签: java algorithm user-interface search shape


【解决方案1】:

此伪代码在设置期间可能不会很快 (O(N^2)),但一旦构建了 NearestBoxes,它就会胜过其他任何东西(因为它不需要重新计算任何东西)。当心拼写错误 - 我没有测试过这个。

public enum RPos { Up, Down, Left, Right };

public class Box {
    int x1, x2, y1, y2;        
    boolean isRelative(b, RPos rp) {
       // returns true if b can be said to be "rp" 
       // (say, left) of this box
    }
    double dist(Box b, RPos rp) {
       // assumes non-overlapping
       // add some simple trig here:
       //   if boxes adjacent in chosen direction, distance 
       //      (if Right, then x2-p.x1, ...)
       //   if boxes not adjacent, then euclidean distance between 
       //   nearest corners.
    }
}

class NearestBoxes {    

    HashMap<RPos, HashMap<Box, TreeMap<Double, ArrayList<Box>>>> 
        = new HashMap<>();

    public NearestBoxes(List<Box> boxes) {
       for (RPos rp : RPos.values) {
          nearest.put(rp, 
             new HashMap<Box, TreeMap<Double, ArrayList<Box>>>();
          for (Box a : boxes) {
             TreeMap<Double, ArrayList<Box>> n = 
                new TreeMap<Double, ArrayList<Box>>());
             nearest.get(rp).put(a, n);                    
             for (Box b : boxes) {
                 if (a.isRelative(b, rp)) {
                    double d = a.dist(b, rp);                        
                    if (d == n.firstKey()) {
                       n.get(d).add(b);
                    } else if (d < n.firstKey()) {
                       n.put(d, new ArrayList());
                       n.get(d).add(b);
                    }
                 }
             }
          }
       }
    }

    public List<Box> getNearest(Box b, RPos rp) {
       TreeMap<Double, ArrayList<Box>> n = nearest.get(rp).get(b);
       return (n.isEmpty()) ? new ArrayList<Box>() 
                            : n.get(n.firstKey());           
    }
}

【讨论】:

  • 看起来很有希望。谢谢 。每个盒子的 LEFT、RIGHT、TOP&BOTTOM 将有一个最小距离的盒子列表的排序图。唯一的问题是,对于每个框移动,我们都需要更改此索引....
  • 这就是为什么我在 cmets 中询问盒子是否会移动,或者是否会有很多(如 1k+)。如果有很多盒子,或者它们经常移动,那么您应该为自己构建一个R-Tree - 但是您要么找到一个好的预先存在的库,要么为大量编码做好准备。
【解决方案2】:

随意发表评论并展示描述它可能产生误报的逻辑。

最近邻搜索中搜索的关键概念是分割域以最小化搜索并在找到最近邻时尽早退出搜索。

假设盒子有一个 id 并且它们有 x,y 坐标。 我想利用 x-y 坐标信息来找到最近的矩形。 该解决方案最初将整个 x-y 平面拆分为相当小的域以在 . 中搜索

左解:

垂直线的方程是 x=b。保存每个矩形的右边缘,因为它们被添加到 x-y 平面。 TreeMap&lt;Integer x,ArrayList&lt;Integer&gt;&gt; rightEdgeMap;ArrayList&lt;Integer&gt; 保存盒子的ID, 因此搜索域急剧减少。 现在在用蓝色颜色标记的缩小的X-Y平面中分割和搜索,直到找到最近的矩形。

如何搜索?

制作一个搜索边界框,并认为它可以在 X-Y 平面上生长。 由于落在参考矩形高度内的任何右边缘都是最接近的可能性,因此从那里开始搜索。[查看图像中的第一个搜索框]。

只在新增长的搜索框内搜索。如果在搜索框中找到多个矩形,则测量距离:

  • 如果右边缘在referenceRect的高度范围内,则取referenceRect或searchBoxRightEdge的水平距离。

    • 否则,取从边缘底部到参考矩形最近角的距离。

    或者,为简单起见,您可以接受搜索框中的最高 x 值边缘。对于细粒度解决方案,请使用上述 2 种方法。

通过在 x 轴和 y 轴上添加 1/5 的最小框像素来展平搜索框,直到其中任何一个轴或两者都到达末尾。 1/5 是一个假设,它可以是实心的 20 或 30 像素。 约束是在搜索框中的 x 和 y 轴上添加相同数量的像素。取太多像素会导致搜索时间更长,等待更长时间才能完成计算。 您无需在第一次匹配后展平搜索框,因为这是搜索的结束。

当调整任何框的大小或添加新框时,请适当更新rightEdgeMap。 您将需要另一个map&lt;Integer,Integer&gt; boxIdToRightEdgeMap;,其中键是框的ID,值是rightEdge x 值。 每当在任何框上添加新框/调整大小时,请使用 boxIdToRightEdgeMap 定位 rightEdge 中的 rightEdgeMap 值。

用例框 4 已调整大小:

int xValOfRightEdge=boxIdToRightEdgeMap.get(4);

使用xValOfRightEdgerightEdgeMap's值arrayList中删除4。 并在适当的rightEdgeMap's value-arryList 中插入 4。

搜索框内查询:

一种方法可能是将边缘存储在NavigableMap&lt;Integer,List&lt;Integer&gt;&gt; 中,其中key= YrightEdge 坐标、value= listrightEdges 位于该Y 坐标中。现在得到 subMap( minY ,MaxY) 。 minY 和 MaxY 是指 searchBox 的最小和最大 Y 值。对该子图进行降序排序,您将获得第一个条目作为答案。

用例框 4 被移动: 无需更改任何地图。

观察: 时间复杂度明显降低。

【讨论】:

  • 搜索框内任意一点到“参考矩形”的距离必须一致。 1.第一个搜索框必须在“参考矩形”的顶部和底部上方和下方增长。 2. 搜索框的2个角必须是凸弯曲的,这样到“Reference Rect”的对角线距离在搜索框内总是相同的
  • 是的,你是对的,我会尽快更新我的答案。
【解决方案3】:

也许您可以将所有矩形存储在一个数组中并匹配其他矩形的最近坐标:

假设矩形数组是: Rectangle[][4] rectangles = {{left, top, right, bottom}, {left, top, right, bottom}}

现在,如果您需要找到左侧的第一个矩形,只需将数组中每个矩形的右侧与参考矩形的左侧进行简单比较。矩形右侧的最大值将为您提供左侧的第一个矩形。

Rectangle referenceRectangle[4] = {rrl, rrt, rrr, rrb}
int max = 0;
for(i = 0 ; i < rectangles.length ; i++)
{
  if(rectangles[0][2] < referenceRectangle[0])
  {
    if(rectangles[0][2] > max)
    {
      max = rectangles[0][2];
      //Note the Index or maintain the list of rectangles.
    }   
  }
}

类似地,其他矩形也可以找出来。

【讨论】:

    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2013-12-03
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    相关资源
    最近更新 更多