3

Description

Suppose the coordinates of 4 side of a rectangle denoted by (x1,y1), (x2,y2),(x3,y3) and (x4,y4). Like this image-

enter image description here

And I have a set of coordinates of 100000 rectangles saved in a txt file. For example here are the values of coordinates of 16 rectangles generated by my code-

#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

These coordinates splits an unit square into sub-rectangles like this picture-enter image description here

Examples of Nearest Rectangles

In the above picture the nearest rectangles for rectangle# 3 are- 9,15,14,1,2,5,13,6 and 7.

For rectangle# 9 they are- 10,4,16,15,3 and 7.

My Problem

Now I would like to calculate the number of nearest rectangles for each of the rectangles using c/c++. How can I do it?

Edit:Based on the responses

#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;
}

Ok I write the above code based on the responses. But it is showing the following error-

    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

What am I doing wrong?

aries0152
  • 381
  • 1
  • 14
  • 1
    Quick note, you don't need to have x2,y2 and x4,y4 ... you can automatically fill those in with x1,y1 and x3,y3 , or, that is, if you're only dealing with rectangles, as you say. – MiJyn Jul 01 '13 at 19:29
  • @MiJyn: You are right. x1,y1 and x3,y3 fills the values for x2,y2 & x4,y4. – aries0152 Jul 01 '13 at 19:32
  • 3
    Isn't this very similar to [this](http://stackoverflow.com/questions/17328004/count-the-number-of-adjacent-boxes) and [this](http://stackoverflow.com/questions/17274934/count-the-number-of-adjacent-rectangles) post of yours? – meaning-matters Jul 01 '13 at 19:39
  • This Q is not C++ specific. Consider removing C++ tag. – Kirill Kobelev Jul 01 '13 at 19:40
  • 1
    Given the restriction of 100000, it seems that it is problem of some coding site with time restriction of 1s. And acceptable complexity is O(n logn). – Shashwat Kumar Jul 01 '13 at 19:47
  • 1
    Have a look to http://en.wikipedia.org/wiki/Quadtree – Maxime Chéramy Jul 01 '13 at 20:03
  • You meant you want the surounding rectangles. – AlexWien Jul 01 '13 at 20:35
  • 1
    @aries0152: have you asked the same question 3 times? – Karoly Horvath Jul 01 '13 at 20:56
  • @meaning-matters & Karoly Horvath: [On that question](http://stackoverflow.com/questions/17328004/count-the-number-of-adjacent-boxes) I wanted the number of boxes only adjacent to four-side except the corners. – aries0152 Jul 02 '13 at 03:15
  • 1
    @Maxime: Yes I have checked that. But Quadtree deals with the evenly splitted sub-nodes. Here I do not split the sub-rectangles evenly. – aries0152 Jul 02 '13 at 03:17

4 Answers4

1

Invert the problem. When you are generating the rectangles maintain a set J of n-tuples (where n varies between 2 and 4) which denote the 'junction points' ie the corner of 2, 3 or 4 rectangles meeting. For your picture above {1,4} would denote the (left) corner of rectangles 1 and 4, {1,4,8} denote the corner of rectangles 1, 4 and 8. There are 25 such n-tuples for your picture.

When you want to perform nearest rectangle query for rectangle R, you need to find all occurrences of R in J, which is easy if you organise elements of J into equivalence classes based on the relation 'rectangle R appears in the n-tuple' and index a vector with the rectangle number. Then looking up the neighbours of R is O(1).

user1666959
  • 1,805
  • 12
  • 11
0

In your case, each of the nearest rectangles must share a common side or part of it (as in case of rect 9 with rect. 3)

  1. Consider that u want to find out the nearest rectangles for rect. A
  2. You know the (x,y) coordinates of it's corners
  3. You know that the coordinates vary along the edges
  4. For example consider the edge A(x3,y3) to A(x4,y4)
  5. Consider a rectangle say B and check if it meets any of the following criteria

B(x2,y2) is between A(x3,y3) and A(x4,y4)
B(x1,y1) is between A(x3,y3)and A(x4,y4)
A(x3,y3) is between B(x2,y2) and B(x1,y1)
A(x4,y4) is between B(x2,y2) and B(x1,y1)
Considered corner(s) of B coincide with that of A

The edge described by corners A(x3,y3) and A(x4,y4) is the top edge of the rectangle A and you want to see if any rectangle B resides on top of this and hence consider the edge of B described by B(x1,y1) and B(x2,y2)

Some of the above criteria are overlapping in some cases.

Do the same for the rest of the sides matching the coordinates of corners properly. (E.g. considering B(x1,y1) and B(x4,y4) when considering edge of A described by A(x3,y2) and A(x2,y2))

Consider all rectangles. Count them and voila!

EDIT:Remember A is the rect. for which you want to find the nearest members. B is a rect. for which you are checking if it satisfies the given criteria.

Colorless Photon
  • 399
  • 1
  • 3
  • 19
  • I downvoted because you just gave the naivest method one can think of. You just wrote the conditions whether two rectangles are adjacent or not when their coordinates are given. So just iterating all rectangles for each rectangle is an obvious solution. I dont think problem would have been asked for such solution. I am sure asker is desiring some better approach. This O(n^2) solution would be extremely slow on 100000 rectangles. – Shashwat Kumar Jul 01 '13 at 20:46
0

So, basically, what you're looking for is to find rectangles touching the rectangle in question? If so, I think something like this should do (I haven't tested it though):

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;
}

And then use it like this:

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);

And then touching should contain, as you said, rectangles 9, 15, 14, 1, 2, 5, 13, 6, and 7 (it will return the Rectangle, not the number).

MiJyn
  • 5,327
  • 4
  • 37
  • 64
  • I have edited my question and try to use your code. But have some error. Could you please help me? – aries0152 Jul 02 '13 at 18:35
  • @aries0152 I edited my question to fix the `==` issue. About the second issue that you have (`ret was not declared in this scope`), you forgot to add `std::vector ret;` to the top of the `get_touching_rectangles` function. – MiJyn Jul 02 '13 at 19:25
  • @aries0152 Please note that this function is kind of more like pseudo-code, to give you an idea of what to do, and to give a basic (reference?) implementation (I couldn't understand the other answers that popped up while writing this answer anyways XD). I added extra comments to explain how everything works :) – MiJyn Jul 02 '13 at 19:38
0

Lets say your rectangle has x and y coordinates as xleft, xright, ybottom, ytop.
Sort the rectangle and keep them separately in different arrays.

  • ybottomarray: Sort the rectangles in increasing order of ybottom then xleft.

  • ytoparray: Sort in increasing order of ytop then xleft.

  • xleftarray: Sort in order of xleft then ytop.

  • xrightarray: Sort in order of xright then ytop.

Now iterate over each rectangle.

Step 1: Find number of adjacent rectangles over it i.e. the rectangles whose ybottom is equal ytop of current rectangle.

  • Binary search in ybottomarray to find first and last indices whose ybottom is equal to ytop of current rectangle. Say the range is range_y.

  • In range_y binary search for index of rectangle whose xleft is just less than xleft of current rectangle say idx1. This gives leftmost rectangle above current rectangle.

  • Again binary search for rectangle with greatest xleft value which is less than or equal to xright of current rectangle say idx2. This gives rightmost rectangle above current rectangle.

So rectangles lying in idx1 to idx2 are all adjacent to current rectangle above it. So idx2-idx1+1 will give the rectangles above it. Similarly find rectangles on all four sides.

Step 2: Find rectangles on right.
Step 3: Find rectangles on bottom.
Step 4: Find rectangles on left.

Also the corner cases are needed to be handled carefully so that no rectangle is counted twice and none is left for counting.

Complexity

The sorting step are of complexity O(nlog n).
Each Step in iterations requires two binary search for finding range_y and binary search for finding idx1 and idx2 each. So four binary search for each step and there are four steps. So total 16 binary searches which makes O(logn) complexity for each iteration.

So for all iterations complexity will be O(n logn).
So overall complexity of this solution is O(n logn).

Shashwat Kumar
  • 5,159
  • 2
  • 30
  • 66