Two Rectangles intersection - algorithm

I have two rectangles characterized by 4 values each :
Left position X, top position Y, width W and height H:
X1, Y1, H1, W1
X2, Y2, H2, W2
Rectangles are not rotated, like so:
+--------------------> X axis
|
| (X,Y) (X+W, Y)
| +--------------+
| | |
| | |
| | |
| +--------------+
v (X, Y+H) (X+W,Y+H)
Y axis
What is the best solution to determine whether the intersection of the two rectangles is empty or not?

if (X1+W1<X2 or X2+W2<X1 or Y1+H1<Y2 or Y2+H2<Y1):
Intersection = Empty
else:
Intersection = Not Empty
If you have four coordinates – ((X,Y),(A,B)) and ((X1,Y1),(A1,B1)) – rather than two plus width and height, it would look like this:
if (A<X1 or A1<X or B<Y1 or B1<Y):
Intersection = Empty
else:
Intersection = Not Empty

Best example..
/**
* 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);
}
and also one other way see this link ... and code it your self..

Should the two rectangles have the same dimensions you can do:
if (abs (x1 - x2) < w && abs (y1 - y2) < h) {
// overlaps
}

I just tried with a c program and wrote below.
#include<stdio.h>
int check(int i,int j,int i1,int j1, int a, int b,int a1,int b1){
return (\
(((i>a) && (i<a1)) && ((j>b)&&(j<b1))) ||\
(((a>i) && (a<i1)) && ((b>j)&&(b<j1))) ||\
(((i1>a) && (i1<a1)) && ((j1>b)&&(j1<b1))) ||\
(((a1>i) && (a1<i1)) && ((b1>j)&&(b1<j1)))\
);
}
int main(){
printf("intersection test:(0,0,100,100),(10,0,1000,1000) :is %s\n",check(0,0,100,100,10,0,1000,1000)?"intersecting":"Not intersecting");
printf("intersection test:(0,0,100,100),(101,101,1000,1000) :is %s\n",check(0,0,100,100,101,101,1000,1000)?"intersecting":"Not intersecting");
return 0;
}

Using a coordinate system where (0, 0) is the left, top corner.
I thought of it in terms of a vertical and horizontal sliding windows
and come up with this:
(B.Bottom > A.Top && B.Top < A.Bottom) && (B.Right > A.Left && B.Left < A.Right)
Which is what you get if you apply DeMorgan’s Law to the following:
Not (B.Bottom < A.Top || B.Top > A.Bottom || B.Right < A.Left || B.Left > A.Right)
B is above A
B is below A
B is left of A
B is right of A

If the rectangles' coordinates of the lower left corner and upper right corner are :
(r1x1, r1y1), (r1x2, r1y2) for rect1 and
(r2x1, r2y1), (r2x2, r2y2) for rect2
(Python like code below)
intersect = False
for x in [r1x1, r1x2]:
if (r2x1<=x<=r2x2):
for y in [r1y1, r1y2]:
if (r2y1<=y<=r2y2):
intersect = True
return intersect
else:
for Y in [r2y1, r2y2]:
if (r1y1<=Y<=r1y2):
intersect = True
return intersect
else:
for X in [r2x1, r2x2]:
if (r1x1<=X<=r1x2):
for y in [r2y1, r2y2]:
if (r1y1<=y<=r1y2):
intersect = True
return intersect
else:
for Y in [r1y1, r1y2]:
if (r2y1<=Y<=r2y2):
intersect = True
return intersect
return intersect

Circle approach is more straightforward. I mean when you define a circle as a center point and radius. Same thing here except you have a horizontal radius (width / 2) and a vertical one (height /2) and 2 conditions for horizontal and for vertical distance.
abs(cx1 – cx2) <= hr1 + hr2 && abs(cy1 - cy2) <= vr1 + vr2
If you need to exclude the case with sides not intersecting filter out these with one rectangle smaller in both dimensions and not enough distance (between centers) from the bigger one to reach one of its edges.
abs(cx1 – cx2) <= hr1 + hr2 && abs(cy1 - cy2) <= vr1 + vr2 &&
!(abs(cx1 – cx2) < abs(hr1 - hr2) && abs(cy1 - cy2) < abs(vr1 - vr2) && sign(hr1 - hr2) == sign(vr1 – vr2))

Rectangle = namedtuple('Rectangle', 'x y w h')
def intersects(rect_a: Rectangle, rect_b: Rectangle):
if (rect_a.x + rect_a.w < rect_b.x) or (rect_a.x > rect_b.x + rect_b.w) or (rect_a.y + rect_a.h < rect_b.y) or (rect_a.y > rect_b.y + rect_b.h):
return False
else:
return True

if( X1<=X2+W2 && X2<=X1+W1 && Y1>=Y2-H2 && Y2>=Y1+H1 )
Intersect
In the question Y is the top position..
Note: This solution works only if rectangle is aligned with X / Y Axes.

Related

Image rotation in matlab using bilinear-interpolation

clear
I = imread('256.jpg');
%imshow(I);
center = 128;
[x, y] = size(I); % declare image size array
Original = [x, y];
Rotated_I = zeros(x,y); %declare size of array to store pixel
theta = 90;
for row = 1:y
for column = 1:x
x_original = (column - 128) * cos(theta) - (row - 128)*sin(theta);
y_original = (column - 128) * sin(theta) + (row - 128)*cos(theta); % reverse rotate
p = floor(x_original);
q = floor(y_original);
a = y_original - p;
b = x_original - q; %
Rotated_I(column, row) = (1-a)*((1-b)*Original(p,q)+b*Original(p,q+1))+a*((q-b)*Original(p+1,q)+b*Original(p+1,q+1)); % Find pixel using bilinear interpolation
end
end
imshow(Rotated_I);
I tried to rotate image using reverse rotate and bilinear interpolation, but only i see is error message. It says "the first index exceeds array". Is there anything wrong in my code?
Here is a working version with a number of changes. The main difference is that it checks whether a coordinate exists in the original image before adding that to the rotate image. This allows for arbitrary rotations, like 45 degrees. Also, images in MATLAB have y as the first dimension and x as the second, so are accessed as I(y, x) or I(row, column).
clear
I = imread('256.jpg');
% imshow(I);
center = 128;
[y, x] = size(I); % in MATLAB, images are y-by-x in size (ie. y is dimension 1)
Original = I; % Original needs to be the image I
Rotated_I = zeros(y, x);
theta = 90;
for row = 1:y
for column = 1:x
x_original = (column - center) * cosd(theta) - (row - center)*sind(theta) + center; % theta is in degrees so use cosd and sind
y_original = (column - center) * sind(theta) + (row - center)*cosd(theta) + center; % also add center back on
p = floor(y_original); % x_original and y_original were swapped here
q = floor(x_original); % x_original and y_original were swapped here
a = y_original - p;
b = x_original - q;
% check if the coordinate is in the original image to prevent errors
if p > 0 && p <= y && q > 0 && q <= x
Rotated_I(row, column) = Rotated_I(row, column) + (1-a)*(1-b)*Original(p,q);
end
if p > 0 && p <= y && q+1 > 0 && q+1 <= x
Rotated_I(row, column) = Rotated_I(row, column) + (1-a)*b*Original(p,q+1);
end
if p+1 > 0 && p+1 <= y && q > 0 && q <= x
Rotated_I(row, column) = Rotated_I(row, column) + a*(1-b)*Original(p+1,q);
end
if p+1 > 0 && p+1 <= y && q+1 > 0 && q+1 <= x
Rotated_I(row, column) = Rotated_I(row, column) + a*b*Original(p+1,q+1);
end
end
end
% convert to uint image so it displays properly (double expects values from 0 to 1)
imshow(uint8(Rotated_I));
I do not know if you necessarily want to have your own implementation or not. But if not, you could always use imrotate:
Rotated_I = imrotate(I, 90, 'bilinear', 'crop');
90 => Degrees of rotation
'bilinear' => Bilinear interpolation (alternatives: nearest, bicubic)
'crop' => Maintain the pixel size of the rotated image the same as the input image
imrotate is part of the Image Processing Toolbox.

Zig-Zag Triangle Traversal Implementation

I was trying to follow "On the Hardware Implementation of Triangle Traversal Algorithms for Graphics Processing" (Royer, Ituero, Lopez-Vallejo, & Barrio) (page 4) to implement Zig-Zag traversal algorithm for triangle triversal/rasterization. However, the explanation in the paper is counter-intuitive for me and I was not able to make it work.
I tried to implement a finite state machine but I can't quite figure out the exact states. For now, I'm having (direction, e_1, e_2, e_3) where e_n represent edge test output for each edge. Pseudo code:
if (right, true, true, true):
x++; // Move towards right
else if (left, true, true, true):
x--; // Move towards left
else:
// This is where I stuck. There should be two cases where in one of them
// y goes down and x doesn't change direction, in the other case x simply
// flips its direction. But I wasn't able to figure it out.
Any help would be appreciated!
Edit: My effort so far:
While the edge test is working correctly, only few parts of the graph was rasterized.
/// Zig Zag (not working)
int top_row = floor(fmin(y0, fmin(y1, y2)));
int bot_row = floor(fmax(y0, fmax(y1, y2)));
if (y0 > y1) {
swap(x0, x1); swap(y0, y1);
}
if (y0 > y2) {
swap(x0, x2); swap(y0, y2);
}
if (y1 > y2) {
swap(x1, x2); swap(y1, y2);
}
assert(top_row == floor(y0));
assert(bot_row == floor(y2));
bool direction = true;
bool changed = false;
int x = floor(x0); int y = floor(y0);
while (y <= bot_row) {
bool e1, e2, e3;
e1 = edge_test((float)x+0.5, (float)y+0.5, x0, y0, x1, y1) < 0.0f;
e2 = edge_test((float)x+0.5, (float)y+0.5, x1, y1, x2, y2) < 0.0f;
e3 = edge_test((float)x+0.5, (float)y+0.5, x2, y2, x0, y0) < 0.0f;
if ((e1 == e2) && (e2 == e3)) {
if ( x < 0 || x >= width ) continue;
if ( y < 0 || y >= height ) continue;
samplebuffer[y][x].fill_pixel(color);
if (direction) x++;
else x--;
} else if (changed) {
y++;
changed = false;
} else {
direction = !direction;
changed = true;
if (direction) x++;
else x--;
}
}
How I see state machine:
Dir = +1 / -1
State 0: (moving inside)
EdgeTest:
0 => State 1 ; y++
1 => State 0 ; x = x + Dir
State 1: (outside)
EdgeTest:
0 => State 3 ; Dir = - Dir
1 => State 2 ;
State 2: (inside moving the same dir)
EdgeTest:
0 => State 3 ; Dir = - Dir
1 => State 2 ; x= x + Dir
State 3: (outside)
EdgeTest:
0 => State 3 ; x = x + Dir
1 => State 0 ;

How to compute the intersection between a quadratic bezier curve and a horizontal line?

What I am trying to do get the X coordinates at which a certain bezier curve crosses a horizontal line (a y coordinate). For the moment, I have this code:
function self.getX(y)
if y > maxY or y < minY then
return
end
local a = y1 - y
if a == 0 then
return
end
local b = 2*(y2 - y1)
local c = (y3 - 2*y2 + y1)
local discriminant = (b^2 - 4*a*c )
if discriminant < 0 then
return
else
local aByTwo = 2*a
if discriminant == 0 then
local index1 = -b/aByTwo
if 0 < index1 and index1 < 1 then
return (1-index1)^2*x1+2*(1-index1)*index1*x2+index1^2*x3
end
else
local theSQRT = math.sqrt(discriminant)
local index1, index2 = (-b -theSQRT)/aByTwo, (-b +theSQRT)/aByTwo
if 0 < index1 and index1 < 1 then
if 0 < index2 and index2 < 1 then
return (1-index1)^2*x1+2*(1-index1)*index1*x2+index1^2*x3, (1-index2)^2*x1+2*(1-index2)*index2*x2+index2^2*x3
else
return (1-index1)^2*x1+2*(1-index1)*index1*x2+index1^2*x3
end
elseif 0 < index2 and index2 < 1 then
return (1-index2)^2*x1+2*(1-index2)*index2*x2+index2^2*x3
end
end
end
end
A few specifications:
This is Lua code.
local means the variable is local to the chunk of code, so it does not affect the code's functionality.
y1, y2, and y3 are the y coordinate of the 3 points. The same applies to x1, x2, x3.
y is the y coordinate of the horizontal line I am computing.
maxY is the biggest of the 3 y's.
minY is the smallest.
For the moment this code gives me this:
There are 8 bezier curves
The green ones are generated using the normal method: (1-t)^2*x1+2*(1-t)*t*x2+t^2*x3
The red dots are the control points.
The white lines are what is generated using the method described with the code above.
The straight lines are lines, ignore them.
There should be 8 curves, but only 4 are rendered.
Thanks in advance,
Creator!
The Bézier curve has
y(t)=(1-t)^2*y1+2(1-t)*t*y2+t^2*y
which expands to
(y1-2*y2+y3)*t^2+2(y2-y1)*t+y1
You have swapped a and c in the quadratic equation a*t^2+b*t+c=0 required for solving y(t)=y.

Algorithm to find all line segment intersections given n lines

I'm looking for a algorithm to find all the intersection points given n line segments.
Below is the pseudo code from http://jeffe.cs.illinois.edu/teaching/373/notes/x06-sweepline.pdf
The input S[1 .. n] is an array of line
segments.
label[i] is the label of the ith leftmost endpoint.
sort the endpoints of S from left to right
create an empty label sequence
for i ← 1 to 2n
line ← label[i]
if isLeftEndPoint[i]
Insert(line)
if Intersect(S[line], S[Successor(line)])
return TRUE
if Intersect(S[line], S[Predecessor(line)])
return TRUE
else
if Intersect(S[Successor(line)], S[Predecessor(line)])
return TRUE
Delete(label[i])
return FALSE
Apply the algorithm to the line set below, only one intersection point is checked. What should I do to know the existence of the other 2 intersection points?
line[1] enters
line[2] enters, intersection between line[1] and line[2] is checked.
line[3] enters, intersection between line[2] and line[3] is checked.
line[4] enters, intersection between line[4] and line[1] is checked. Intersection A is found.
line[4] leaves, nothing is checked.
line[1] leaves, nothing is checked.
line[2] leaves, nothing is checked.
line[3] leaves, nothing is checked.
Standard line equation
Ax+By=C
The slope(m) of a line defined by the standard line of equation is
m = -(A/B)
Point-slope line equation
y-y1=m(x-x1)
Substituting m = (-A/B) in the point-slope line equation
y2-y1 = (A/-B)*(x2-x1)
(y2-y1)/(x2-x1) = A/-B
thus:
A = y2-y1
B = x1-x2
C = Ax+By
x = (C-By)/A
y = (C-Ax)/B
Given two lines with equation
A1x1+B1y1=C1 and A2x2+B2y2=C2.
Then the point of intersection between the lines is specified
by the points that make A1x+B1y-C1 = A2x+B2y-C2
A1x+B1y=C1
A2x+B2y=C2
A1B2x+B1B2y=B2C1 (multiply the first equation by B2)
A1B2x+B1B2y-B2C1=0
A2B1x+B1B2y=B1C2 (multiply the second equation by B1)
A2B1x+B1B2y-B1C2=0
Equating the two equations
A1B2x+B1B2y-B2C1=A2B1x+B1B2y-B1C2
A1B2x+B1B2y-B2C1-A2B1x-B1B2y+B1C2=0
A1B2x-B2C1-A2B1x+B1C2=0
A1B2x-A2B1x=B2C1-B1C2
x(A1B2-A2B1)=B2C1-B1C2
x = (B2C1-B1C2)/A1B2-A2B1
A1x+B1y=C1
A2x+B2y=C2
A1A2x+A2B1y=A2C1 (multiply the first equation by A2)
A1A2x+A2B1y-A2C1=0
A1A2x+A1B2y=A1C2 (multiply the second equation by A1)
A1A2x+A1B2y-A1C2=0
Equating the two equations
A1A2x+A2B1y-A2C1=A1A2x+A1B2y-A1C2
A1A2x+A2B1y-A2C1-A1A2x-A1B2y+A1C2=0
A1C2-A2C2=A1B2y-A2B1y
A1B2y-A2B1y=A1C2-A2C2
y(A1B2-A2B1)=A1C2-A2C1
y(A1B2-A2B1)=A1C2-A2C1
y = (A1C2-A2C1)/(A1B1-A2B1)
the denominator in y and in x are the same so
denominator = A1B1-A2B1
thus:
x = (B2C1-B1C2)/denominator
y = (A1C2-A2C1)/denominator
These are the x and y coordinates of the intersection of two lines with points (x1, y1), (x2, y2) and (x3, y3), (x4, y4)
Now for a line segment it's the same but we need to check that the x or y coordinate is in both segments. That means between the x coordinate of both segments with lesser value and the x coordinate of both segments with greater value
This is a C++ program that returns true if the segments intersect and returns false if they don't. If the segments intersect it stores the point of intersection in a variable i.
struct Point
{
float x, y;
};
//p1 and p2 are the points of the first segment
//p3 and p4 are the points of the second segment
bool intersection(Point p1, Point p2, Point p3, Point p4, Point &i)
{
float max1; //x-coordinate with greater value in segment 1
float min1; //x-coordinate with lesse value in segment 1
float max2; //x-coordinate with greater value in segment 2
float min2; //x-coordinate with lesser value in segment 2
float A1 = p2.y - p1.y;
float B1 = p1.x - p2.x;
float C1 = A1 * p1.x + B1 * p1.y;
float A2 = p4.y - p3.y;
float B2 = p3.x - p4.x;
float C2 = A2 * p3.x + B2 * p3.y;
float denom = A1 * B2 - A2 * B1;
if (denom == 0.0) //When denom == 0, is because the lines are parallel
return false; //Parallel lines do not intersect
i.x = (C1 * B2 - C2 * B1) / denom;
i.y = (A1 * C2 - A2 * C1) / denom;
if (p1.x > p2.x)
{
max1 = p1.x;
min1 = p2.x;
}
else
{
max1 = p2.x;
min1 = p1.x;
}
if (p3.x > p4.x)
{
max2 = p3.x;
min2 = p4.x;
}
else
{
max2 = p4.x;
min2 = p3.x;
}
//check if x coordinate is in both segments
if (i.x >= min1 && i.x <= max1 &&
i.x >= min2 && i.x <= max2)
return true;
return false; //Do no intersect, intersection of the lines is not between the segments
}
Now you just need to compare on a loop all the segments and store the intersection point on array.

Point in polygon algorithm explanation

Hi I came across this algorithm from Mathhelpforum which determines whether a point is inside or outside a polygon. The code works perfectly so far but I don't fully understand the logic. Kindly provide an explanation if you do, especially on the method...whether ray casting, or winding number, etc. Thanks.
function [ inside ] = inpoly(polygon,xt,yt)
rows = size(polygon);
npoints = rows(1);
disp (npoints);
inside = 0;
xold = polygon(npoints,1);
yold = polygon(npoints,2);
for i = 1:1:npoints
xnew = polygon(i,1);
ynew = polygon(i,2);
if (xnew > xold)
x1=xold;
x2=xnew;
y1=yold;
y2=ynew;
else
x1=xnew;
x2=xold;
y1=ynew;
y2=yold;
end
if ((xnew < xt) == (xt <= xold) & (yt-y1)*(x2-x1) < (y2-y1)*(xt-x1) )
inside=~inside;
end
xold=xnew;
yold=ynew;
end
endfunction
To test the function e.g. :
inpoly([p,q],x,y)
Where p and q are vertices of the polygon and x, y coordinates of the point.
Seems a ray casting to me. Varaibles x1, y1, x2, y2 are the polygon side's endpoints sorted with respect to X. The condition (xnew < xt) == (xt <= xold) tests whether the Y-parallel line from the point xt,yt meets the side. The other part of the condition tests if xt,yt is at the proper side of the polygon's side.
Condition
(yt-y1)*(x2-x1) < (y2-y1)*(xt-x1)
is equivalent to
(yt-y1)*(x2-x1) - (y2-y1)*(xt-x1) < 0
which is a matrix determinant
| yt-y1 xt-x1 |
| | < 0
| y2-y1 x2-x1 |
and the matrix is a vector cross product
(pointT - point1) times (point2 - point1)

Resources