Algorithm Questions: how to determine rectangle is inside the another rectangle? - algorithm

Given a list of tuples (including x, y, width, height which four values define a rectangle in two-dimension coordination).
The goal is to check in the original list, whether one rectangle is inside another rectangle (if it is, only take the smaller one, larger one is discarded)

The most obvious solution, if it isn't too slow, is to define rect1.contains(rect2) as:
rect1.x <= rect2.x && rect1.y <= rect2.y && rect1.x + rect1.width >= rect2.x + rect2.width && rect1.y + rect1.height >= rect2.y + rect2.height
and then check every rect in the list to see if it contains any others. (Don't check it against itself, though!)

Check on this:
http://www.jstor.org/stable/2691523?seq=1#page_scan_tab_contents
and
Find out if a rectangle is inside another rectangle [C]

Related

Check if a rectangle bisects another rectangle

I have two rectangles on a grid, defined by x, y, width, and height (all integers).
I want to tell if one of them bisects the other. That is, not just overlaps, but goes all the way through so as to create three rectangles.
Example:
Is there a relatively time-efficient algorithm to do this?
If we look at the second example in your question, we can find the following conditions to determine if rectangle A bisects rectangle B vertically:
xA <= xB && xA + widthA >= xB + widthB && yA > yB && yA + heightA < yB + heightB
Similarly, there are three more cases (horizontal and the same for the other way around). If any of these cases apply, you have a bisection.

What is the best way to check all pixels within certain radius?

I'm currently developing an application that will alert users of incoming rain. To do this I want to check certain area around user location for rainfall (different pixel colours for intensity on rainfall radar image). I would like the checked area to be a circle but I don't know how to do this efficiently.
Let's say I want to check radius of 50km. My current idea is to take subset of image with size 100kmx100km (user+50km west, user+50km east, user+50km north, user+50km south) and then check for each pixel in this subset if it's closer to user than 50km.
My question here is, is there a better solution that is used for this type of problems?
If the occurrence of the event you are searching for (rain or anything) is relatively rare, then there's nothing wrong with scanning a square or pixels and then, only after detecting rain in that square, checking whether that rain is within the desired 50km circle. Note that the key point here is that you don't need to check each pixel of the square for being inside the circle (that would be very inefficient), you have to search for your event (rain) first and only when you found it, check whether it falls into the 50km circle. To implement this efficiently you also have to develop some smart strategy for handling multi-pixel "stains" of rain on your image.
However, since you are scanning a raster image, you can easily implement the well-known Bresenham circle algorithm to find the starting and the ending point of the circle for each scan line. That way you can easily limit your scan to the desired 50km radius.
On the second thought, you don't even need the Bresenham algorithm for that. For each row of pixels in your square, calculate the points of intersection of that row with the 50km circle (using the usual schoolbook formula with square root), and then check all pixels that fall between these intersection points. Process all rows in the same fashion and you are done.
P.S. Unfortunately, the Wikipedia page I linked does not present Bresenham algorithm at all. It has code for Michener circle algorithm instead. Michener algorithm will also work for circle rasterization purposes, but it is less precise than Bresenham algorithm. If you care for precision, find a true Bresenham on somewhere. It is actually surprisingly diffcult to find on the net: most search hits erroneously present Michener as Bresenham.
There is, you can modify the midpoint circle algorithm to give you an array of for each y, the x coordinate where the circle starts (and ends, that's the same thing because of symmetry). This array is easy to compute, pseudocode below.
Then you can just iterate over exactly the right part, without checking anything.
Pseudo code:
data = new int[radius];
int f = 1 - radius, ddF_x = 1;
int ddF_y = -2 * radius;
int x = 0, y = radius;
while (x < y)
{
if (f >= 0)
{
y--;
ddF_y += 2; f += ddF_y;
}
x++;
ddF_x += 2; f += ddF_x;
data[radius - y] = x; data[radius - x] = y;
}
Maybe you can try something that will speed up your algorithm.
In brute force algorithm you will probably use equation:
(x-p)^2 + (y-q)^2 < r^2
(p,q) - center of the circle, user position
r - radius (50km)
If you want to find all pixels (x,y) that satisfy above condition and check them, your algorithm goes to O(n^2)
Instead of scanning all pixels in this circle I will check only only pixels that are on border of the circle.
In that case, you can use some more clever way to define circle.
x = p+r*cos(a)
y = q*r*sin(a)
a - angle measured in radians [0-2pi]
Now you can sample some angles, for example twenty of them, iterate and find all pairs (x,y) that are border for radius 50km. Now check are they on the rain zone and alert user.
For more safety I recommend you to use multiple radians (smaller than 50km), because your whole rain cloud can be inside circle, and your app will not recognize him. For example use 3 incircles (r = 5km, 15km, 30km) and do same thing. Efficiency of this algorithm only depends on number of angles and number of incircles.
Pseudocode will be:
checkRainDanger()
p,q <- position
radius[] <- array of radii
for c = 1 to length(radius)
a=0
while(a<2*pi)
x = p + radius[c]*cos(a)
y = q + radius[c]*sin(a)
if rainZone(x,y)
return true
else
a+=pi/10
end_while
end_for
return false //no danger
r2=r*r
for x in range(-r, +r):
max_y=sqrt(r2-x*x)
for y in range(-max_y, +max_y):
# x,y is in range - check for rain

An algorithm to randomly place circles at least D distance apart

I'm trying to work out how to write an algorithm to randomly place circles of R radius, in a 2d rectangle of arbitrary dimensions, such that each placed circle is at least D distance away from other circles in the rectangle,
The rectangle doesn't need to be filled, to be more specific older circles may be destroyed, so I need to be able to place a new circle that respects the positions of the last N circles I've already placed (say 5 for eg), if it can't satisfy these conditions then I could handle it seperately.
Can anyone help me how to deduce such an algorithm, or perhaps point to some research that may cover this?
1 Place circle at random location
2 Loop over previous circles
3 if too close
4 delete new circle
5 goto 1
6 if need more circles
7 goto 1
To determine if there is room
Choose resolution required, say delta = D/100
for( x = 0; x < rectangle_size x += delta )
for( y = 0; y < rectangle_size y += delta )
unset failed
loop over circles
if x,y less than 2D from circle
set failed
break from circle loop
if not failed
return 'yes there is room'
return 'no, there is no room'
If you expect to have so many circles that there only a few holes left with room for new circles, then you could do this
clear candidates
Choose resolution required, say delta = D/100
for( x = 0; x < rectangle_size x += delta )
for( y = 0; y < rectangle_size y += delta )
unset failed
loop over circles
if x,y less than 2D from circle
set failed
break from circle loop
if not failed
add x,y to candidates
if no candidates
return 'there is no room'
randomly choose location for new circle from candidates
1. Pick random startingspot.
2. Place circle
3. Move in random direction at least D
4. Goto 2 until distance to edge is < D or the distance to another circles center is < 2D
The first algorithm to come to mind is simulated annealing. Basically, you start out with the easiest solution, probably just a grid, then you "shake the box" in random ways to see if you get better answers. First you do large shakes, then gradually make them smaller. It sounds a little chaotic, and doesn't always produce the absolute best solution, but when something is computationally intensive it usually comes pretty close in a lot shorter time.
It really depends on what you mean by "random". Assuming that you want as close to a uniform distribution as possible, you will probably have to use an iterative solution like the one ravenspoint suggested. It may be slightly faster to place all of the circles randomly and then start replacing circles that don't meet your distance condition.
If the randomness isn't that important - i.e. if it just has to "look" random (which is probably fine if you're not doing something scientific), then grid your space up and place your N circles by choosing N indices in the grid. You could make it slightly more "random" by adding some noise to the location that you place the circle inside the grid. This would work really well for sparse placement.

How can i extract rectangles from a rectangle intersection

Having a rectangle (A) and intersecting it with another rectangle (B), how could I extract the other rectangles created through that intersection (C,D,E & F)?
AAAAAAAAAAAAAA CCCFFFFDDDDDDD
AAABBBBAAAAAAA CCCBBBBDDDDDDD
AAABBBBAAAAAAA -> CCCBBBBDDDDDDD
AAAAAAAAAAAAAA CCCEEEEDDDDDDD
AAAAAAAAAAAAAA CCCEEEEDDDDDDD
And could this be extended to extract rectangles from several intersections, such as this example which intersects A with B & C and extracts D, E, F & G?
BBBBAAAAAAAAAA BBBBDDDDDDDDDD
BBBBAAAAAAAAAA BBBBDDDDDDDDDD
AAAAAACCCCCAAA -> EEEEEECCCCCFFF
AAAAAACCCCCAAA EEEEEECCCCCFFF
AAAAAAAAAAAAAA EEEEEEGGGGGFFF
If the answer to TJB's question is yes, then they are:
(left, top, right, bottom) notation
C = (A.left, A.top, B.left, A.bottom)
D = (B.right, A.top, A.right, A.bottom)
E = (B.left, B.bottom, B.right, A.bottom)
E = (B.left, A.top, B.right, B.top)
Assuming B is completely Contained in A, it would be something like:
Rectangle[] GetSurrounding( Rectangle outer, Rectangle inner )
{
Rectangle left, top, right, bottom; // Initialize all of these...
left = new Rectangle( outer.Left, outer.Top, outer.Height, inner.Left - outer.Left );
top = new Rectangle( inner.Left, outer.Top, inner.Top - outer.Top, inner.Width );
// So on and so forth...
return new Rectangle[]{ left, top, right, bottom };
}
// This assumes:
Rectangle( x , y , height, width ); // Constructor
Also, deciding weather you stretch the left and right rectangles the full height or the top and bottom rectangles the full width is arbitrary, and will either need to be a constant decision or a parameter to the method. Other cases where the rectangles only partially overlap will require more logic looking at the MAX/MIN of values to check for going out of bounds etc.
If A completly contains B:
Rectange C = new Rectangle(A.X,A.Y,B.X-A.X,A.Height);
Rectange D = new Rectangle(B.Right,A.Y,A.Right-B.Right,A.Height);
Rectange E = new Rectangle(B.X,B.Bottom,B.Width,A.Bottom-A.Bottom);
Rectange F = new Rectangle(B.X,A.Y,B.Width,B.Y-A.Y);
this is .NET, I'm not sure about the language of your code, but I think most of the structures look simular in different languages, in .NET the constructor of a System.Drawing.Rectangle is (X,Y,Width,Height)
for more arbitrary shapes a scanline algorithm would work. you will get different results depending on whether you scan horizontally or vertically (your example matches a vertical scan)
essentially you scan along each column or row and break it into intervals between each shape, intervals on the next column or row with the same start and end can be merged.
Given a large rectangle with any number of smaller rectangles punched out of it, you can use a greedy algorithm to break up the remaining area of the large rectangle into smaller rectangles.
Pick the leftmost, uppermost point that hasn't been covered yet.
Start a rectangle there.
Extend it downwards as far as it can go.
Then extend it rightwards as far as it can go.
Add that rectangle to your collection and repeat.
This is not guaranteed to produce the minimum number of rectangles.
The first step is the most complicated one. If you don't mind a little randomness, an easier thing to do would be to pick random points until you find one that isn't covered yet; then go left until you hit an edge; then go up until you hit an edge.
For a general solution to this (the second half of your question), you should use a corner-stitching data structure, which does exactly this (and more).
for all rectangles A
for all corners C of A
for all other rectangles B
if C is inside B
for all corners D of B
if D is inside A
got rectangle C-D
endif
endfor
endif
endfor
endfor
endfor

Laying out overlapping rectangles

I am trying to layout a bunch of overlapping rectangles that start out like this:
alt text http://img690.imageshack.us/img690/209/picture1bp.png
The 2-pass algorithm I thought up is roughly:
// Pass 1 - Move all rectangles to the right until they do not overlap any other rectangles
rects = getRectsSortedOnTopLeft(); // topmost first, all rects same size
foreach(rect in rects)
{
while(rect.collidingRects().size() != 0)
{
rect.x += RECT_SIZE;
}
}
This (probably) ends up with rectangles laid out like:
alt text http://img685.imageshack.us/img685/9963/picture2bc.png
This is not aesthetically pleasing so I thought of a second pass which would move them all left starting again from the topmost:
// Pass 2
foreach(rect in rects)
{
while(rect.x >= LEFT_MARGIN)
{
assert(rect.collidingRects().size() == 0);
rect.x -= RECT_WIDTH;
if(rect.collidingRects().size() != 0)
{
rect.x += RECT_WIDTH;
break;
}
}
}
I think this should end up looking like below (looks exactly correct in practice):
alt text http://img511.imageshack.us/img511/7059/picture3za.png
However, I am wary of this algorithm because I am not sure if it will lay out correctly in all cases and it may be really slow. Do you think this algorithm can work? Can you make some suggestions on a better algorithm?
I think that this problem is of polynomial complexity. Assuming your example's limitation of only two rectangles overlapping at any given point is not a true limitation of the problem, you would need to try every possible order of bumping the rectangles to the right in order to produce the optimal (least wide) result. This is a form of space packing problem, and those are Hard unless your data set is small enough to brute force.
However, one small improvement to your pseudocode is possible, which would improve its performance in many cases.
Consider this desired final result:
A
A C
A C E
A C E
B C E
B D E
B D F
B D F
D F
F
(where all four of one character are a single rectangle)
Your first pass would move everything except A to the right, forming a staircase. Then in the second pass your code would decline to move B to the left margin, because the first attempt to move it would overlap with E. What you need to do is start at the left margin and check for the leftmost position you can move each rectangle to in pass 2.
Pseudocode:
// Pass 1 - Move all rectangles to the right until they do not overlap any other rectangles
rects = getRectsSortedOnTopLeft(); // topmost first, all rects same width
foreach(rect in rects)
while(rect.collidingRects())
rect.x += RECT_WIDTH;
// Pass 2 - Move all rectangles to the leftmost position in which they don't overlap any other rectangles
foreach(rect in rects)
for(i=LEFT_MARGIN; i+=RECT_WIDTH; i<rect.x)
{
o = rect.x;
rect.x = i;
if(rect.collidingRects())
rect.x = o;
}
You could use a physics-based approach, where the blocks are rigid bodies an fall to the left:
No, this wouldn't produce the best result all the time, but having watched your screencast I think it would be very intuitive to use in an interactive program, and it might be suitable :)

Resources