Use movement vector to detect impact in 2D field - algorithm

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.

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)

Sampling without replacement along a 2D grid in Cython without gil (can be in C++)

I have essentially a 2D grid of N by M (i.e. N rows, and M columns). I would like to sample from this grid without replacement in Cython without requiring the GIL. I would want something like this
for j in range(n_samples):
row_idx, col_idx = sample_without_replacement(grid)
So for example, say my 2D grid is 3 x 4, then I might get the following samples
(0, 3),
(0, 2),
(2, 1),
(3, 0)
Is there a simple way to do this in Cython?

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.

Algorithm for inverting a polygon within a rectangle?

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?

Build a directed regular graph of elements in an array

Given an array, I would like to be able to define some relationship between its elements so that each element "points to" a given number of elements, such that no element should share more than one target element with any other given element of the array.
I'm pretty sure this can be done easily with some solution from graph theory, but I embarrassingly don't know any graph theory and therefore don't know what I'm looking for. The best I can say is that the graph describing the links between elements is regular and directed.
The XY: what I actually have/want is two-dimensional grid (I don't think the dimension is relevant to the math but is very helpful with the visualization), where each cell points to around 16 (flexible on this) other cells with a minimum of duplication. The grid is a texture so it's anywhere in the 256*256 to 4096*4096 size range, which hopefully doesn't make a significant difference to the algorithm.
Once visualized as a 2D texture, there is an obvious "intuitive" solution based on image masks, but it's totally informal and relies on the implementation details (using fewer targets for the purposes of illustration):
Using a regular pattern for the pointed-to cells is inappropriate:
The next cell along will share seven targets with the origin cell (red, x). Duplication is guaranteed.
An irregular "broken circle" style arrangement intuitively seems like it should work:
If no pair of cells in the group (pointed-to and origin) have an equal difference in position to any other pair of cells in the group, then any given movement of the origin on the grid seems like it shouldn't result in more than one pointed-to cell overlapping with any of those highlighted in the original position, and none of the pointed-to (blue) cells should point back to the origin (red, x) directly (it would be nice if they didn't loop back too quickly, either).
("wrapping around" at the edges of the texture is assumed)
But this is totally informal and intuitive. I don't have any proof of this and don't know how to go about proving it. Is there an algorithm known from graph theory that can produce such a result, without wishy-washy handwaving involving image masks? Not least because the intuitive solution, even assuming it works, doesn't provide any guarantees about whether the target cells will loop back to the origin quickly or not, and whether the entire grid (or most of it, I don't mind a few unused cells) forms a single connected graph, which is absolutely essential.
Alternatively, if the "broken circle" model actually works, how would one go about formalizing this back down to an abstract algorithm operating on a sequence (I guess it's effectively just an integer sequence), rather than relying on a mask image, which is totally getting confused by implementation details? (The fact that I want to apply this to a texture should be irrelevant)
The mathematical description of what you want to do is to build a (strongly?) connected high-girth Cayley graph on the group Z/w × Z/h (where w is the width of the texture and h is the height) such that no two vertices have more than one out-neighbor in common.
Practically speaking, each vertex (i.e., pixel) points to the pixels at a fixed list of offsets. If a vertex at (0, 0) (w.l.o.g. by the vertex-transitivity of Cayley graphs) and a vertex at (x, y) have two out-neighbors in common, then there exist offsets (dx1, dy1), (dx2, dy2), (dx3, dy3), (dx4, dy4) such that (dx1, dy1) = (x + dx2, y + dy2) and (dx3, dy3) = (x + dx4, y + dy4), and (dx1, dy1) ≠ (dx3, dy3) (equivalently, (dx2, dy2) ≠ (dx4, dy4)). This condition can be verified programmatically, and for random sets of offsets within a close distance, it doesn't take long to find a suitable set. Here's some Python to generate and test them.
from random import randrange
# random pattern of offsets within the square [-k, k] x [-k, k]
def pattern(k, n):
return [(randrange(-k, k + 1), randrange(-k, k + 1)) for i in range(n)]
def valid(pat):
s = set()
for (x1, y1) in pat:
for (x2, y2) in pat:
if ((x1, y1) != (x2, y2)):
(dx, dy) = (x2 - x1, y2 - y1)
if (dx, dy) in s:
return False
s.add((dx, dy))
return True
if __name__ == '__main__':
while True:
pat = pattern(10, 16)
if valid(pat):
break
print(pat)
This code does not verify strong connectivity. I would conjecture that strong connectivity is very likely to be satisfied by random offset sets. You might want to write more code to check for short cycles, which can be found by breadth-first search.
The code above gives a list of offsets like
[(3, -4), (-8, -9), (2, 7), (-9, 3), (-4, 7), (-2, -7), (-6, 3), (-7, -2), (9, -10), (8, -2), (-6, -3), (2, -8), (-6, 6), (-9, -7), (-7, 10), (3, 10)]
(no idea if that one's any good). To figure out which vertices (x, y) points to, iterate (dx, dy) through the list above and yield the neighbor ((x + dx) & (w - 1), (y + dy) & (h - 1)), assuming that w and h are powers of two and that we're two's complement.

Resources