Square Grid - (Rotated) Rect intersection - Calculate all intersection cells - math

We have Square Grid with a Cell width and height of 1.0
The grid can be of any size, let's say 25x25 for this example.
Now there's a rectangle (or a line with a thickness), that has an arbitrary start and end point, e.g. start point (2.2, 1.0) end point (20.4, 5.5), thickness 1.5. The start and end point are in the center of a rectangle line, hence the thickness expands equally on both sides of the line.
How can one calculate all cell coordinates that this rectangle intersects with?

To enumerate all intersected cells for thin line case, there is method of Amanatides and Woo A Fast Voxel Traversal Algorithm for Ray Tracing.
Here is practical implementation.
For thick line you may choose two parallel edges of rectangle and walk through them synchronously by some coordinate (X or Y), at every step getting the whole scanline.
For your case (arbitrary coordinates, probably not exact):
bottom left corner is in (2,0) cell, top left in (2,1) cell
(2,0)-(2,1) vertical scanline contains two cells
walk with bottom ray to (3,0), wait until top ray reaches X=3
walk with top ray to (2,2), add this cell to the last scanline
walk with top ray to (3,2)
(3,0)-(3,2) vertical scanline contains three cells
and so on

Related

How to detect whether a circle and a polygon overlap?

I am implementing a function that can detect whether a circle and a polygon are overlapping or not.
I have all the points of the polygon and I know the center points and radius of the circle.
There I check two scenarios:
polygon vertices are inside the circle
circle center is inside the polygon
But there are other scenarios in which a circle and a polygon are overlapping, as shown in the attached image. Can anyone suggest validation for finding the intersection?
Here is a possible approach.
If one of the polygon vertices is inside the circle, there is overlap.
If the the circle center is inside the polygon, they overlap. Note that this test is not trivial for non-convex shape. For example consider a polygon similar to a thin spiral.
Otherwise, for every edge (a,b) of the polygon:
Find p, the projection of the circle center to the line (a,b).
If the distance of p to the circle center is larger than the radius, there is no overlap for this edge.
Otherwise, if p is between a and b (so p_x between a_x and b_x, and also p_y between a_y and b_y, to include the case of horizontal and vertical edges), then there is overlap for this edge, otherwise not.

Dividing space outside of convex polygons into horizontally spanning quadrilaterals

I'm looking for an algorithm that can take an area containing a set of non-overlapping convex polygons as input, and break the space outside of the polygons into a set of non-overlapping convex quadrilaterals. The quadrilaterals need to have the property that they (individually) use as much horizontal space as possible.
Here's the input:
Here's the desired output:
I feel like I have seen some variation of this algorithm used to calculate regions to be flood-filled in very old paint programs. Is there a pleasant way to do this in better than O(n^2) time?
Edit: I realize there are some triangles in the output. I should probably state that quadrilaterals are the desired output, falling back to triangles only when it's physically impossible to use a quad.
I came up with a solution to this. In order to solve this efficiently, some sort of spatial data structure is needed in order to query which polygons are overlapped by a given rectangular area. I used a Quadtree. It's also necessary for the polygon data structure being used to be able to distinguish between internal and external edges. An edge is internal if it is common to two polygons.
The steps are as follows (assuming a coordinate system with the origin in the top-left corner):
Insert all polygons into whatever spatial data structure you're using.
Iterate over all polygons and build a list of all of the Y values upon
which vertices occur. This has the effect of conceptually dividing up
the scene into horizontal strips:
Iterate over the pairs of Y values from top to bottom. For each
pair (y0, y1) of Y values, declare a rectangular area a with
the the top left corner (0, y0) and bottom right corner
(width, y1). Determine the set of polygons S that are
overlapped by a by querying the spatial data structure. For
each polygon p in S, determine the set of edges E of p
that are overlapped by a. For best results, ignore any edge in
E with a normal that points directly up or down. For each
edge e in E, it's then necessary to determine the pair of
points at which e intersects the top and bottom edges of a.
This is achieved with a simple line intersection test,
treating the top and bottom edges of a as simple horizontal
line segments. Join the intersection points to create a set of
new line segments, shown in red:
Create vertical line segments L0 = (0, y0) → (0, y1) and
L1 = (width, y0) → (width, y1). Working from left to right,
gather any line segments created in the preceding step into pairs,
ignoring any line segments that were created from internal edges.
If there were no intersecting external edges, then the only two
edges will be L0 and L1. In this example strip, only four
edges remain:
Join the vertices in the remaining pairs of edges to create
polygons:
Repeating the above process for each horizontal strip achieves
the desired result. Assuming a set of convex, non-overlapping
polygons as input, the created polygons are guaranteed to be
either triangles or quadrilaterals. If a horizontal strip contains
no edges, the algorithm will create a single rectangle. If no
polygons exist in the scene, the algorithm will create a single
rectangle covering the whole scene.

How do I find the dimensions of a rotated rectangle within an unrotated rectangle such that area is maximized?

I have a rectangle that is W x H.
Within that rectangle is another rectangle that is rotated by ϴ degrees which is always between -45 and 45 degrees, and shares the same center as the outer rectangle. I need to find w and h such that the area of the inner rectangle is maximized.
Here's a (ghetto) image to illustrate a bit. Though, the corners of the rectangles should probably be touching, I assume?
Here is the prototype of the function I'm looking to write:
SizeD GetMaxRectangleSize(double outerWidth, double outerHeight, float angle)
SizeD is just a struct that has a width and height in doubles.
Thanks to the comments for steering me in the right direction!
My solution, though perhaps not mathematically optimal, was to assume that if all four corners of the inner rectangle fall on the outer rectangle then area will be maximized.
Therefore:
H = wSin(ϴ) + hCos(ϴ)
W = wCos(ϴ) + hSin(ϴ)
Solving for w and h and substituting gives:
h = (HCos(ϴ) - WSin(ϴ))/(cos(ϴ)^2 - sin(ϴ)^2)
w = (WCos(ϴ) - HSin(ϴ))/(cos(ϴ)^2 - sin(ϴ)^2)
Which happens to work for ϴ = [0,45), and (-45,0] should act the same.
The tricky part of this question isn't how to calculate the area of an interior rectangle, but which of all the possible interior rectangles has maximum area?
To start with, observe that the box in your image is the same area regardless of how it is slid around horizontally, and if it is slid to the rightmost wall, it allows for an easy parameterization of the problem as follows:
I find it a bit easier to think of this problem, with the fixed box rotated by the offset angle so that the interior box lines up in a standard orientation. Here's a figure (I've changed theta to beta just because I can type it easily on a mac, and also left off the left most wall for reasons that will be clear):
So think of this constructed as follows: Pick a point on the right side of the exterior rectangle (shown here by a small circle), note the distance a from this point to the corner, and construct the largest possible interior with a corner at this point (by extending vertical and horizontal lines to the exterior rectangle). Clearly, then, the largest possible rectangle is one of the rectangles derived from the different values for a, and a is a good parameter for this problem.
So given that, then the area of the interior rectangle is:
A = (a * (H-a))/(cosß * sinß)
or, A = c * a * (H-a)
where I've folded the constant trig terms into the constant c. We need to maximize this, and to do that the derivative is useful:
dA/da = c * (H - 2a)
That is, starting at a=0 (ie, the circle in the figure is in the lower corner of the exterior rectangle, resulting in a tall and super skin interior rectangle), then the area of the interior rectangle increases monotonically until a=H/2, and then the area starts to decrease again.
That is, there are two cases:
1) If, as a increase from 0 to H/2, the far interior corner hits the opposite wall of the exterior, then the largest possible rectangle is when this contact occurs (and you know it's the largest due to the monotonic increase -- ie, the positive value of the derivative). This is your guess at the solution.
2) If the far corner never touches a wall, then the largest interior rectangle will be at a=H/2.
I haven't explicitly solved here for the area of the interior rectangle for each case, since that's a much easier problem than the proof, and anyone who could follow the proof, I assume could easily calculate the areas (and it does take a long time to write these things up).

Math Problem: Getting Coordinates From Position And Angle

let me begin by stating that's i'm dreadful at math.
i'm attempting to reposition and rotate a rectangle. however, i need to rotate the rectangle from a point that is not 0,0 but according to how far its coordinates has shifted. i'm sure that doesn't make much sense, so i've made some sketches to help explain what i need.
the image above shows 3 stages of the red rectangle moving from 0% to 100%. the red rectangle's X and Y coordinates (top left of the red rectangle) only moves a percentage of the blue rectangle's height.
the red rectangle can rotate. focusing only on the middle example ("Distance -50%") from above, where the red rectangle is repositioned at -50 of the blue rectangle's height, its new angle in the above image is now -45º. it has been rotated from its 0, 0 point.
now, my problem is that i want its rotational point to reflect its position.
the red and blue rectangles are the same size, but have opposite widths and heights. since the red rectangle's 0,0 coordinates are now -50% of the blue rectangle's height, and since they have opposite widths and heights, i want the rotational point to be 50% of the red rectangle's width (or 50% of the blue rectangle's height, which is the same thing).
rather than specifically telling the red rectangle to rotate at 50% of its width, in order to do what i want, i need to emulate doing so by using a formula that will position the red rectangle's X and Y coordinates so that its rotational point reflects its position.
Here's an illustrated solution to your problem:
I don't exactly understand what you need, but it seems that a procedure to rotate a rectangle around an arbitrary point may help.
Suppose we want to rotate a point (x,y) d radians around the origin (0,0). The formula for the location of the rotated point is:
x' = x*cos(d) - y*sin(d)
y' = x*sin(d) + y*cos(d)
Now we don't want to rotate around the origin, but around a given point (a,b). What we do is first move the origin to (a,b), then apply the rotation formula above, and then move the origin back to (0,0).
x' = (x-a)*cos(d) - (y-b)*sin(d) + a
y' = (x-a)*sin(d) + (y-b)*cos(d) + b
This is your formula for rotating a point (x,y) d radians around the point (a,b).
For your problem (a,b) would be the point halfway on the right side of the blue rectangle, and (x,y) would be every corner of the red rectangle. The formula gives (x',y') for the coordinates of the corners of rotated red rectangle.
It's quite simple really.
1. Let's settle on your point you want to rotate the rectangle about, i.e. the point of rotation (RP) which does not move when you swivel your rectangle around. Let's assume that the point is represented by the diamond in the figure below.
2. Translate the 4 points so that RP is at (0,0). Suppose the coordinates of that point is (RPx,RPy), therefore subtract all 4 corners of the rectangle by those coordinates.
3. Rotate the points with a rotation matrix (which rotates a point anticlockwise around the origin through some angle which is now the point of rotation thanks to the previous translation):
The following figure shows the rectangle rotated by 45° anticlockwise.
4. Translate the rectangle back (by adding RP to all 4 points):
I assume this is what you want :)
It seems like you could avoid a more complex rotation by more crafty positioning initially? For example, in the last example, position the red box at "-25% Blue Height" and "-25% Red Height" -- if I follow your referencing scheme -- then perform the rotation you want.
If you know the origin O and a point P on the side of rotated rectangle, you can calculate the vector between the two:
(source: equationsheet.com)
You can get the angle between the vector and the x-axis by taking the dot product with this vector:
(source: equationsheet.com)
Given this, you can transform any point on the rectangle by multiplying it by a rotation matrix:
(source: equationsheet.com)

How can a convex polygon be broken down into right triangles aligned on the X- and Y- axes?

Given a convex polygon represented by a set of vertices (we can assume they're in counter-clockwise order), how can this polygon be broken down into a set of right triangles whose legs are aligned with the X- and Y-axes?
Since I probably lack some math terminology, "legs" are what I'm calling those two lines that are not the hypotenuse (apologies in advance if I've stabbed math jargon in the face--brief corrections are extra credit).
I'm not sure about writing an algorithm to do this but it seems entirely possible to do this for any convex polygon on a piece of paper. For each vertex project a line vertically or horizontally from that vertex until it meets another of these vertical or horizontal lines. For vertices with small changes in angle, where adjacent sides are both travelling in the same direction in terms of x and y, you will need to add two lines from the vertex, one horizontal and one vetical.
Once you have done this, you should be left with a polygon in the centre of the origonal polygon but with sides that are either vertical or horizontal because the sides have been formed by the lines drawn from the vertices of the original polygon. Because these sides are either vertical or horizontal, this shape can easily be sub-divided into a number of triangles with one horizontal side, one vertical side and one hypotenuse.
I'm assuming you've already ordered the vertices as you describe above, and that they indeed define a convex polygon.
Each vertex defines a horizontal line. For V vertices, then, you will have a set of V lines. Discard any line that meets one of the following criteria:
The vertex or vertices defining that line has/have the highest or lowest Y component (if one vertex, that line intersects the polygon only at that point; if two, that line coincides with a polygon edge)
If two vertices have equal Y coordinates otherwise, keep only one of those lines (it's duplicated).
The result will resemble a "banding" of the polygon.
Each horizontal line intersects the polygon at two points. One is its defining vertex. The other is either another vertex, or a point on a segment defined by two vertices. You can determine which is the case easily enough - just simple comparison of Y coords. The coordinates of the intersection with a segment is also easy math, which I leave to you.
Each intersection defines a vertical segment. The segment is contained within the polygon (if it coincides with an edge, you can discard it), and the other end meets either another horizontal line, or the edge of the polygon if that edge is itself horizontal. Determining the case is again a matter of mere comparison of coords. Finally, there may be 0-2 additional vertical segments, defined by the vertices with the highest and/or lowest Y coords, if there is only one of either.
The resulting diagram now shows each band with a right triangle trimmed off each end if possible. Each triangle should meet your criteria. The leftover regions are rectangles; draw an arbitrary diagonal to split each into two more right triangles meeting your criteria.
You're done.
I'm not sure if this is possible. Think about a square that's already aligned with the sides on the X and Y axes. How do you draw triangles using the vertices that are also aligned to the X,Y axes?
Or are the actual sides of the polygon allowed to be along the x,y axis. Which means you could just draw a line down the diagonal of the square. If so, it might be difficult to do with a more complex polygon where some sides are aligned to the axes, while others are not.
I'm not convinced there is a general solution to the question as posed. The problem is the aligned with the X- and Y-axes bit. That means that each vertex needs to be projected to the opposite side of the polygon in both the X and Y directions, and new vertices created at those intersection points. But that process must continue on for each new vertex added that way. You might get lucky and have this process terminate (because there's already a vertex appropriately placed on the opposite side), but in the general case it's just going to go on and on.
If you throw out that restriction, then Neil N's suggestion seems good to me.
Neil N is right, I think. Unfortunate that he didn't provide any specific links.
If you have a trapezoid whose top and bottom are parallel to the X axis, you can easily render that with 4 right triangles. Call that shape a horizontal trapezoid.
If you have a triangle with one side parallel to the X axis, you can render that with 2 right triangles -- or you can consider a degenerate case of the trapezoid with the top of bottom having length zero.
Start at either the top or bottom of your convex hull (i.e. search for coordinate with min or max y) and split it into horizontal trapezoids.
It's not to hard to write the code so that it works just as well with non-convex polygons.
I think this is not possible in the general case.
Consider the polygon {(0, 1), (1, 0), (2, 0)}
.
..
This triangle can not be split into a finite number of triangles as you describe.

Resources