Algorithm for inverting a polygon within a rectangle? - algorithm

I'm trying to make a "flashlight" effect in my game where the player can only see places that are in his line of sight.
I've got most of the effect done by raycasting to each vertex in the game world and added and extra raycasts +-0.0001 rad, then connecting them in clockwise order to form this shape in red. I'm trying to get the inverse of this polygon within the bounds of the rectangular level similar to the "Inverse Selection" option in programs like Photoshop (example)

Construct a set for both rectangle and polygon and calculate the symmetric difference (vertices in either rectangle or polygon but not in both), for example:
rectangle = [(0, 0), (13, 0), (13, 10), (0, 10)]
polygon = [(0, 5), (0, 10), (2, 6), (8, 6), (11, 0), (13, 0), (13, 10)]
# "^" is the symmetric difference operator in python
set(rectangle) ^ (set(polygon))
Returns:
set([(11, 0), (2, 6), (0, 5), (0, 0), (8, 6)])
Which corresponds to the green area (vertices A, I, E, H, J) in the following picture:
Beware that it will get the complement of the red polygon which does not include the intersection with the wall in your original image:
If you want your result to be the yellow polygon of the next figure instead:
Then you will have to do a rectangle-polygon intersection for every wall/block in the stage with the complement polygon using some method like the ones described in the following question:
Method to detect intersection between a rectangle and a polygon?

Related

Iterate Over Circular Area Of Hexagonal Grid?

I am currently working with a hexagonal grid of cells which are indexed like this:
I am trying to find the simplest way to iterate over a circular area of this grid. For example, with (3, 3) as the center cell and a radius of one cell, I would want the loop to iterate over the cells (3, 3), (4, 4), (4, 3), (4, 2), (3, 2), (2, 3), (3, 4) (in any order). Given the coordinate of the center cell and a radius (excluding the center cell), how would you construct a two-dimensional loop to iterate over each cell/coordinate?
The basic idea:
Let's scan each row of the hexagon left-to-right.
How to do it:
Let R be the "cell radius".
Start at the center and move left R cells. Call this cell "A". A's row has 2*R-1 cells in it.
Now step one cell up/right. This cell begins a row with one less
cell.
Repeat step 2 until you've stepped up/right R times.
This covers the top half. Now do the lower half with similar steps (stepping down/right starting from A, to find the beginning of each of those rows).
Details
How do you step up/right?
The y coordinate increases by 1. The x coordinate increases by 1 only if y was odd.
How do you step down/right?
The y coordinate decreases by 1. The x coordinate increases by 1 only if y was odd.
The choice of grid system is what makes this one complicated. Because, for example, a step down and right might change your coordinates by (1, -1) or (0, -1) depending on which row you are in.
Therefore I would move to a different grid system, do the calculation there, then switch back to the grid system that you're showing.
Here is a demonstration of that in Python.
def loop (center, radius):
if 0 == radius:
yield center
else:
directions = [
( 1, -1),
( 0, -1),
(-1, 0),
(-1, 1),
( 0, 1),
( 1, 0),
]
cell = list(to_normalized(center))
cell[1] += radius
for direction in directions:
for i in range(radius):
cell[0] += direction[0]
cell[1] += direction[1]
yield to_grid(cell)
def to_normalized (cell):
return (cell[0] - (cell[1] // 2), cell[1])
def to_grid (cell):
return (cell[0] + (cell[1] // 2), cell[1])
for cell in loop((3, 3), 2):
print(cell)

Use movement vector to detect impact in 2D field

Given a coordinate and a movement vector. How can I get the list of all blocks will be infected?
I think it's a little bit like "object in view" or "object collision"?
For example, the original point O is (2, 2), the movement vector "→" is (0, 1) and the blocks B should be [(1, 3), (1, 4), (2, 4), (3, 3), (3, 4)]
0123 y→
0.......
1...BB..
2..O→B..
3...BB..
x.......
↓.......
If the movement vector is (-1, 1), the B should be [(0, 2), (0, 3), (0, 4), (1, 4), (2, 4)]
0123 y→
0..BBB..
1...↗B..
2..O.B..
3.......
x.......
↓.......
I'm currently considering
point P (x, y) vector V (v, u)
x' = x + v
y' = y + u
set S = ([x'-1, x'+1], [y'-1, y'+1])
calculate a line L "y=ax+b" perpendicular to V crossing (x', y').
split S into two groups by L
chose the one V is facing
but I cannot find a way to achieve last two steps.
Any suggestion will be helpful.
I think what you are looking for is something called time-until-impact or time-until-collision or something like that.
But in most game engines this is not the way to go. What a standard technique for collision handling is, is space partitioning. That means, if you have n rigid bodies in your simulation then a naive algorithm requires n^2 checks (each with another) to see if a collision happened. However, performance-wise this is a killer. Instead you should partition your space via (`uniform partitioning, Oct-Trees, Z-ordering, etc.), then you only check with neighboring rigid bodies that are neighbors with the cell in question.
Note, that the velocity vector (what you call movement) vector is not really needed here because in practice it brings no benefits.

Finding the shape corresponding to a set of points

I'm working on a small problem right now.
I'm reading in from a file a set of points, and I am asked to find the area inside of them (there is more to the problem, but I'm not worried about that right now). I am given the number of points, and the problem I have is that my area function does not work if the points are not a edge traversal.
For example: If the set of points is [(0,0) , (1, 0), (1, 1), (0, 1)], it will correctly calculate the area as 1. However, if the set of points is given as [(0,0) , (1, 1), (1, 0), (0, 1)], it will return 0 as the area.
How can I take the list of points, and have it find a traversal (either clockwise or counterclockwise, it doesn't matter)? I'm not familiar with any fast algorithms to do so.
Note: This is not a convex-hull problem. The shape does not necessarily have to be convex. For example, the set of points [(0,0), (0,2), (1, 1), (2, 2), (2, 0)] is a valid shape.

Given a set of pairs of lines, how would you find the area enclosed by all of them?

If you were given a set of pairs of lines, how would you find the amount of area which is contained by all pairs of lines (if it exists)? For example, if I had the pairs of lines:
((0, 0), (0, 10)) & ((10, 0), (10, 10))
and
((0, 0), (10, 0)) & ((0, 10), (10, 10))
how would you go about finding the area enclosed by all those lines (which in this simple case would be a square defined by points (0,0),(10,0),(10,10) & (0,10).
What algorithms might point me in the direction of solving such a problem?
EDIT: The lines won't always touch at the ends or intersect with each other. If there exists a pair of lines which doesn't intersect any of the other lines and doesn't touch at the edges, then it can be concluded that that set of pairs of lines does not have an area enclosed by all of them.
EDIT2:Take the following sets of lines:
pair 1: ((0, 0), (10, 0)) & ((0, 10), (10, 10))
pair 2: ((0, 0), (0, 10)) & ((10, 0), (10, 10))
pair 3: ((2, 0), (2, 10)) & ((8, 0),(8, 10))
The enclosed area by those three pairs of lines is the area defined by points (2,0),(2,10),(8,10) and (8,0). The convex hull algorithm however would return the values (0,0),(10,0),(10,10) and (0,10).
EDIT: it appears the convex hull is not the solution.
Just to make sure I understand your problem: is that the red area in this picture that you want?
Find all points of intersection which stay within the line segment for all pairs of lines. If no of points are less than 4 then no enclosed shape found.
If 4 points found then clip the lines with those points.Use flood fill to get the area of figure enclosed in the points.

Given two overlapping arbitrary polygons find best rotation to maximize overlap

I have two arbitrary polygons that may or may not be the same shape, I'm looking for a advice on a simple algorithm that will rotate one of the polygons to minimize the difference between the two. Thanks.
If you are trying to make them more similar, you could try to minimize the area of the difference between the two polygons. That is, the area of the union of the two, minus, the area of the intersection between them.
An approximation would be to find the two points with maximum distance in each polygon (lets call them 'diameters'), and align those for the two polygons.
For example:
Polygon A = [(13, 12); (9, 14); (1,4); (5, 2)] (a rhombus)
Diameter = [(13, 12); (1,4)] (length 14.4)
Polygon B = [(14, 11); (8, 17); (3,24); (9, 18)] (another rhombus)
Diameter = [(14, 11); (3,24)] (length 17.0)
Polygon B shifted and rotated so diameters align:
[(14.08465297, 12.72310198); (7.439737081, 7.446257009);
(-0.084652970, 3.276898021); (6.560262919, 8.553742991)]

Resources