Rectangle intersect code - Is this right? - c++

Can someone tell me whether my rectangle intersect code is correct?
bool checkCollide(int x, int y, int oWidth, int oHeight,
int x2, int y2, int o2Width, int o2Height) {
bool collide = false;
if (x >= x2 && x <= x2+o2Width && y >= y2 && y <= y2+o2Height)
collide = true;
if (x+oWidth >= x2 && x+oWidth <= x2+o2Width && y >= y2 && y <= y2+o2Height)
collide = true;
if (x >= x2 && x<= x2+o2Width && y+oHeight >= y2 && y+oHeight <= y2+o2Height)
collide = true;
if (x+oWidth >= x2 && x+oWidth <= x2+o2Width && y+oHeight >= y2 && y+oHeight <= y2+o2Height)
collide = true;
return collide;
}

Nope, a corner of a rectangle doesn't have to be in the other rectangle for the rectangles to collide. What you want to do is to find the logic when they do not intersect and use the negation of that. The picture below shows two rectangles that clearly intersect each other, but only the sides are intersecting, not the corners.
Just formulate the logic as follows: What does it take for the blue to not intersect the red? Well it's either completely to the right, completely to the left, up or below. Formulate an if statement to that and negate it.
Let me help you with the beginning:
if (!(x2 > x+oWidth || x2+o2Width < x || ..))
collide = true;

Following on from Magnus's answer, I'd take a slightly different approach.
As he says, if the two don't intersect then one will be completely left, completely right, etc. For performance however you can stop testing as soon as any of these conditions are found to be false, e.g.:
if (x2 + owidth2 < x)
return false; // box 2 is left of box 1
if (x + owidth < x2)
return false; // box 1 is left of box 2
// etc...

First implement interval intersection (i.e. one dimension).
Then you can implement rectangle intersection by first applying interval intersection to the x-coordinates and then applying interval intersection to the y-coordinates.

checkCollide(0, 0, 3, 3, 1, 1, 1, 1) == false
I'm guessing that's not what you want.

Related

How to compute the position of the 4th corner of a rectangle?

I have 3 corners of an axis aligned box, I must find the 4th corner.
How can I compute it more efficiently:
if (loc[0].first != loc[1].first && loc[0].first != loc[2].first)
x = loc[0].first;
else if (loc[1].first != loc[0].first && loc[1].first != loc[2].first)
x = loc[1].first;
else
x = loc[2].first;
if (loc[0].second != loc[1].second && loc[0].second != loc[2].second)
y = loc[0].second;
else if (loc[1].second != loc[0].second && loc[1].second!=loc[2].second)
y = loc[1].second;
else
y = loc[2].second;
Assuming you have 2 identical (integral) numbers and a third one, xor might give you the expected one:
x = loc[0].first ^ loc[1].first ^ loc[2].first;
y = loc[0].second ^ loc[1].second ^ loc[2].second;
if type is not integral (so no xor), it seems more readable to check for equality (that also does one check for equality instead of 2 checks for inequality by test):
if (loc[0].first == loc[1].first)
x = loc[2].first;
else if (loc[0].first == loc[2].first)
x = loc[1].first;
else // loc[1].first == loc[2].first
x = loc[0].first;
If the points are guaranteed to be perfectly aligned vertically or horizontally, the fourth corner is found at the unique abscissa and unique ordinate.
if X0 == X1:
X3= X2
elif X0 == X2:
X3= X1
else:
X3= X0
You can't do this in less than two comparisons, because the outcome depends on the three values.
Same code on Y, independently. Or, you can even spare a comparison on Y, because if two X's are known to be equal, the corresponding Y's are perforce different. Hence on average a total of 8/3 comparisons.
If you are after the ordered axis-aligned bounding box, take the minimum and maximum of the abscissas and ordinates separately.

All possible paths between two points of a matrix in C++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Given a NxM plane, find all the possible paths between two points with three movements: right, down and diagonal(right-down, 315º).
I'm stuck on this problem. I have to resolve it two ways: recursive and iterative. For iterative I have the idea but don't know how to implement it.
The description of my idea is:
(Google Translate). We are faced with a board of N columns of width and M rows of height. We must arrive from a point (x1, y1) to another point (x2, y2), so (xi, yj) can not be greater than N or M respectively. The restrictions for movement are that we can only move to the right (1), diagonal down-right (2) and down (3), with each movement we assign the number in parentheses. Given these movements, we realize that we can not go left or up, so x1 has to be less than x2 and y1 has to be greater than y2.
The algorithm would start from the first point (x1, y1) and try to create three "children", one for each movement:
Right (x1 + 1)
Diagonal (x1 + 1, y1-1)
Down (y1-1)
 
The conditionals for each child to be accepted would be those already said, x1 <= N, y1 <= M, x1 <= x2, y1> = y2.
The iteration would be to try to create 3 more children (one for each movement) from each accepted child.
This iteration would conclude by being (x1, y1) of each child equal to (x2, y2).
Thanks in advance.
Iterative Approach :
This can be solved by memoization, which means you keep track of the no. of ways to reach a certain cell in matrix M.
Initially M[x][y] = 0 , for all x,y. b/w sx, dx and sy,dy respecitevly
Pseudocode:
We first start from source cell (sx,sy), there is only one way to reach it, therefore
sx,sy // source cell
dx,dy // destination cell
M[sx][sy] = 1 ;
for row x between sx, dx :
for column y between sx, dy:
if y-1 >= sy:
M[x][y] += M[x][y-1] // coming to x,y from left cell
if x-1 >= sx:
M[x][y] += M[x][y-1] // coming to x,y from top cell
if x-1 >= sx && y-1 >= sy:
M[x][y] += M[x-1][y-1] // coming from diagonal left cell.
Answer will be M[dx][dy].
Recursive Approach:
Going by the same idea as iterative approach , the same can be implemented recursively as well:
Initially M[x][y] == -1: for all x b/w sx and dx , for all y b/w sy and dy
path( row, col )
if row == dx && col == dy:
return 1
if M[x][y] != -1: return M[x][y] // this means result for this is already calculated
M[x][y] = 0
if col+1 <= dy:
M[row][col] += path(row, col+1) // going right
if row+1 <= dx:
M[row][col] += path (row+1, col) // going down
if row+1 <= dx && col+1 <= dy:
M[row][col] += path(row+1, col+1) // going diagonally right
return M[row][col]
Answer will M[sx][sy]
A simple recursive solution would be to create new childs with each recursion call e.g.
int foundSolutions = 0;
boolean pathExistsBetweenPoints(Point source, Point target, List<Point> previousPoints) {
//Check if we're there yet
if(source.x == target.x && source.y == target.y) {
foundSolutions++;
//Here you can display previousPoints if you want a possible solution
return true;
}
if(source.x > N || source.y > M || source.x > target.x || source.y > target.y) {
return false; //This trail is out of bounds
}
//Add this point to the list of points
List<Point> newPoints = previousPoints.add(source);
//Get the childpoints
Point rightPoint = new Point(source.x, source.y + 1);
Point diagonalPoint = new Point(source.x + 1, source.y + 1);
Point downPoint = new Point(source.x + 1, source.y);
//Check if any of the childs can reach the target
boolean validPath = pathExistsBetweenPoints(rightPoint, target, previousPoints);
validPath = validPath || pathExistsBetweenPoints(diagonalPoint, target, previousPoints);
validPath = validPath || pathExistsBetweenPoints(downPoint, target, previousPoints);
return validPath;
}
I'm not familiar with C++ syntax but this should be fairly translatable

Rectangle collision (C++)

I'm currently using this collision code:
( // tx = other x, tex = other end x etc.
( // horizontal collision
(xpos >= tx && xpos <= tex)
||
((xpos + w) <= tex && (xpos + w) >= tx)
)
&&
( // vertical collision
(ypos >= ty && ypos <= tey)
||
((ypos + h) <= tey && (ypos + h) >= ty)
)
)
However, it only detects if the top left pixel, the top right pixel, the bottom left pixel, or the bottom right pixel is within the rectangle to test. I don't know what to do, it already took forever to get to the current collision testing method I'm using, what can I change to fix this problem?
Do I understand correctly that one rectangle extends horizontally from xpos to xpos + w and vertically from ypos to ypos + h, and the other extends horizontally from tx to tex and vertically from ty to tey? With w, h, tex − tx, and tey − ty all being positive?
If so, then you can write:
xpos <= tex && xpos + w >= tx // horizontal collision
&& ypos <= tey && ypos + h >= ty // vertical collision
Alternatively, you may find it easier to reason about if you calculate the conditions whereby they don't collide, and just add a !:
!(
xpos > tex // first rectangle entirely to right of second
|| xpos + w < tx // first rectangle entirely to left of second
|| ypos > tey // first rectangle entirely above second
|| ypos + h < ty // first rectangle entirely below second
)
(The two versions are equivalent, due to one of De Morgan's laws.)

Recursive floodFill function? C++

So recursion is not my strong point, and I have been challenged to make a recursive floodFill function that fills a vector of a vector of ints with 1's if the value is zero. My code keeps segfaulting for reasons beyond me. Perhaps my code will make that sound more clear.
This is the grid to be flood filled:
vector<vector<int> > grid_;
It belongs to an object I created called "Grid" that is basically a set of functions to help manipulate the vectors. The grid's values are initialized to all zeros.
This is my flood fill function:
void floodFill(int x, int y, Grid & G)
{
if (G.getValue(x,y))
{
G.setValue(x,y,1);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x+1,y,G);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x,y+1,G);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x-1,y,G);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x,y-1,G);
}
}
The intention here is to have the function check if a point's value is zero, and if it is, change it to one. Then it should check the one above it for the same. It does this until it either finds a 1 or hits the end of the vector. Then it tries another direction and keeps going until the same conditions as above and so on and so forth until its flood filled.
Can anyone help me fix this? Maybe tell me whats wrong?
Thanks!
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x-1,y,G);
won't work, since you can access index -1 of the underlying vector if x == 0
Same goes for floodFill(x,y-1,G);
This code has a lot of problems. First of all you check with if(G.getValue(x,y)) whether the value at a position is 1, and if so, then you set it to 1 with G.setValue(x,y,1). Think about this for a second, this can't be right. When will you ever set non-zero values to 1?
Then, another more subtle point is that you shouldn't do the recursion into neighbors if they are already set to 1.
As it stands the code you have will likely run until you overflow the stack because just going to recurse forever on the 1's that are connected to wherever you start from.
How about this?
void floodFill(int x, int y, Grid &g) {
if(x >= g.getColumns() || y >= g.getRows()) {
return;
}
floodFill(x+1, y, g);
if( x == 0 ) {
floodFill(x, y+1, g);
}
g.setValue(x, y, 1)
}
I think that will fill the grid without every hitting the same coordinate multiple times, and whenever either index is out of bounds it just returns so no chance of a seg fault.

Determine if two rectangles overlap each other?

I am trying to write a C++ program that takes the following inputs from the user to construct rectangles (between 2 and 5): height, width, x-pos, y-pos. All of these rectangles will exist parallel to the x and the y axis, that is all of their edges will have slopes of 0 or infinity.
I've tried to implement what is mentioned in this question but I am not having very much luck.
My current implementation does the following:
// Gets all the vertices for Rectangle 1 and stores them in an array -> arrRect1
// point 1 x: arrRect1[0], point 1 y: arrRect1[1] and so on...
// Gets all the vertices for Rectangle 2 and stores them in an array -> arrRect2
// rotated edge of point a, rect 1
int rot_x, rot_y;
rot_x = -arrRect1[3];
rot_y = arrRect1[2];
// point on rotated edge
int pnt_x, pnt_y;
pnt_x = arrRect1[2];
pnt_y = arrRect1[3];
// test point, a from rect 2
int tst_x, tst_y;
tst_x = arrRect2[0];
tst_y = arrRect2[1];
int value;
value = (rot_x * (tst_x - pnt_x)) + (rot_y * (tst_y - pnt_y));
cout << "Value: " << value;
However I'm not quite sure if (a) I've implemented the algorithm I linked to correctly, or if I did exactly how to interpret this?
Any suggestions?
if (RectA.Left < RectB.Right && RectA.Right > RectB.Left &&
RectA.Top > RectB.Bottom && RectA.Bottom < RectB.Top )
or, using Cartesian coordinates
(With X1 being left coord, X2 being right coord, increasing from left to right and Y1 being Top coord, and Y2 being Bottom coord, increasing from bottom to top -- if this is not how your coordinate system [e.g. most computers have the Y direction reversed], swap the comparisons below) ...
if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
RectA.Y1 > RectB.Y2 && RectA.Y2 < RectB.Y1)
Say you have Rect A, and Rect B.
Proof is by contradiction. Any one of four conditions guarantees that no overlap can exist:
Cond1. If A's left edge is to the right of the B's right edge,
- then A is Totally to right Of B
Cond2. If A's right edge is to the left of the B's left edge,
- then A is Totally to left Of B
Cond3. If A's top edge is below B's bottom edge,
- then A is Totally below B
Cond4. If A's bottom edge is above B's top edge,
- then A is Totally above B
So condition for Non-Overlap is
NON-Overlap => Cond1 Or Cond2 Or Cond3 Or Cond4
Therefore, a sufficient condition for Overlap is the opposite.
Overlap => NOT (Cond1 Or Cond2 Or Cond3 Or Cond4)
De Morgan's law says
Not (A or B or C or D) is the same as Not A And Not B And Not C And Not D
so using De Morgan, we have
Not Cond1 And Not Cond2 And Not Cond3 And Not Cond4
This is equivalent to:
A's Left Edge to left of B's right edge, [RectA.Left < RectB.Right], and
A's right edge to right of B's left edge, [RectA.Right > RectB.Left], and
A's top above B's bottom, [RectA.Top > RectB.Bottom], and
A's bottom below B's Top [RectA.Bottom < RectB.Top]
Note 1: It is fairly obvious this same principle can be extended to any number of dimensions.
Note 2: It should also be fairly obvious to count overlaps of just one pixel, change the < and/or the > on that boundary to a <= or a >=.
Note 3: This answer, when utilizing Cartesian coordinates (X, Y) is based on standard algebraic Cartesian coordinates (x increases left to right, and Y increases bottom to top). Obviously, where a computer system might mechanize screen coordinates differently, (e.g., increasing Y from top to bottom, or X From right to left), the syntax will need to be adjusted accordingly/
struct rect
{
int x;
int y;
int width;
int height;
};
bool valueInRange(int value, int min, int max)
{ return (value >= min) && (value <= max); }
bool rectOverlap(rect A, rect B)
{
bool xOverlap = valueInRange(A.x, B.x, B.x + B.width) ||
valueInRange(B.x, A.x, A.x + A.width);
bool yOverlap = valueInRange(A.y, B.y, B.y + B.height) ||
valueInRange(B.y, A.y, A.y + A.height);
return xOverlap && yOverlap;
}
struct Rect
{
Rect(int x1, int x2, int y1, int y2)
: x1(x1), x2(x2), y1(y1), y2(y2)
{
assert(x1 < x2);
assert(y1 < y2);
}
int x1, x2, y1, y2;
};
bool
overlap(const Rect &r1, const Rect &r2)
{
// The rectangles don't overlap if
// one rectangle's minimum in some dimension
// is greater than the other's maximum in
// that dimension.
bool noOverlap = r1.x1 > r2.x2 ||
r2.x1 > r1.x2 ||
r1.y1 > r2.y2 ||
r2.y1 > r1.y2;
return !noOverlap;
}
It is easier to check if a rectangle is completly outside the other, so if it is either
on the left...
(r1.x + r1.width < r2.x)
or on the right...
(r1.x > r2.x + r2.width)
or on top...
(r1.y + r1.height < r2.y)
or on the bottom...
(r1.y > r2.y + r2.height)
of the second rectangle, it cannot possibly collide with it. So to have a function that returns a Boolean saying weather the rectangles collide, we simply combine the conditions by logical ORs and negate the result:
function checkOverlap(r1, r2) : Boolean
{
return !(r1.x + r1.width < r2.x || r1.y + r1.height < r2.y || r1.x > r2.x + r2.width || r1.y > r2.y + r2.height);
}
To already receive a positive result when touching only, we can change the "<" and ">" by "<=" and ">=".
This is a very fast way to check with C++ if two rectangles overlap:
return std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right)
&& std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom);
It works by calculating the left and right borders of the intersecting rectangle, and then comparing them: if the right border is equal to or less than the left border, it means that the intersection is empty and therefore the rectangles do not overlap; otherwise, it tries again with the top and bottom borders.
What is the advantage of this method over the conventional alternative of 4 comparisons? It's about how modern processors are designed. They have something called branch prediction, which works well when the result of a comparison is always the same, but have a huge performance penalty otherwise. However, in the absence of branch instructions, the CPU performs quite well. By calculating the borders of the intersection instead of having two separate checks for each axis, we're saving two branches, one per pair.
It is possible that the four comparisons method outperforms this one, if the first comparison has a high chance of being false. That is very rare, though, because it means that the second rectangle is most often on the left side of the first rectangle, and not on the right side or overlapping it; and most often, you need to check rectangles on both sides of the first one, which normally voids the advantages of branch prediction.
This method can be improved even more, depending on the expected distribution of rectangles:
If you expect the checked rectangles to be predominantly to the left or right of each other, then the method above works best. This is probably the case, for example, when you're using the rectangle intersection to check collisions for a game, where the game objects are predominantly distributed horizontally (e.g. a SuperMarioBros-like game).
If you expect the checked rectangles to be predominantly to the top or bottom of each other, e.g. in an Icy Tower type of game, then checking top/bottom first and left/right last will probably be faster:
return std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom)
&& std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right);
If the probability of intersecting is close to the probability of not intersecting, however, it's better to have a completely branchless alternative:
return std::max(rectA.left, rectB.left) < std::min(rectA.right, rectB.right)
& std::max(rectA.top, rectB.top) < std::min(rectA.bottom, rectB.bottom);
(Note the change of && to a single &)
Suppose that you have defined the positions and sizes of the rectangles like this:
My C++ implementation is like this:
class Vector2D
{
public:
Vector2D(int x, int y) : x(x), y(y) {}
~Vector2D(){}
int x, y;
};
bool DoRectanglesOverlap( const Vector2D & Pos1,
const Vector2D & Size1,
const Vector2D & Pos2,
const Vector2D & Size2)
{
if ((Pos1.x < Pos2.x + Size2.x) &&
(Pos1.y < Pos2.y + Size2.y) &&
(Pos2.x < Pos1.x + Size1.x) &&
(Pos2.y < Pos1.y + Size1.y))
{
return true;
}
return false;
}
An example function call according to the given figure above:
DoRectanglesOverlap(Vector2D(3, 7),
Vector2D(8, 5),
Vector2D(6, 4),
Vector2D(9, 4));
The comparisons inside the if block will look like below:
if ((Pos1.x < Pos2.x + Size2.x) &&
(Pos1.y < Pos2.y + Size2.y) &&
(Pos2.x < Pos1.x + Size1.x) &&
(Pos2.y < Pos1.y + Size1.y))
↓
if (( 3 < 6 + 9 ) &&
( 7 < 4 + 4 ) &&
( 6 < 3 + 8 ) &&
( 4 < 7 + 5 ))
Ask yourself the opposite question: How can I determine if two rectangles do not intersect at all? Obviously, a rectangle A completely to the left of rectangle B does not intersect. Also if A is completely to the right. And similarly if A is completely above B or completely below B. In any other case A and B intersect.
What follows may have bugs, but I am pretty confident about the algorithm:
struct Rectangle { int x; int y; int width; int height; };
bool is_left_of(Rectangle const & a, Rectangle const & b) {
if (a.x + a.width <= b.x) return true;
return false;
}
bool is_right_of(Rectangle const & a, Rectangle const & b) {
return is_left_of(b, a);
}
bool not_intersect( Rectangle const & a, Rectangle const & b) {
if (is_left_of(a, b)) return true;
if (is_right_of(a, b)) return true;
// Do the same for top/bottom...
}
bool intersect(Rectangle const & a, Rectangle const & b) {
return !not_intersect(a, b);
}
In the question, you link to the maths for when rectangles are at arbitrary angles of rotation. If I understand the bit about angles in the question however, I interpret that all rectangles are perpendicular to one another.
A general knowing the area of overlap formula is:
Using the example:
1 2 3 4 5 6
1 +---+---+
| |
2 + A +---+---+
| | B |
3 + + +---+---+
| | | | |
4 +---+---+---+---+ +
| |
5 + C +
| |
6 +---+---+
1) collect all the x coordinates (both left and right) into a list, then sort it and remove duplicates
1 3 4 5 6
2) collect all the y coordinates (both top and bottom) into a list, then sort it and remove duplicates
1 2 3 4 6
3) create a 2D array by number of gaps between the unique x coordinates * number of gaps between the unique y coordinates.
4 * 4
4) paint all the rectangles into this grid, incrementing the count of each cell it occurs over:
1 3 4 5 6
1 +---+
| 1 | 0 0 0
2 +---+---+---+
| 1 | 1 | 1 | 0
3 +---+---+---+---+
| 1 | 1 | 2 | 1 |
4 +---+---+---+---+
0 0 | 1 | 1 |
6 +---+---+
5) As you paint the rectangles, its easy to intercept the overlaps.
Here's how it's done in the Java API:
public boolean intersects(Rectangle r) {
int tw = this.width;
int th = this.height;
int rw = r.width;
int rh = r.height;
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
return false;
}
int tx = this.x;
int ty = this.y;
int rx = r.x;
int ry = r.y;
rw += rx;
rh += ry;
tw += tx;
th += ty;
// overflow || intersect
return ((rw < rx || rw > tx) &&
(rh < ry || rh > ty) &&
(tw < tx || tw > rx) &&
(th < ty || th > ry));
}
struct Rect
{
Rect(int x1, int x2, int y1, int y2)
: x1(x1), x2(x2), y1(y1), y2(y2)
{
assert(x1 < x2);
assert(y1 < y2);
}
int x1, x2, y1, y2;
};
//some area of the r1 overlaps r2
bool overlap(const Rect &r1, const Rect &r2)
{
return r1.x1 < r2.x2 && r2.x1 < r1.x2 &&
r1.y1 < r2.y2 && r2.x1 < r1.y2;
}
//either the rectangles overlap or the edges touch
bool touch(const Rect &r1, const Rect &r2)
{
return r1.x1 <= r2.x2 && r2.x1 <= r1.x2 &&
r1.y1 <= r2.y2 && r2.x1 <= r1.y2;
}
Don't think of coordinates as indicating where pixels are. Think of them as being between the pixels. That way, the area of a 2x2 rectangle should be 4, not 9.
bool bOverlap = !((A.Left >= B.Right || B.Left >= A.Right)
&& (A.Bottom >= B.Top || B.Bottom >= A.Top));
Easiest way is
/**
* Check if two rectangles collide
* x_1, y_1, width_1, and height_1 define the boundaries of the first rectangle
* x_2, y_2, width_2, and height_2 define the boundaries of the second rectangle
*/
boolean rectangle_collision(float x_1, float y_1, float width_1, float height_1, float x_2, float y_2, float width_2, float height_2)
{
return !(x_1 > x_2+width_2 || x_1+width_1 < x_2 || y_1 > y_2+height_2 || y_1+height_1 < y_2);
}
first of all put it in to your mind that in computers the coordinates system is upside down. x-axis is same as in mathematics but y-axis increases downwards and decrease on going upward..
if rectangle are drawn from center.
if x1 coordinates is greater than x2 plus its its half of widht. then it means going half they will touch each other. and in the same manner going downward + half of its height. it will collide..
For those of you who are using center points and half sizes for their rectangle data, instead of the typical x,y,w,h, or x0,y0,x1,x1, here's how you can do it:
#include <cmath> // for fabsf(float)
struct Rectangle
{
float centerX, centerY, halfWidth, halfHeight;
};
bool isRectangleOverlapping(const Rectangle &a, const Rectangle &b)
{
return (fabsf(a.centerX - b.centerX) <= (a.halfWidth + b.halfWidth)) &&
(fabsf(a.centerY - b.centerY) <= (a.halfHeight + b.halfHeight));
}
Lets say the two rectangles are rectangle A and rectangle B. Let their centers be A1 and B1 (coordinates of A1 and B1 can be easily found out), let the heights be Ha and Hb, width be Wa and Wb, let dx be the width(x) distance between A1 and B1 and dy be the height(y) distance between A1 and B1.
Now we can say we can say A and B overlap: when
if(!(dx > Wa+Wb)||!(dy > Ha+Hb)) returns true
If the rectangles overlap then the overlap area will be greater than zero. Now let us find the overlap area:
If they overlap then the left edge of overlap-rect will be the max(r1.x1, r2.x1) and right edge will be min(r1.x2, r2.x2). So the length of the overlap will be min(r1.x2, r2.x2) - max(r1.x1, r2.x1)
So the area will be:
area = (max(r1.x1, r2.x1) - min(r1.x2, r2.x2)) * (max(r1.y1, r2.y1) - min(r1.y2, r2.y2))
If area = 0 then they don't overlap.
Simple isn't it?
I have implemented a C# version, it is easily converted to C++.
public bool Intersects ( Rectangle rect )
{
float ulx = Math.Max ( x, rect.x );
float uly = Math.Max ( y, rect.y );
float lrx = Math.Min ( x + width, rect.x + rect.width );
float lry = Math.Min ( y + height, rect.y + rect.height );
return ulx <= lrx && uly <= lry;
}
I have a very easy solution
let x1,y1 x2,y2 ,l1,b1,l2,be cordinates and lengths and breadths of them respectively
consider the condition ((x2
now the only way these rectangle will overlap is if the point diagonal to x1,y1 will lie inside the other rectangle or similarly the point diagonal to x2,y2 will lie inside the other rectangle. which is exactly the above condition implies.
A and B be two rectangle. C be their covering rectangle.
four points of A be (xAleft,yAtop),(xAleft,yAbottom),(xAright,yAtop),(xAright,yAbottom)
four points of A be (xBleft,yBtop),(xBleft,yBbottom),(xBright,yBtop),(xBright,yBbottom)
A.width = abs(xAleft-xAright);
A.height = abs(yAleft-yAright);
B.width = abs(xBleft-xBright);
B.height = abs(yBleft-yBright);
C.width = max(xAleft,xAright,xBleft,xBright)-min(xAleft,xAright,xBleft,xBright);
C.height = max(yAtop,yAbottom,yBtop,yBbottom)-min(yAtop,yAbottom,yBtop,yBbottom);
A and B does not overlap if
(C.width >= A.width + B.width )
OR
(C.height >= A.height + B.height)
It takes care all possible cases.
This is from exercise 3.28 from the book Introduction to Java Programming- Comprehensive Edition. The code tests whether the two rectangles are indenticle, whether one is inside the other and whether one is outside the other. If none of these condition are met then the two overlap.
**3.28 (Geometry: two rectangles) Write a program that prompts the user to enter the
center x-, y-coordinates, width, and height of two rectangles and determines
whether the second rectangle is inside the first or overlaps with the first, as shown
in Figure 3.9. Test your program to cover all cases.
Here are the sample runs:
Enter r1's center x-, y-coordinates, width, and height: 2.5 4 2.5 43
Enter r2's center x-, y-coordinates, width, and height: 1.5 5 0.5 3
r2 is inside r1
Enter r1's center x-, y-coordinates, width, and height: 1 2 3 5.5
Enter r2's center x-, y-coordinates, width, and height: 3 4 4.5 5
r2 overlaps r1
Enter r1's center x-, y-coordinates, width, and height: 1 2 3 3
Enter r2's center x-, y-coordinates, width, and height: 40 45 3 2
r2 does not overlap r1
import java.util.Scanner;
public class ProgrammingEx3_28 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out
.print("Enter r1's center x-, y-coordinates, width, and height:");
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double w1 = input.nextDouble();
double h1 = input.nextDouble();
w1 = w1 / 2;
h1 = h1 / 2;
System.out
.print("Enter r2's center x-, y-coordinates, width, and height:");
double x2 = input.nextDouble();
double y2 = input.nextDouble();
double w2 = input.nextDouble();
double h2 = input.nextDouble();
w2 = w2 / 2;
h2 = h2 / 2;
// Calculating range of r1 and r2
double x1max = x1 + w1;
double y1max = y1 + h1;
double x1min = x1 - w1;
double y1min = y1 - h1;
double x2max = x2 + w2;
double y2max = y2 + h2;
double x2min = x2 - w2;
double y2min = y2 - h2;
if (x1max == x2max && x1min == x2min && y1max == y2max
&& y1min == y2min) {
// Check if the two are identicle
System.out.print("r1 and r2 are indentical");
} else if (x1max <= x2max && x1min >= x2min && y1max <= y2max
&& y1min >= y2min) {
// Check if r1 is in r2
System.out.print("r1 is inside r2");
} else if (x2max <= x1max && x2min >= x1min && y2max <= y1max
&& y2min >= y1min) {
// Check if r2 is in r1
System.out.print("r2 is inside r1");
} else if (x1max < x2min || x1min > x2max || y1max < y2min
|| y2min > y1max) {
// Check if the two overlap
System.out.print("r2 does not overlaps r1");
} else {
System.out.print("r2 overlaps r1");
}
}
}
bool Square::IsOverlappig(Square &other)
{
bool result1 = other.x >= x && other.y >= y && other.x <= (x + width) && other.y <= (y + height); // other's top left falls within this area
bool result2 = other.x >= x && other.y <= y && other.x <= (x + width) && (other.y + other.height) <= (y + height); // other's bottom left falls within this area
bool result3 = other.x <= x && other.y >= y && (other.x + other.width) <= (x + width) && other.y <= (y + height); // other's top right falls within this area
bool result4 = other.x <= x && other.y <= y && (other.x + other.width) >= x && (other.y + other.height) >= y; // other's bottom right falls within this area
return result1 | result2 | result3 | result4;
}
struct point { int x, y; };
struct rect { point tl, br; }; // top left and bottom right points
// return true if rectangles overlap
bool overlap(const rect &a, const rect &b)
{
return a.tl.x <= b.br.x && a.br.x >= b.tl.x &&
a.tl.y >= b.br.y && a.br.y <= b.tl.y;
}