Building a distance map from collision data on a 2d grid - c#

As the title says I have an array representing a 2d grid with walkable/nonwalkable data.
From that array, I want to create a new array with integers representing the number of steps to the nearest nonwalkable node.
What I do now is for every node in the grid to check all the neighbors in a radius of 1,2,3 and so on until we hit a nonwalkable node. But as I need to check all the nodes and multiple neighbors it is slow.
What I want to accomplish is the numbers in the image. Red representing the nonwalkable nodes.
Grid example
Is there a fast way of doing this?
If it matters I was doing this in c# but if I get an example in any other language I could probably figure it out.

There is a efficient algorithm for this. Unfortunately I fail to find a reference to what it is called. It is essentially divided into two passes. Assuming the non walkable nodes have a value of zero, and the walkable have a max-value initially:
Start at upper left corner
Process each node left to right, top to bottom
Take the minimum of the value to on top of and the value to the left
Add one to the value
If the value is smaller than the current node value, update the node with the value.
Repeat the process but starting at the bottom right, and processing nodes in reverse order, and checking the values to the right and underneath instead.
This assumes you do now allow diagonal traversal but the method could be adapted for this if that is a requirement.

Yes, run a BFS starting in all unwalkable cells.
You add all the unwalkable cells to a queue. While the queue is not empty you take the first element, compute the distance by looking at it's neighbors and adding 1 (if it's not walkable you can set it to 0). Then you add all it's unseen neighbors to the end of the queue and mark them as as seen.
This will be O(N*M) complexity both in time and in space. In this case, a grid where only neighbors are adjacent, this is O(N) since edges are capped at about 2N.

Related

How to find inner border of shape represented as point collection?

I need to get inner border of shape. Previously, I found nearest point to the center of shape in case of square or circle shape, but how can I do it in M-shape case.
What I have (I need marked points at screenshot №2):
Any algorithms, steps to find these points?
UPD: Now, I have segments direction vector like (1, 0) or (0.5, 0.5)
It looks like the first step is to simplify by averaging near-neighbour dots into a single point. Then find the smallest convex polygon that contains all points (easily done). Then selectively punch some sides in to meet the internal points (the polygon becomes concave). There are many ways to select which sides to punch in, and which points to punch in to first, and I can't be sure what's best without knowing more about your specific goals.
A simple approach would be to deal first with those points that are closest to an existing side, and punch the nearest side in to meet them. But you may want to apply other scoring conditions to choose the best points to deal with first and the best sides to punch in. For instance, you may want to give higher scores to points that are closely vertically or horizontally aligned with one of the vertices of the current polygon, so that they are dealt with earlier rather than later; and give the sides adjoining that vertex a higher score as candidates for punching in. You probably also want to award longer sides with higher scores as candidates for punching in.
I imagine that with a few simple weighting criteria such as these, you will quickly get some sensible results.
Finally, if you wish, you can refer back to your original set of unaveraged dots, and make further small adjustments to the shape to ensure that all those dots fall outside its boundaries.

How to determine whether a Line runs through a Rectangle

In my program, I've got a set of chess squares drawn on panel by a Graphics object (with each Square object having a Rectangle object that defines its bounds). I recently, added a method for drawing lines across some of the squares for emphasis. The problem is: I need to be able to "erase" these lines and it seems the only way of erasing a line it is redrawing the squares "affected" by the line.
I want to ask, assuming a line starts from PointA(x, y) and stops at PointB(x, y), how do I determine the squares on the panel to redraw? Is it best to resolve each line into a series of Points and then, check which Square.Rectangle contains any of the points? If so, how do I do that?
I would imagine you would need to iterate through each of the lines (so keep a record of them), and determine if the lines intersect with the top, right, left, or bottom boundaries of the rectangle. You don't need to do anything with the lines once they're drawn, after all, the line object contains all the information you would need to deduce whether or not the line intersects the rectangle. The one thing I would recommend doing (if you're not already), is store the objects in a collection so you can iterate through them.
Chessboard cells are joined together, so you don't need to check for all cells. Just traverse along line and get cells touched. Note that this process slightly differs from line rasterizing.
You need to calculate the first cell containing line start point and then get neighbor cells intersected by line one-by-one. For example, if line direction is right-up, then check right and top edges and so on.
If you are aware of effectiveness (large grid), consider quite effective algorithm of Amanatides and Woo

Checking for rectangle overlap in multi-dimensional array C#

So I'm making a procedural dungeon maker, right now I store the map in a multi-dimensional array. I plot n number of rooms of random positions and random sizes all of which are rectangles. As seen below:
'X' represents part of a room and '.' represent empty space. As you can see since I am randomly generating the size and position of these rooms some of these rooms overlap, this can be seen in the image.
My question is how would I go about checking if there are overlapping rectangles and therefore remove the overlapping rectangles? Not asking anyone to code this, I'm just struggling with understanding the logic.
Thanks
1) make a 2D array like that and check for X's BEFORE you put a room there ;-) If there are X's, don't put the new room there to begin with. Doesn't have to be rocket science. Remember you have control over this. Put the room-making logic in a method that can see your grid and room dimensions, have it operate in 2 modes: mode1=return TRUE if overlapping, mode 2, update the grid. call it once to see if you have a good good spot for a new room, if not, make another room!
2) brute force compares: (pseudocode) this is if you have an array of individual drawing.2d.rectangles.
bool collides(rect newrect, rect[] allrects)
for each item in allrects
if item.intersects(newrect)
return true
There, I didn't 'code' it ;-)
Before adding a new rectangle, call this routine.

Flipping tile game

I need help building an algorithm to solve a tile flipping game: Given an integer 'n', an n x n square of 1s and 0s is formed. I must flip all of the 1s to 0s. Although, you can only flip the tiles in the form of a rectangle (everything in the rectangle is toggled), where the upper-left vertice of the rectangle is the upper-left corner of the square. I must compute the minimum number of toggles that can be made to have all zeros.
If the solution is optimal, no rectangle is flipped more than once (indeed, we can never flip it instead of flipping it twice).
The order of flips doesn't matter.
Thus, we can use the following algorithm:
for i = n - 1 downto 0
for j = n - 1 downto 0
if f[i][j] == 1
flip(i, j) // This function should flip the entire rectangle
res += 1
If we process cells in this order, later cells never affect any previous one. Thus, we either flip the current cell or we don't.
If N is large, you can use prefix sums on rectangles to find whether we need to make a flip or not to obtain an O(N^2) time complexity (if it's small, you can flip the rectangle naively).
Not sure if there's an actual benefit over #kraskevich's answer, apart of progressively shorter rows to flip.
My proposal is to flip the furthest row which is not already in its final form and discard it. Then, the same with the column at the same distance from origin. At this point you have an n-1 x n-1 square to which we can apply the same solution.
I still find very unfortunate the situation with inner homogeneous rectangles (all 0's or all 1's.
For example, say you have as input an nxn square such that its inner n-1 x n-1 square is homogeneous and the furthest row and/or column is randomly "scrambled" with 0's and 1's. Then, to flip these outer tiles you don't have choice but to totally scramble the inner square.
My questions are:
do we actually have no choice? No possible preprocessing which globally helps?
Would the inner rectangle get irreversibly scrambled? No property I'm not seeing which would still allow us to get profit of the fact that area was originally uniform? Something like it gets scrambled when flipping the outer-row tiles but after "unscrambling" the furthest row in the inner rectangle the whole of it woyld trivially get unscrambled too?
EDIT:
I believe the second question has affirmative answer, as conditional bit flipping is reversible.
However, I still feel the need of some proof of optimality I still don't come up with.

algorithm for creating shapes out of arrays

I'm looking for an algorithm which could create shapes based
on arrays with coordinates. I have two 50x50 arrays: one with x and second with y coordinates.
There is always 2500 points. Then I have another 50x50 array with my values for coordinates.
I create 3 to 6 areas based on value (for example 0-100, 200-300 and 300-500). Points with certain values creates areas.
I need an algorithm which can calculate if there is only one shape in area or more and fill shapes with colors.
I need that because I must fill shapes with certain colors for each area.
Language is C#.
Example points.
Expected edges.
Expected result
Basically you could use hierarchical clustering to find the clusters.
Each point is its own cluster
Find two cluster closest together and merge them
Repeat until end condition is met
Couple of specifics: In step 2 you could use many metrics to find the closest clusters. Mean-to-mean distance or minimum distance over all point pairs are probably best choices
In Step 3, you can either stop when remaining number of clusters is 2 (or some other number). Or stop when distance is more than a threshold.
To find the actual outline, I suggest coming up with some optimization function that minimizes the length of outline while minimizing the area of the outline. And the some heuristics to optimize the function.
Something like Area - constant*Length.

Categories