A naive solution requires O (N ^ 2), where N is the number of rectangles, here's how to do it faster.
Two rectangles are adjacent only if they have one common coordinate (note that the opposite is not true). Therefore, you can count the number of neighboring boxes faster by first breaking the input rectangles into two hashes, one based on the x location of the rectangle, and the other based on the y location. As a result, one rectangle will fit into four different hash buckets based on its x1, y1, x2 and y2.
Example
For example, rect (0.0000,0.0000) (0.3412,0.4175) will be hashed in bucketX(0.000) , bucketX(0.3412) , bucketY(0.0000) and bucketY(0.4175) .
From the input to the OP, bucketX (0.000) and bucketX (1.000) will have the following rectangles:
bucketX(0.0000): (0.0000,0.0000) (0.3412,0.4175) (0.0000,0.4175) (0.3412,0.6553) (0.0000,0.6553) (0.7445,1.0000) (0.0000,0.4175) (0.3412,0.6553) bucketX(1.0000): (0.7445,0.0000) (1.0000,0.6553) (0.7445,0.6553) (1.0000,1.0000)
Time complexity
For the hashing step, only the calculation time O (N) is required, where N is the number of rectangles, and for the verification obtained, O (m ^ 2) is required, where m is the size of the largest bucket, which in most cases is much smaller than N.
Adjacency check in each hash bucket
Then for all the rectangles inside the same hash bucket. Check if the two rectangles are adjacent by determining if they have the same x value and the overlapping value in y or vice versa.
The following is an example of checking if two rectangles are adjacent:
class Rect { public: double x1, x2, y1, y2; // assuming x1 <= x2 and y1 <= y2 ... bool isAdjacent(Rect rect) { if (x1 == rect.x1 || x1 == rect.x2 || x2 == rect.x1 || x2 == rect.x2) { // use only < when comparing y1 and rect.y2 avoids sharing only a corner if (y1 >= rect.y1 && y1 < rect.y2) { return true; } if (y2 > rect.y1 && y2 <= rect.y2) { return true; } if (rect.y1 >= y1 && rect.y1 < y2) { return true; } if (rect.y2 > y1 && rect.y2 <= y2) { return true; } } if (y1 == rect.y1 || y1 == rect.y2 || y2 == rect.y1 || y2 == rect.y2) { if (x1 >= rect.x1 && x1 < rect.x2) { return true; } if (x2 > rect.x1 && x2 <= rect.x2) { return true; } if (rect.x1 >= x1 && rect.x1 < x2) { return true; } if (rect.x2 > x1 && rect.x2 <= x2) { return true; } } return false; } }
Running example
Here is an example adjacency verification code:
#include <stdio.h> #include <stdlib.h> #include <vector> class Rect { public: double x1, x2, y1, y2; // assuming x1 <= x2 and y1 <= y2 Rect(double X1, double Y1, double X2, double Y2) { if (X1 < X2) { x1 = X1; x2 = X2; } else { x2 = X1; x1 = X2; } if (Y1 < Y2) { y1 = Y1; y2 = Y2; } else { y2 = Y1; y1 = Y2; } } double area() { return (x2 - x1) * (y2 - y1); } bool isAdjacent(Rect rect) { if (x1 == rect.x1 || x1 == rect.x2 || x2 == rect.x1 || x2 == rect.x2) { // use only < when comparing y1 and rect.y2 avoids sharing only a corner if (y1 >= rect.y1 && y1 < rect.y2) { return true; } if (y2 > rect.y1 && y2 <= rect.y2) { return true; } if (rect.y1 >= y1 && rect.y1 < y2) { return true; } if (rect.y2 > y1 && rect.y2 <= y2) { return true; } } if (y1 == rect.y1 || y1 == rect.y2 || y2 == rect.y1 || y2 == rect.y2) { if (x1 >= rect.x1 && x1 < rect.x2) { return true; } if (x2 > rect.x1 && x2 <= rect.x2) { return true; } if (rect.x1 >= x1 && rect.x1 < x2) { return true; } if (rect.x2 > x1 && rect.x2 <= x2) { return true; } } return false; } }; int main() { std::vector<Rect> rects; rects.push_back(Rect(9999, 9999, 9999, 9999)); rects.push_back(Rect(0.0000,0.0000, 0.8147,0.1355)); rects.push_back(Rect(0.8147,0.0000, 1.0000,0.1355)); rects.push_back(Rect(0.8147,0.1355, 0.9058,0.8350)); rects.push_back(Rect(0.0000,0.1355, 0.1270,0.9689)); rects.push_back(Rect(0.9058,0.1355, 0.9134,0.2210)); rects.push_back(Rect(0.9058,0.8350, 1.0000,1.0000)); rects.push_back(Rect(0.8147,0.8350, 0.9058,1.0000)); rects.push_back(Rect(0.1270,0.1355, 0.6324,0.3082)); rects.push_back(Rect(0.1270,0.9689, 0.8147,1.0000)); rects.push_back(Rect(0.0000,0.9689, 0.1270,1.0000)); rects.push_back(Rect(0.9134,0.1355, 1.0000,0.2210)); rects.push_back(Rect(0.9134,0.2210, 1.0000,0.8350)); rects.push_back(Rect(0.9058,0.2210, 0.9134,0.8350)); rects.push_back(Rect(0.6324,0.1355, 0.8147,0.3082)); rects.push_back(Rect(0.6324,0.3082, 0.8147,0.9689)); rects.push_back(Rect(0.1270,0.3082, 0.6324,0.9689)); int adj_count = 0; int y = 1; for (int x = 0; x < rects.size(); ++x) { if (x == y) continue; if (rects[y].isAdjacent(rects[x])) { printf("rect[%d] is adjacent with rect[%d]\n", y, x); } } y = 2; for (int x = 0; x < rects.size(); ++x) { if (x == y) continue; if (rects[y].isAdjacent(rects[x])) { printf("rect[%d] is adjacent with rect[%d]\n", y, x); } } }
and output:
rect[1] is adjacent with rect[2] rect[1] is adjacent with rect[4] rect[1] is adjacent with rect[8] rect[1] is adjacent with rect[14] rect[2] is adjacent with rect[1] rect[2] is adjacent with rect[3] rect[2] is adjacent with rect[5] rect[2] is adjacent with rect[11]