Zig-zag fill algorithm? - algorithm

How do I make an algorithm to zig-zag fill a grid at any size as shown in the image below?
Here is my algorithm which doesn't work. (Starting bottom left to top right corner instead):
x1 = 0;
y1 = grid_h-1;
var a = 0;
put(x1,y1);
while(!((x1 = grid_w-1) and (y1 = 0))) { //If it isn't at the top right corner
if a = 2 {
x1 += 1;
put(x1,y1);
while(x1 != grid_w-1) { //While x1 isn't at the right
//Go diagonally down
x1 += 1;
y1 += 1;
put(x1,y1);
}
y1 -= 1;
put(x1,y1);
while(y1 != 0) { //While y1 isn't at the top
//Go diagonally up
x1 -= 1;
y1 -= 1;
put(x1,y1);
}
} else if a = 1 {
while(x1 != grid_w-1) { //While x1 isn't at the right
//Go diagonally down
x1 += 1;
y1 += 1;
put(x1,y1);
}
y1 -= 1;
put(x1,y1);
while(y1 != 0) { //While y1 isn't at the top
//Go diagonally up
x1 -= 1;
y1 -= 1;
put(x1,y1);
}
x1 += 1;
put(x1,y1);
} else {
y1 -= 1;
if (y1 = 0) { a = 1; } //At top?
put(x1,y1);
while(y1 != grid_h-1) { //While y1 isn't at the bottom
//Go diagonally down
x1 += 1;
y1 += 1;
put(x1,y1);
}
x1 += 1;
put(x1,y1);
while(x1 != 0) { //While x1 isn't at the left
//Go diagonally up
x1 -= 1;
y1 -= 1;
put(x1,y1);
if (y1 = 0) { a = 2; } //At top?
}
}
}
Any simpler way to do this?

The key observation here is that you go northeast when the Manhattan distance to the top left square is odd and southwest otherwise.
Of course, you must consider hitting one of the edges. For example, when you walk southwest and hit the bottom or south edge, you move east instead; when you hit the left or west edge, you move south. You can either catch the three cases (south edge, west edge, unrestrained movement) or you can move and correct your position when you have walked out of bounds.
After hitting an adge, your new position should leave you moving the other way. That is, each correction involves an odd number of steps. (Steps here is the Manhattan distance between the point you'd have gone to normally and the point you ended up in.)
If your zigzagging algorithm works correctly, you will end up visiting each cell once. That is you make h × w moves, where h and w are the height and width. You can use this as termination criterion instead of checking whether you are in the last square.
Here's example code for this solution. The additional boolean parameter down specifies whether the first step is down or left.
function zigzag(width, height, down) {
var x = 0;
var y = 0;
var n = width * height;
if (down === undefined) down = false;
while (n--) {
var even = ((x + y) % 2 == 0);
put(x, y);
if (even == down) { // walk southwest
x--;
y++;
if (y == height) {
y--; x += 2;
}
if (x < 0) x = 0;
} else { // walk northeast
x++;
y--;
if (x == width) {
x--; y += 2;
}
if (y < 0) y = 0;
}
}
return res;
}

Here's the solution abusing if-statements.
x1 = 0;
y1 = 0;
put(x1,y1);
var a = 0;
while(!((x1 = grid_w-1) and (y1 = grid_h-1))) {
switch(a) { //Down, Right-Up, Right, Left-Down
case 0: y1++; break;
case 1: x1++;y1--; break;
case 2: x1++; break;
case 3: x1--;y1++; break;
}
put(x1,y1);
if (a = 2) { //If moved right.
if (x1 = grid_w-1) or (y1 = 0) { //If at the right or top edge. Go left-down.
a = 3
} else if (y1 = grid_h-1) { //At bottom edge. Go right-up.
a = 1
}
} else if (y1 = 0) { ///At top edge.
if (x1 = grid_w-1) { //If at the right corner. Go down.
a = 0;
} else { //Go right.
a = 2;
}
} else if (a = 3) { ///If moved left-down.
if (y1 = grid_h-1) { //At bottom n edge. Go right.
a = 2
} else if (x1 = 0) { //At left edge and not bottom. Go down.
a = 0
}
} else if (a = 0) { //If moved down.
if (x1 = 0) { //If at the left corner. Go right-up.
a = 1
} else if (x1 = grid_w-1) { //If at the right corner. Go left-down.
a = 3
} else { //Go right
a = 2
}
} else if (a = 1) { //If right-up.
if (x1 = grid_w-1) { //If at the right corner.
if (a = 2) { //If moved right. Go left-down.
a = 3
} else { //Go down.
a = 0
}
}
}
}
Doesn't work well if one of the size is 1.

Basically we can use state diagram along with recursion to solve this.
permitted_directions = {
"start":["down", "side"],
"down":["north_east", "south_west"],
"north_east":["north_east", "side","down"],
"side":["north_east", "south_west"],
"south_west":["south_west","down", "side"]
}
def is_possible(x, y, pos):
if pos == "down":
if x+1 < row and y >=0 and y < col:
return (True, x+1, y)
if pos == "side":
if x >= 0 and x < row and y+1 >=0 and y+1 < col:
return (True, x, y+1)
if pos == "north_east":
if x-1 >= 0 and x-1 < row and y+1 >= 0 and y+1 < col:
return (True, x-1, y+1)
if pos == "south_west":
if x+1 >= 0 and x+1 < row and y-1 >= 0 and y-1 < col:
return (True, x+1, y-1)
return (False, 0, 0)
def fill_the_grid(grid, x, y, position, prev):
grid[x][y] = prev
prev = (x, y)
for pos in permitted_directions[position]:
possible, p, q = is_possible(x, y, pos)
if possible:
return fill_the_grid(grid, p, q, pos, prev)
return grid

Related

How to fin the shortest pass in matrix C++

Given a matrix of 0 and 1 (0 is free space, 1 is wall). Find the shortest path from one cell to another, passing only through 0 and also without touching 1.
enter image description here
How can I do this using Lee's Algorithm?
class Solution {
public:
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
// edge case: start or end not accessible
if (grid[0][0] || grid.back().back()) return -1;
// support variables
int res = 2, len = 1, maxX = grid[0].size() - 1, maxY = grid.size() - 1;
queue<pair<int, int>> q;
// edge case: single cell matrix
if (!maxX && !maxY) return 1 - (grid[0][0] << 1);
// adding the starting point
q.push({0, 0});
// marking start as visited
grid[0][0] = -1;
while (len) {
while (len--) {
// reading and popping the coordinates on the front of the queue
auto [cx, cy] = q.front();
q.pop();
for (int x = max(0, cx - 1), lmtX = min(cx + 1, maxX); x <= lmtX; x++) {
for (int y = max(0, cy - 1), lmtY = min(cy + 1, maxY); y <= lmtY; y++) {
// check if we reached the target
if (x == maxX && y == maxY) return res;
// marking it as visited and adding it to the q if it was still a valid cell
if (!grid[y][x]) {
grid[y][x] = -1;
q.push({x, y});
}
}
}
}
// preparing for the next loop
res++;
len = q.size();
}
return -1;
}
};

Generating and solving a maze with no boundaries?

Well, suppose that you try to walk across the "northern edge" of the maze, you'll come back to the same maze but at the "southern edge". Kinda like navigating through a sphere of maze.
Would it be possible to generate and solve a maze like that? I have yet to find a documentation on this subject...
The key point is reconceptualizing the maze from a grid of pixels to a graph. You can then connect the graph so it forms a toroid.
Wilson's Algorithm might be particularly easy to understand. It's also nice in that it generates a Uniform Spanning Tree, which is a spanning tree drawn uniformly from the set of all possible spanning trees of a space.
Perform the following:
Choose any vertex at random and add it to the UST.
Select any vertex that is not already in the UST and perform a loop-erasing random walk until you encounter a vertex that is in the UST. You can modify this random walk so that when it encounters an edge it will wrap around.
Add the vertices and edges touched in the random walk to the UST.
Repeat 2 and 3 until all vertices have been added to the UST.
Discussions are available here and here.
Here's a draft of what the algorithm might look like (the remaining pink cells are an artefact of something in the drawing routine, but don't affect the result).
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #000;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 200,
height = 200;
var N = 1 << 0,
S = 1 << 1,
W = 1 << 2,
E = 1 << 3;
var cellSize = 4,
cellSpacing = 4,
cellWidth = Math.floor((width - cellSpacing) / (cellSize + cellSpacing)),
cellHeight = Math.floor((height - cellSpacing) / (cellSize + cellSpacing)),
cells = new Array(cellWidth * cellHeight), // each cell’s edge bits
remaining = d3.range(cellWidth * cellHeight), // cell indexes to visit
previous = new Array(cellWidth * cellHeight), // current random walk path
i0, x0, y0; // end of current random walk
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
context.translate(
Math.round((width - cellWidth * cellSize - (cellWidth + 1) * cellSpacing) / 2),
Math.round((height - cellHeight * cellSize - (cellHeight + 1) * cellSpacing) / 2)
);
// Add the starting cell.
context.fillStyle = "white";
var start = remaining.pop();
cells[start] = 0;
fillCell(start);
// While there are remaining cells,
// add a loop-erased random walk to the maze.
context.fillStyle = "magenta";
d3.timer(function() {
for (var k = 0; k < 50; ++k) {
if (loopErasedRandomWalk()) {
return true;
}
}
});
function loopErasedRandomWalk() {
var i1;
// Pick a location that’s not yet in the maze (if any).
if (i0 == null) {
do if ((i0 = remaining.pop()) == null) return true;
while (cells[i0] >= 0);
previous[i0] = i0;
fillCell(i0);
x0 = i0 % cellWidth;
y0 = i0 / cellWidth | 0;
return;
}
// Perform a random walk starting at this location,
// by picking a legal random direction.
i1 = Math.random() * 4 | 0;
if (i1 === 0) {
if (y0 <= 0){
y0 = cellHeight-1;
i1 = i0 - cellWidth + cellWidth*cellHeight;
} else{
--y0;
i1 = i0 - cellWidth;
}
} else if (i1 === 1) {
if (y0 >= cellHeight - 1){
y0 = 0;
i1 = i0 + cellWidth - cellWidth*cellHeight;
} else {
++y0;
i1 = i0 + cellWidth;
}
} else if (i1 === 2) {
if (x0 <= 0){
x0 = cellWidth-1;
i1 = i0+cellWidth-1;
} else {
--x0;
i1 = i0 - 1;
}
} else {
if (x0 >= cellWidth - 1) {
x0 = 0;
i1 = i0-cellWidth+1;
} else {
++x0;
i1 = i0 + 1;
}
}
// If this new cell was visited previously during this walk,
// erase the loop, rewinding the path to its earlier state.
if (previous[i1] >= 0) eraseWalk(i0, i1);
// Otherwise, just add it to the walk.
else {
previous[i1] = i0;
fillCell(i1);
if (i1 === i0 - 1) fillEast(i1);
else if (i1 === i0 + 1) fillEast(i0);
else if (i1 === i0 - cellWidth) fillSouth(i1);
else fillSouth(i0);
}
// If this cell is part of the maze, we’re done walking.
if (cells[i1] >= 0) {
// Add the random walk to the maze by backtracking to the starting cell.
// Also erase this walk’s history to not interfere with subsequent walks.
context.save();
context.fillStyle = "#fff";
fillCell(i1);
while ((i0 = previous[i1]) !== i1) {
fillCell(i0);
if (i1 === i0 + 1) cells[i0] |= E, cells[i1] |= W, fillEast(i0);
else if (i1 === i0 - 1) cells[i0] |= W, cells[i1] |= E, fillEast(i1);
else if (i1 === i0 + cellWidth) cells[i0] |= S, cells[i1] |= N, fillSouth(i0);
else cells[i0] |= N, cells[i1] |= S, fillSouth(i1);
previous[i1] = NaN;
i1 = i0;
}
context.restore();
previous[i1] = NaN;
i0 = null;
} else {
i0 = i1;
}
}
function eraseWalk(i0, i2) {
var i1;
context.save();
context.globalCompositeOperation = "destination-out";
do {
i1 = previous[i0];
if (i1 === i0 - 1) fillEast(i1);
else if (i1 === i0 + 1) fillEast(i0);
else if (i1 === i0 - cellWidth) fillSouth(i1);
else fillSouth(i0);
fillCell(i0);
previous[i0] = NaN;
i0 = i1;
} while (i1 !== i2);
context.restore();
}
function fillCell(i) {
var x = i % cellWidth, y = i / cellWidth | 0;
context.fillRect(x * cellSize + (x + 1) * cellSpacing, y * cellSize + (y + 1) * cellSpacing, cellSize, cellSize);
}
function fillEast(i) {
var x = i % cellWidth, y = i / cellWidth | 0;
context.fillRect((x + 1) * (cellSize + cellSpacing), y * cellSize + (y + 1) * cellSpacing, cellSpacing, cellSize);
}
function fillSouth(i) {
var x = i % cellWidth, y = i / cellWidth | 0;
context.fillRect(x * cellSize + (x + 1) * cellSpacing, (y + 1) * (cellSize + cellSpacing), cellSize, cellSpacing);
}
d3.select(self.frameElement).style("height", height + "px");
</script>

How to convert polyline or polygon into chain-code?

I have an open or closed polyline (polygon) consisted from the set of 2D points.
I need to represent that polyline as a chain-code. If I correctly understand, I need to rasterize polyline segments using Bresenham's algorithm and construct chain-code form that raster. But is there a better algorithm?
What is the optimal algorithms for converting polyline (polygon) into chain-code?
Yes, it will be significantly faster to simply draw the points directly into the Fourier transform. Skip the raster and making a chaincode from that, after all you need the points correctly in order in the direction the polyline takes for what I assume is Kuhl-Giardiana 1982 algorithmic use. You want all the pixels in the correct order, you can directly get that by drawing the pixels into the algorithm itself rather than rasterizing anything. In fact, this would basically skip the chain code and the raster.
All lines are going to be of the form y = mx+b and the fastest way to do this is going to be Bresenham's. Though, depending on the eventual use you might opt for Wu's algorithm so that you can be sure to include anti-aliasing, which tends to make the lines look sharper (and requires you save the alpha). Assuming you need the chain code for something specific, yes you need the actual pixels that that line will produce which means using a line drawing algorithm.
Most of your drawing apis will give you the rasterized image rather than chain-code. There is the option of drawing the polyline on to an aptly sized white image in black and going through the entire image and listing every black pixel. It would be easy to code, though slow and unneeded and in mission critical operations would be a non-starter.
The code is going to be pretty easy, just do bresenham and then toss the points where it would add a point into the chaincode.
public void plotLines(int[] twodshape, Chaincode chain) {
for (int i = 0, s = twodshape.length-4; i < s; i+=2) {
plotLine(twodshape[i],twodshape[i+1],twodshape[i+2],twodshape[i+3],chain);
}
}
public void plotLine(int x0, int y0, int x1, int y1, Chaincode chain) {
int dy = y1 - y0; //BRESENHAM LINE DRAW ALGORITHM
int dx = x1 - x0;
int stepx, stepy;
if (dy < 0) {
dy = -dy;
stepy = -1;
} else {
stepy = 1;
}
if (dx < 0) {
dx = -dx;
stepx = -1;
} else {
stepx = 1;
}
if (dx > dy) {
dy <<= 1; // dy is now 2*dy
dx <<= 1;
int fraction = dy - (dx >> 1); // same as 2*dy - dx
chain.add(x0,y0);
while (x0 != x1) {
if (fraction >= 0) {
y0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x0 += stepx;
fraction += dy; // same as fraction += 2*dy
chain.add(x0,y0);
}
chain.add(x0,y0);
} else {
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
int fraction = dx - (dy >> 1);
chain.add(x0,y0);
while (y0 != y1) {
if (fraction >= 0) {
x0 += stepx;
fraction -= dy;
}
y0 += stepy;
fraction += dx;
chain.add(x0,y0);
}
chain.add(x0,y0);
}
}
Update:
I removed the recursive bit, I needed that for a specific issue with lines being drawn from point A to point B not being guaranteed to be the same from B to A. Due to the rounding of the slope. For example if you are going up 1 pixel and right 5. There are two equally valid ways of doing this, and it wasn't giving me a consistent answer.
If you deeply need it in chaincode:
public int convertToChaincode(int cx, int cy) {
if ((cx == 1) && (cy == 0)) return 0;
if ((cx == 1) && (cy == 1)) return 1;
if ((cx == 0) && (cy == 1)) return 2;
if ((cx == -1) && (cy == 1)) return 3;
if ((cx == -1) && (cy == 0)) return 4;
if ((cx == -1) && (cy == -1)) return 5;
if ((cx == 0) && (cy == -1)) return 6;
if ((cx == 1) && (cy == -1)) return 7;
return -1; //error.
}
public void plotLine(int x0, int y0, int x1, int y1, ChainCode chain) {
int dy = y1 - y0; //BRESENHAM LINE DRAW ALGORITHM
int dx = x1 - x0;
int stepx, stepy;
int cx = 0;
int cy = 0;
if (dy < 0) {
dy = -dy;
stepy = -1;
} else {
stepy = 1;
}
if (dx < 0) {
dx = -dx;
stepx = -1;
} else {
stepx = 1;
}
if (dx > dy) {
dy <<= 1; // dy is now 2*dy
dx <<= 1;
int fraction = dy - (dx >> 1); // same as 2*dy - dx
//typically set start point.
while (x0 != x1) {
if (fraction >= 0) {
y0 += stepy;
cy = stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x0 += stepx;
cx = stepx;
fraction += dy; // same as fraction += 2*dy
chain.add(convertToChaincode(cx,cy));
}
} else {
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
int fraction = dx - (dy >> 1);
//typically set start point
while (y0 != y1) {
if (fraction >= 0) {
x0 += stepx;
cx = stepx;
fraction -= dy;
}
y0 += stepy;
cy = stepy;
fraction += dx;
chain.add(convertToChaincode(cx,cy));
}
}
}

For all labeled regions in a matrix find their vertices for drawing

I am looking for an algorithm that would get me data necessary for drawing labeled regions of a matrix in a 3d application.
The input looks like this:
For each region I need to find vertices of its outer boundary in CCW order.
I already can find the vertices of all horizontal or vertical edges by looking at the neighbours, but my implementation finds vertices from left to right, from top to bottom and not in the CCW order. Here is my code.
for (int i = 1; i < columns-1; i++)
for (int j = 1; j < rows - 1; j++) {
if (grid[i][j] > 0) { // not background
if ((grid[i + 1][j] != id) && (grid[i][j - 1] != id)) {
getCellTopLeftCoord(i, j, &x, &y);
polyPath[id]->Add(gcnew mPoint(x + width, y));
}
if ((grid[i - 1][j] != id) && (grid[i][j - 1] != id)) {
getCellTopLeftCoord(i, j, &x, &y);
polyPath[id]->Add(gcnew mPoint(x, y));
}
... // etc..
here are the boundaries I am interested in:
The following procedure should work if there aren't any unconnected surfaces with repeated labels:
Traverse the matrix from top to bottom and from left to right. If you encounter a non-null cell with a label that you haven't treated yet, create the path for that label.
The point you have found is guaranteed to be a northeast corner. Put that point into your path.
Now create a list of directions and start by going south. Because you are walking along the border anticlockwise, you should always have an occupied cell to the left and an unoccupied cell to the right. (Occupied here refers to a cell with the desired label.)
When you try to find the next direction, continue in the last direction and check the cells to your right and left. if both are unoccupied, turn left. If at least the right one is occupied, turn right. Otherwise, continues straight on.
When you change direction, append the current point to your path.
Update the coordinates acording to the current direction. Repeat until you reach your original coordinates.
This method will not give you the diagonal lines around the area labelled 4 in your sketch; it will follow the axis-aligned jagged outline.
Here's an example implementation in Javascript. The cell data is contained in the two-dimensional array m. cell looks up a cell, but accounts for out-of bounds look-ups. path creates the path for a single label. paths creates a list of paths; it calls path:
function cell(x, y) {
if (y < 0) return 0;
if (y >= m.length) return 0;
if (x < 0) return 0;
if (x >= m[y].length) return 0;
return m[y][x];
}
function path(x, y, c) {
var x0 = x;
var y0 = y;
var res = [{x: x, y: y}];
var dir = "s";
var l, r;
y++;
while (x != x0 || y != y0) {
var old = dir;
switch (dir) {
case "n": l = (cell(x - 1, y - 1) == c) ? 1 : 0;
r = (cell(x, y - 1) == c) ? 2 : 0;
dir = ["w", "n", "e", "e"][l + r];
break;
case "e": l = (cell(x, y - 1) == c) ? 1 : 0;
r = (cell(x, y) == c) ? 2 : 0;
dir = ["n", "e", "s", "s"][l + r];
break;
case "s": l = (cell(x, y) == c) ? 1 : 0;
r = (cell(x - 1, y) == c) ? 2 : 0;
dir = ["e", "s", "w", "w"][l + r];
break;
case "w": l = (cell(x - 1, y) == c) ? 1 : 0;
r = (cell(x - 1, y - 1) == c) ? 2 : 0;
dir = ["s", "w", "n", "n"][l + r];
break;
}
if (dir != old) res.push({x: x, y: y});
switch (dir) {
case "n": y--; break;
case "e": x++; break;
case "s": y++; break;
case "w": x--; break;
}
}
return res;
}
function paths() {
var res = {};
for (var y = 0; y < m.length; y++) {
for (var x = 0; x < m[y].length; x++) {
var c = m[y][x];
if (c && !(c in res)) {
res[c] = path(x, y, c);
}
}
}
return res;
}

algorithm to find a certain lat long position in a polygon enclosed by lat/long postions or not

I have a set of polygons drawn on google map,now I want to implement the algo that given a postion with certain lat/long in which of the polygon it lies.
Note:polygons are also drawn given the lat/long positions using the google maps api
So Is there any api for it or how can i convert lat/long positions to x-y planes so that i can check if a given point lies in which area using area formulas?
would google.maps.geometry.poly.containsLocation work ?
use below ray casting alogrithm that may help u to resolve the problem
google.maps.Polygon.prototype.Contains = function(point) {
// ray casting alogrithm
var crossings = 0,
path = this.getPath();
// for each edge
for (var i = 0; i < path.getLength(); i++) {
var a = path.getAt(i),
j = i + 1;
if (j >= path.getLength()) {
j = 0;
}
var b = path.getAt(j);
if (rayCrossesSegment(point, a, b)) {
crossings++;
}
}
// odd number of crossings?
return (crossings % 2 == 1);
function rayCrossesSegment(point, a, b) {
var px = point.lng(),
py = point.lat(),
ax = a.lng(),
ay = a.lat(),
bx = b.lng(),
by = b.lat();
if (ay > by) {
ax = b.lng();
ay = b.lat();
bx = a.lng();
by = a.lat();
}
// alter longitude to cater for 180 degree crossings
if (px < 0) { px += 360 };
if (ax < 0) { ax += 360 };
if (bx < 0) { bx += 360 };
if (py == ay || py == by) py += 0.00000001;
if ((py > by || py < ay) || (px > Math.max(ax, bx))) return false;
if (px < Math.min(ax, bx)) return true;
var red = (ax != bx) ? ((by - ay) / (bx - ax)) : Infinity;
var blue = (ax != px) ? ((py - ay) / (px - ax)) : Infinity;
return (blue >= red);
}
};

Resources