Find nearby rectangles on X-Y plane

时间:2015-12-14 18:06:09

标签: java algorithm user-interface search shape

Output

I have few rectangles on an x-y plane.There is a reference rectangle . The reference rectangle's position is changeable. I need efficient way to find the

  • first rectangle that is found on the LEFT side of the reference rectangle.
  • first rectangle that is found on the RIGHT side of the reference rectangle.
  • first rectangle that is found on the TOP side of the reference rectangle.
  • first rectangle that is found on the BOTTOM side of the reference rectangle.

Pseudo-code or Java code is fine. Emphasis is given on the faster code than space consumed .
Solving one side will solve the other 3 sides. Let's say, we need to find the list of nearest rectangles that fall on the left side of the "REFERENCE RECT" . The "REFERENCE RECT" is movable. All other rectangles are stationary at the time of calculating.

PS. Each box can be the "REFERENCE RECT". Boxes are added to the X-Y plane one at a time.

3 个答案:

答案 0 :(得分:2)

这个伪代码在设置过程中可能不会很快(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());           
    }
}

答案 1 :(得分:2)

随意发表评论,并显示出可能产生误报的逻辑。

在最近邻搜索中搜索的关键概念是将域拆分为最小化搜索并在找到最近邻居时退出搜索。

假设盒子有一个id,它们有x,y坐标。 我想利用x-y坐标信息找到最近的矩形。 该解决方案最初将整个x-y平面分成相当小的域以搜索。enter image description here

解决左派:

垂直线的等式是x = b。当它们被添加到x-y平面时,每个矩形的右边缘。 TreeMap<Integer x,ArrayList<Integer>> rightEdgeMap;ArrayList<Integer>包含框的ID, 因此搜索域大幅减少。 现在拆分并在标有 蓝色 颜色的X-Y平面上搜索,直到找到最近的矩形。

如何搜索?

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

仅在搜索框的新增长内搜索。如果在搜索框中找到多个rect,请测量距离:

  • 如果右边缘落在referenceRect的高度范围内,请从referenceRect或searchingBoxRightEdge获取水平距离。

    • 其他明智的做法是从边缘底部到referenceRect最近的角落。

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

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

调整任何框的大小或添加新框时,请相应地更新rightEdgeMap。 您将需要另一个map<Integer,Integer> boxIdToRightEdgeMap;,其中key是id的box,value是rightEdge x值。 每当在任何框中添加新框/调整大小时,请使用boxIdToRightEdgeMaprightEdge中找到rightEdgeMap值。

用例框4已调整大小:

int xValOfRightEdge=boxIdToRightEdgeMap.get(4);

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

在搜索框内查询:

一种方法是,将边缘存储在NavigableMap<Integer,List<Integer>>key= Y rightEdge坐标value= listrightEdges subMap( minY ,MaxY)落入Y坐标。现在得到mvn release:prepare release:perform --batch-mode 。 minY和MaxY指的是搜索框的最小和最大Y值。对该子图进行排序,您可以得到第一个条目作为答案。

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

<强>观察: 时间复杂度明显减少。

答案 2 :(得分:0)

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

假设矩形数组是:    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.
    }   
  }
}

同样,可以找到其他矩形。