检查最近的矩形

时间:2013-07-01 19:22:39

标签: algorithm

描述

假设由(x1,y1),(x2,y2),(x3,y3)和(x4,y4)表示的矩形的4边的坐标。喜欢这张图片 -

enter image description here

我在txt文件中保存了一组100000个矩形的坐标。例如,这里是由我的代码生成的16个矩形的坐标值 -

#Rect    x1      y1      x2       y2        x3        y3      x4     y4        area

1     0.0000   0.0000   0.8147   0.0000   0.8147   0.1355   0.0000   0.1355   0.1104
2     0.8147   0.0000   1.0000   0.0000   1.0000   0.1355   0.8147   0.1355   0.0251
3     0.8147   0.1355   0.9058   0.1355   0.9058   0.8350   0.8147   0.8350   0.0637
4     0.0000   0.1355   0.1270   0.1355   0.1270   0.9689   0.0000   0.9689   0.1058
5     0.9058   0.1355   0.9134   0.1355   0.9134   0.2210   0.9058   0.2210   0.0006
6     0.9058   0.8350   1.0000   0.8350   1.0000   1.0000   0.9058   1.0000   0.0155
7     0.8147   0.8350   0.9058   0.8350   0.9058   1.0000   0.8147   1.0000   0.0150
8     0.1270   0.1355   0.6324   0.1355   0.6324   0.3082   0.1270   0.3082   0.0873
9     0.1270   0.9689   0.8147   0.9689   0.8147   1.0000   0.1270   1.0000   0.0214
10    0.0000   0.9689   0.1270   0.9689   0.1270   1.0000   0.0000   1.0000   0.0040
11    0.9134   0.1355   1.0000   0.1355   1.0000   0.2210   0.9134   0.2210   0.0074
12    0.9134   0.2210   1.0000   0.2210   1.0000   0.8350   0.9134   0.8350   0.0532
13    0.9058   0.2210   0.9134   0.2210   0.9134   0.8350   0.9058   0.8350   0.0047
14    0.6324   0.1355   0.8147   0.1355   0.8147   0.3082   0.6324   0.3082   0.0315
15    0.6324   0.3082   0.8147   0.3082   0.8147   0.9689   0.6324   0.9689   0.1205
16    0.1270   0.3082   0.6324   0.3082   0.6324   0.9689   0.1270   0.9689   0.3339

这些坐标将单位正方形划分为像这张图片的子矩形 - enter image description here

最近的矩形示例

在上图中,矩形#3的最近矩形为-9,15,14,1,2,5,13,​​6和7。

对于矩形#9,它们是-10,4,16,15,3和7。

我的问题

现在我想用c / c ++计算每个矩形的最近矩形数。我该怎么办?

修改:根据回复

#include <iostream>
#include <vector>
#include <fstream>

using namespace std;


struct Rectangle {
    double x1, y1;
    double x2, y2;
    double x3, y3;
    double x4, y4;
};




vector<double> get_touching_rectangles(Rectangle base, vector<Rectangle> rectangles) {


    for (auto it = rectangles.begin(); it != rectangles.end(); it++) {
        Rectangle other = *it;
        if (base == other) {
            continue; // This is our rectangle... skip it
        }
        // Top or bottom
        if ((other.x2 >= base.x1 && other.x1 <= base.x2) && (other.y1 == base.y3 || other.y3 == base.y1)) {
            ret.push_back(other);
            continue;
        }
        // Left or right
        if ((other.y3 >= base.y2 && other.y2 <= base.y3) && (other.x1 == base.x3 || other.x3 == base.x1)) {
            ret.push_back(other);
            continue;
        }
    }
    return ret;
}

int main(int argc, char const *argv[])
{
vector<Rectangle> rectangles;

//parse_txt_file(file, &rectangles); // Or whateer I need to do to parse that .txt file
ifstream inputFile;
inputFile.open("RectCoordinates.txt");

//std::vector<Rectangle> touching = 
get_touching_rectangles(rectangles.at(2) /* Rectangle #3 */, rectangles);

 inputFile.close();
    return 0;
}

好的,我根据回复编写了上面的代码。但它显示以下错误 -

    g++ -std=c++11 st5.cpp -o ssst5.cpp: In function ‘std::vector<double> get_touching_rectangles(Rectangle, std::vector<Rectangle>)’:
    st5.cpp:23:21: error: no match for ‘operator==’ in ‘base == other’
    st5.cpp:23:21: note: candidates are:
    In file included from /usr/include/c++/4.7/iosfwd:42:0,
                     from /usr/include/c++/4.7/ios:39,
                     from /usr/include/c++/4.7/ostream:40,
                     from /usr/include/c++/4.7/iostream:40,
                     from st5.cpp:1:
    /usr/include/c++/4.7/bits/postypes.h:218:5: note: template<class _StateT> bool std::operator==(const std::fpos<_StateT>&, const std::fpos<_StateT>&)
    /usr/include/c++/4.7/bits/postypes.h:218:5: note:   template argument deduction/substitution failed:

st5.cpp:28:13: error: ‘ret’ was not declared in this scope
st5.cpp:33:13: error: ‘ret’ was not declared in this scope
st5.cpp:37:12: error: ‘ret’ was not declared in this scope

我做错了什么?

4 个答案:

答案 0 :(得分:1)

反转问题。当您生成矩形时,保持一组J个n元组(其中n在2和4之间变化),这表示“连接点”,即2,3或4个矩形的角落相交。对于上面的图片,{1,4}表示矩形1和4的(左)角,{1,4,8}表示矩形1,4和8的角。有25个这样的n元组用于你的图片

当您想对矩形R执行最近的矩形查询时,您需要在J中找到所有出现的R,如果根据关系'矩形R出现在n-中将J的元素组织成等价类,这很容易使用矩形编号对元组进行元组索引。然后查找R的邻居是O(1)。

答案 1 :(得分:0)

在你的情况下,每个最近的矩形必须共享一个共同的一面或一部分(如使用rect.3的rect 9的情况)

  1. 考虑一下你想找出最近的矩形矩形。的 A
  2. 你知道它角落的(x,y)坐标
  3. 您知道坐标沿边缘变化
  4. 例如,考虑边缘A(x3,y3)到A(x4,y4)
  5. 考虑一个矩形说 B 并检查它是否符合以下任何条件
  6.   

    B(x2,y2)介于A(x3,y3)和A(x4,y4)之间   B(x1,y1)在A(x3,y3)和A(x4,y4)之间   A(x3,y3)在B(x2,y2)和B(x1,y1)之间   A(x4,y4)在B(x2,y2)和B(x1,y1)之间   考虑到B的角落与A

    的角落一致

    角A(x3,y3)和A(x4,y4)描述的边是矩形A的上边缘,你想看看是否有任何矩形B位于此顶部,因此考虑B的边缘由B(x1,y1)和B(x2,y2)

    描述

    在某些情况下,上述某些标准会重叠。

    对于与角落坐标正确匹配的其余边做同样的事情。 (例如,当考虑A(x3,y2)和A(x2,y2)所描述的A的边缘时考虑B(x1,y1)和B(x4,y4)

    考虑所有矩形。算上他们吧瞧!

    编辑:记住A是矩形。你想找到最近的成员。 B是一个矩形。你正在检查它是否满足给定的标准。

答案 2 :(得分:0)

所以,基本上,你要找的是找到触摸矩形的矩形?如果是这样,我认为这样的事情应该做(虽然我没有测试过):

struct Rectangle {
    int x1, y1;
    int x2, y2;
    int x3, y3;
    int x4, y4;
};

// This is why I hate C++ :/
bool operator==(const Rectangle& lhs, const Rectangle& rhs) {
    return  lhs.x1 == rhs.x1 && lhs.y1 == rhs.y1 &&
            lhs.x2 == rhs.x2 && lhs.y2 == rhs.y2 &&
            lhs.x3 == rhs.x3 && lhs.y3 == rhs.y3 &&
            lhs.x4 == rhs.x4 && lhs.y4 == rhs.y4;
}

// Returns all rectangles in `rectangles` that touch `base`
std::vector<int> get_touching_rectangles(Rectangle base,
        std::vector<Rectangle> rectangles) {

    // Create the array that we will return,
    //  i.e. the touching rectangles
    std::vector<Rectangle> ret;

    // Iterate through each rectangle
    for (auto it = rectangles.begin(); it != rectangles.end(); it++) {
        Rectangle other = *it;

        // If this (`other`) is our rectangle (`base`)
        //   i.e. the one we are trying to find rectangles that touch it,
        // skip it
        if (base == other) {
            continue;
        }

        // If `other` touches the top or bottom sides of `base`, add it
        if ((other.x2 >= base.x1 && other.x1 <= base.x2) &&
                (other.y1 == base.y3 || other.y3 == base.y1)) {
            ret.push_back(other);
            continue;
        }

        // If `other` touches the left or right sides of `base`, add it
        if ((other.y3 >= base.y2 && other.y2 <= base.y3) &&
                (other.x1 == base.x3 || other.x3 == base.x1)) {
            ret.push_back(other);
            continue;
        }

    }

    return ret;
}

然后像这样使用它:

std::vector<Rectangle> rectangles;
parse_txt_file(file, &rectangles); // Or whatever you do to parse that .txt file
std::vector<Rectangle> touching = get_touching_rectangles(rectangles.at(2) /* Rectangle #3 */, rectangles);

然后touching应该包含,如你所说,矩形9,15,14,1,2,5,13,​​6和7(它将返回Rectangle,而不是数字)。

答案 3 :(得分:0)

让我们说你的矩形的x和y坐标为xleft, xright, ybottom, ytop 对矩形进行排序,并将它们分别保存在不同的数组中。

  
      
  • ybottomarray:按ybottom然后xleft的递增顺序对矩形进行排序。

  •   
  • ytoparray:按ytop然后xleft的递增顺序排序。

  •   
  • xleftarray:按xleft然后ytop的顺序排序。

  •   
  • xrightarray:按xright然后ytop的顺序排序。

  •   

现在迭代每个矩形。

步骤1:在其上查找相邻矩形的数量,即ybottom等于当前矩形ytop的矩形。

  • ybottomarray中进行二进制搜索,以查找其中的第一个和最后一个索引 ybottom等于当前矩形的ytop。假设范围是range_y

  • range_y二进制搜索xleft所在的矩形索引中 只是当前矩形的xleft小于idx1。这使得最左边的矩形在当前矩形上方。

  • 再次二进制搜索具有最大xleft值的矩形 小于或等于当前矩形的xright,例如idx2。这会在当前矩形上方显示最右边的矩形。

所以位于idx1到idx2的矩形都与它上面的当前矩形相邻。 因此idx2-idx1+1会在其上方显示矩形。同样在四边找到矩形。

步骤2:找到右边的矩形 第3步:在底部找到矩形 第4步:找到左边的矩形。

此外需要小心处理角落的情况,这样就不会计算两次矩形,也不会计算任何矩形。

复杂性

排序步骤的复杂性为 O(nlog n) 迭代中的每个步骤都需要两个二进制搜索来查找range_y和二进制搜索以查找每个idx1和idx2。因此每个步骤有四个二进制搜索,有四个步骤。因此总共16次二进制搜索使得每次迭代的 O(logn)复杂度。

因此,对于所有迭代,复杂度将为O(n logn) 因此,此解决方案的总体复杂性为 O(n logn)