fast nested for to draw circle in matrix - algorithm

Suppose I have a NxN matrix, where each cell is a 1x1 white square.
Suppose I have a position P and a radius R. I want to paint all the cells of the circle of radius R centered in P.
Of course I could do this:
for(int i = P.x - R; i < P.x + R; i++)
for(int j = P.y - R; j < P.y + R; j++)
if (distance from P to (i,j) < R)
Paint(i,j)
But as I will run this code on a shader that will execute every frame, I'd like to know a faster way to find the correct cells instead of asking the distance for each cell, which is slow.
Is there a smarter way?

You could for each given height of the circle calculate its segment width and fill it out completely.
You'd go from y = P - R to P + R filling all points in the chord (circular segment).
For the length of the chord just use formula (9) from here.

Related

Algorithm Problem: Finding all cells that has distance of K from some specific cells in a 2D grid [duplicate]

I am attempting to solve a coding challenge however my solution is not very performant, I'm looking for advice or suggestions on how I can improve my algorithm.
The puzzle is as follows:
You are given a grid of cells that represents an orchard, each cell can be either an empty spot (0) or a fruit tree (1). A farmer wishes to know how many empty spots there are within the orchard that are within k distance from all fruit trees.
Distance is counted using taxicab geometry, for example:
k = 1
[1, 0]
[0, 0]
the answer is 2 as only the bottom right spot is >k distance from all trees.
My solution goes something like this:
loop over grid and store all tree positions
BFS from the first tree position and store all empty spots until we reach a neighbour that is beyond k distance
BFS from the next tree position and store the intersection of empty spots
Repeat step 3 until we have iterated over all tree positions
Return the number of empty spots remaining after all intersections
I have found that for large grids with large values of k, my algorithm becomes very slow as I end up checking every spot in the grid multiple times. After doing some research, I found some solutions for similar problems that suggest taking the two most extreme target nodes and then only comparing distance to them:
https://www.codingninjas.com/codestudio/problem-details/count-nodes-within-k-distance_992849
https://www.geeksforgeeks.org/count-nodes-within-k-distance-from-all-nodes-in-a-set/
However this does not work for my challenge given certain inputs like below:
k = 4
[0, 0, 0, 1]
[0, 1, 0, 0]
[0, 0, 0, 0]
[1, 0, 0, 0]
[0, 0, 0, 0]
Using the extreme nodes approach, the bottom right empty spot is counted even though it is 5 distance away from the middle tree.
Could anyone point me towards a more efficient approach? I am still very new to these types of problems so I am finding it hard to see the next step I should take.
There is a simple, linear time solution to this problem because of the grid and distance structure. Given a fruit tree with coordinates (a, b), consider the 4 diagonal lines bounding the box of distance k around it. The diagonals going down and to the right have a constant value of x + y, while the diagonals going down and to the left have a constant value of x - y.
A point (x, y) is inside the box (and therefore, within distance k of (a, b)) if and only if:
a + b - k <= x + y <= a + b + k, and
a - b - k <= x - y <= a - b + k
So we can iterate over our fruit trees (a, b) to find four numbers:
first_max = max(a + b - k); first_min = min(a + b + k);
second_max = max(a - b - k); second_min = min(a - b + k);
where min and max are taken over all fruit trees. Then, iterate over empty cells (or do some math and subtract fruit tree counts, if your grid is enormous), counting how many empty spots (x,y) satisfy
first_max <= x + y <= first_min, and
second_max <= x - y <= second_min.
This Python code (written in a procedural style) illustrates this idea. Each diagonal of each bounding box cuts off exactly half of the plane, so this is equivalent to intersection of parallel half planes:
fruit_trees = [(a, b) for a in range(len(grid))
for b in range(len(grid[0]))
if grid[a][b] == 1]
northwest_half_plane = -infinity
southeast_half_plane = infinity
southwest_half_plane = -infinity
northeast_half_plane = infinity
for a, b in fruit_trees:
northwest_half_plane = max(northwest_half_plane, a - b - k)
southeast_half_plane = min(southeast_half_plane, a - b + k)
southwest_half_plane = max(southwest_half_plane, a + b - k)
northeast_half_plane = min(northeast_half_plane, a + b + k)
count = 0
for x in range(len(grid)):
for y in range(len(grid[0])):
if grid[x][y] == 0:
if (northwest_half_plane <= x - y <= southeast_half_plane
and southwest_half_plane <= x + y <= northeast_half_plane):
count += 1
print(count)
Some notes on the code: Technically the array coordinates are a quarter-turn rotated from the Cartesian coordinates of the picture, but that is immaterial here. The code is left deliberately bereft of certain 'optimizations' which may seem obvious, for two reasons: 1. The best optimization depends on the input format of fruit trees and the grid, and 2. The solution, while being simple in concept and simple to read, is not simple to get right while writing, and it's important that the code be 'obviously correct'. Things like 'exit early and return 0 if a lower bound exceeds an upper bound' can be added later if the performance is necessary.
As Answered by #kcsquared ,Providing an implementation in JAVA
public int solutionGrid(int K, int [][]A){
int m=A.length;
int n=A[0].length;
int k=K;
//to store the house coordinates
Set<String> houses=new HashSet<>();
//Find the house and store the coordinates
for(int i=0;i<m;i++) {
for (int j = 0; j < n; j++) {
if (A[i][j] == 1) {
houses.add(i + "&" + j);
}
}
}
int northwest_half_plane = Integer.MIN_VALUE;
int southeast_half_plane = Integer.MAX_VALUE;
int southwest_half_plane = Integer.MIN_VALUE;
int northeast_half_plane = Integer.MAX_VALUE;
for(String ele:houses){
String arr[]=ele.split("&");
int a=Integer.valueOf(arr[0]);
int b=Integer.valueOf(arr[1]);
northwest_half_plane = Math.max(northwest_half_plane, a - b - k);
southeast_half_plane = Math.min(southeast_half_plane, a - b + k);
southwest_half_plane = Math.max(southwest_half_plane, a + b - k);
northeast_half_plane = Math.min(northeast_half_plane, a + b + k);
}
int count = 0;
for(int x=0;x<m;x++) {
for (int y = 0; y < n; y++) {
if (A[x][y] == 0){
if ((northwest_half_plane <= x - y && x - y <= southeast_half_plane)
&& southwest_half_plane <= x + y && x + y <= northeast_half_plane){
count += 1;
}
}
}
}
return count;
}
This wouldn't be easy to implement but could be sublinear for many cases, and at most linear. Consider representing the perimeter of each tree as four corners (they mark a square rotated 45 degrees). For each tree compute it's perimeter intersection with the current intersection. The difficulty comes with managing the corners of the intersection, which could include more than one point because of the diagonal alignments. Run inside the final intersection to count how many empty spots are within it.
Since you are using taxicab distance, BFS is unneccesary. You can compute the distance between an empty spot and a tree directly.
This algorithm is based on a suggestion by https://stackoverflow.com/users/3080723/stef
// select tree near top left corner
SET flag false
LOOP r over rows
LOOP c over columns
IF tree at c, r
SET t to tree at c,r
SET flag true
BREAK
IF flag
BREAK
LOOP s over empty spots
Calculate distance between s and t
IF distance <= k
ADD s to spotlist
LOOP s over spotlist
LOOP t over trees, starting at bottom right corner
Calculate distance between s and t
IF distance > k
REMOVE s from spotlist
BREAK
RETURN spotlist

Formula, Circle's perimeter intersects with corners of rectangle

Note: Everything about the circle is unknown. Only the width and height of the rectangle are known.
I devised a formula to determine the diameter of circle, so that the circle's perimeter intersects with the bottom two corners of a rectangle, whatever the proportion of the rectangle is (or at least if the width is greater than the height). The formula is as follows, whereby W refers to the width and H refers to the height of the rectangle:
X = W / H
Diameter = ((X/4) + (1/X)) * W
Does anybody know a more eloquent way to calculate this or is there a known algorithm to do this more efficiently?
Letting the center of the circle be (0, 0), the diameter be D, the width of the rectangle be W, and the height be H, the points (±W/2, D/2 − H) should lie on the circle, which by Pythagoras holds if and only if
(W/2)2 + (D/2 − H)2 = (D/2)2.
Expanding the binomial and subtracting (D/2)2 from both sides, we get
W2/4 − D H + H2 = 0.
Solving for D by adding D H to both sides and dividing through by H, we get
D = W2/(4 H) + H.
In code this could be as follows.
double diameter(double width, double height) {
return width * width / (4 * height) + height;
}

Count nodes within k distance of marked nodes in grid

I am attempting to solve a coding challenge however my solution is not very performant, I'm looking for advice or suggestions on how I can improve my algorithm.
The puzzle is as follows:
You are given a grid of cells that represents an orchard, each cell can be either an empty spot (0) or a fruit tree (1). A farmer wishes to know how many empty spots there are within the orchard that are within k distance from all fruit trees.
Distance is counted using taxicab geometry, for example:
k = 1
[1, 0]
[0, 0]
the answer is 2 as only the bottom right spot is >k distance from all trees.
My solution goes something like this:
loop over grid and store all tree positions
BFS from the first tree position and store all empty spots until we reach a neighbour that is beyond k distance
BFS from the next tree position and store the intersection of empty spots
Repeat step 3 until we have iterated over all tree positions
Return the number of empty spots remaining after all intersections
I have found that for large grids with large values of k, my algorithm becomes very slow as I end up checking every spot in the grid multiple times. After doing some research, I found some solutions for similar problems that suggest taking the two most extreme target nodes and then only comparing distance to them:
https://www.codingninjas.com/codestudio/problem-details/count-nodes-within-k-distance_992849
https://www.geeksforgeeks.org/count-nodes-within-k-distance-from-all-nodes-in-a-set/
However this does not work for my challenge given certain inputs like below:
k = 4
[0, 0, 0, 1]
[0, 1, 0, 0]
[0, 0, 0, 0]
[1, 0, 0, 0]
[0, 0, 0, 0]
Using the extreme nodes approach, the bottom right empty spot is counted even though it is 5 distance away from the middle tree.
Could anyone point me towards a more efficient approach? I am still very new to these types of problems so I am finding it hard to see the next step I should take.
There is a simple, linear time solution to this problem because of the grid and distance structure. Given a fruit tree with coordinates (a, b), consider the 4 diagonal lines bounding the box of distance k around it. The diagonals going down and to the right have a constant value of x + y, while the diagonals going down and to the left have a constant value of x - y.
A point (x, y) is inside the box (and therefore, within distance k of (a, b)) if and only if:
a + b - k <= x + y <= a + b + k, and
a - b - k <= x - y <= a - b + k
So we can iterate over our fruit trees (a, b) to find four numbers:
first_max = max(a + b - k); first_min = min(a + b + k);
second_max = max(a - b - k); second_min = min(a - b + k);
where min and max are taken over all fruit trees. Then, iterate over empty cells (or do some math and subtract fruit tree counts, if your grid is enormous), counting how many empty spots (x,y) satisfy
first_max <= x + y <= first_min, and
second_max <= x - y <= second_min.
This Python code (written in a procedural style) illustrates this idea. Each diagonal of each bounding box cuts off exactly half of the plane, so this is equivalent to intersection of parallel half planes:
fruit_trees = [(a, b) for a in range(len(grid))
for b in range(len(grid[0]))
if grid[a][b] == 1]
northwest_half_plane = -infinity
southeast_half_plane = infinity
southwest_half_plane = -infinity
northeast_half_plane = infinity
for a, b in fruit_trees:
northwest_half_plane = max(northwest_half_plane, a - b - k)
southeast_half_plane = min(southeast_half_plane, a - b + k)
southwest_half_plane = max(southwest_half_plane, a + b - k)
northeast_half_plane = min(northeast_half_plane, a + b + k)
count = 0
for x in range(len(grid)):
for y in range(len(grid[0])):
if grid[x][y] == 0:
if (northwest_half_plane <= x - y <= southeast_half_plane
and southwest_half_plane <= x + y <= northeast_half_plane):
count += 1
print(count)
Some notes on the code: Technically the array coordinates are a quarter-turn rotated from the Cartesian coordinates of the picture, but that is immaterial here. The code is left deliberately bereft of certain 'optimizations' which may seem obvious, for two reasons: 1. The best optimization depends on the input format of fruit trees and the grid, and 2. The solution, while being simple in concept and simple to read, is not simple to get right while writing, and it's important that the code be 'obviously correct'. Things like 'exit early and return 0 if a lower bound exceeds an upper bound' can be added later if the performance is necessary.
As Answered by #kcsquared ,Providing an implementation in JAVA
public int solutionGrid(int K, int [][]A){
int m=A.length;
int n=A[0].length;
int k=K;
//to store the house coordinates
Set<String> houses=new HashSet<>();
//Find the house and store the coordinates
for(int i=0;i<m;i++) {
for (int j = 0; j < n; j++) {
if (A[i][j] == 1) {
houses.add(i + "&" + j);
}
}
}
int northwest_half_plane = Integer.MIN_VALUE;
int southeast_half_plane = Integer.MAX_VALUE;
int southwest_half_plane = Integer.MIN_VALUE;
int northeast_half_plane = Integer.MAX_VALUE;
for(String ele:houses){
String arr[]=ele.split("&");
int a=Integer.valueOf(arr[0]);
int b=Integer.valueOf(arr[1]);
northwest_half_plane = Math.max(northwest_half_plane, a - b - k);
southeast_half_plane = Math.min(southeast_half_plane, a - b + k);
southwest_half_plane = Math.max(southwest_half_plane, a + b - k);
northeast_half_plane = Math.min(northeast_half_plane, a + b + k);
}
int count = 0;
for(int x=0;x<m;x++) {
for (int y = 0; y < n; y++) {
if (A[x][y] == 0){
if ((northwest_half_plane <= x - y && x - y <= southeast_half_plane)
&& southwest_half_plane <= x + y && x + y <= northeast_half_plane){
count += 1;
}
}
}
}
return count;
}
This wouldn't be easy to implement but could be sublinear for many cases, and at most linear. Consider representing the perimeter of each tree as four corners (they mark a square rotated 45 degrees). For each tree compute it's perimeter intersection with the current intersection. The difficulty comes with managing the corners of the intersection, which could include more than one point because of the diagonal alignments. Run inside the final intersection to count how many empty spots are within it.
Since you are using taxicab distance, BFS is unneccesary. You can compute the distance between an empty spot and a tree directly.
This algorithm is based on a suggestion by https://stackoverflow.com/users/3080723/stef
// select tree near top left corner
SET flag false
LOOP r over rows
LOOP c over columns
IF tree at c, r
SET t to tree at c,r
SET flag true
BREAK
IF flag
BREAK
LOOP s over empty spots
Calculate distance between s and t
IF distance <= k
ADD s to spotlist
LOOP s over spotlist
LOOP t over trees, starting at bottom right corner
Calculate distance between s and t
IF distance > k
REMOVE s from spotlist
BREAK
RETURN spotlist

Find If a Ray Intersects a Voxel Without Marching

I'm well aware of the marching / DDA algorithms, but instead I would like to be able to do a per voxel-ray pair check, in constant time, without having to "march" through the voxel space. How would I go about this?
To be clear, I am not trying to find the first voxel a ray intersects, but rather, given a ray and a voxel, determine if that voxel's cell even lies within the ray's path.
A ray is P = O + t D, where P, O, D are vectors and t a positive real. There is an intersection with the voxel [x,y,z]x[x+1,y+1,z+1] if the system below has a solution:
x < Ox + t Dx < x + 1
y < Oy + t Dy < y + 1
z < Oz + t Dz < z + 1
0 < t
which we rewrite for brevity (with x' = (x - Ox) / Dx ...)
x' < t < x"
y' < t < y"
z' < t < z"
0 < t
If Dx < 0, the inequalities must be reversed. If Dx == 0, the inequation degenerates in x < Ox < x + 1, which can be directly decided.
Repeat the same discussion for all three axis and check if all bracketings are compatible.
For instance, for Dx, Dy, Dz > 0, you must have
max(0, x', y', z') < min(x", y", z").
There are 27 sign combinations to be considered, which are separated in three cascaded three-way comparisons.
As a micro-optimization, you can rescale the last inequality by Dx Dy Dz and simplify, to trade divisions for (faster) multiplications.
If many rays miss the voxel, you can speed-up the process a little by using the bounding sphere. Assuming that the voxel center is C, voxel radius R and the vector D is normalized, the pre-test is
(OC x D)² < R²
You can use any Ray Box (AABB) Intersection algorithm.
Arbitrary one
If you need intersection coordinates, then choose 3D line clipping algorithm

Number of right isosceles triangles in a rectangular grid

How to count efficiently the number of right isosceles triangles in a nxm rectangular grid?
The 3 corners of the triangles must have integer coordinates.
The right sides of the triangles are not necessarily parallel to grid lines.
Let A be the triangle's corner where the right angle is located. Let ab be the difference vector to the first corner and ac the difference vector to the other corner. ac should always be left of ab. So for a given ab, we can calculate ac as:
ac = (-ab.y, ab.x)
So there are only two integer degrees of freedom for a certain triangle, given A. We can calculate the possible intervals for ab as:
A.x + ab.x >= 0 --> ab.x >= -A.x
A.x + ab.x <= m --> ab.x <= m - A.x
A.y + ab.x >= 0 --> ab.x >= -A.y
A.y + ab.x <= n --> ab.x <= n - A.y
A.y + ab.y >= 0 --> ab.y >= -A.y
A.y + ab.y <= n --> ab.y <= n - A.y
A.x - ab.y >= 0 --> ab.y <= A.x
A.x - ab.y <= m --> ab.y >= A.x - m
So the possible intervals are
xmin = max(-A.x, -A.y)
xmax = min(m - A.x, n - A.y)
ymin = max(-A.y, A.x - m)
ymax = min(n - A.y, A.x)
The number of possible vectors that fulfil these conditions (except the 0-vector) are:
c = (xmax - xmin + 1) * (ymax - ymin + 1) - 1
The desired result is the sum of c for all possible A within the grid. With the naive approach you get an O(grid cells) runtime. Depending on your grid, this could already be fast enough.
Update
In order to split the sum of c (over all grid cells) we must determine where the results of the max and min operations change. E.g. ymax changes as follows:
Note that I have offset the line a bit to the right, so there is a unique mapping from points to the regions the points belong to.
When we do this for all interval boundaries, we get the following picture (for m > n):
Now we can calculate the sum of c for each region independently. I'll show that exemplarily for the left most triangle region.
For that region the following conditions hold:
xmin = -A.y
xmax = n - A.y
ymin = -A.y
ymax = A.x
c(x, y) = (n - y + x) * (x + y) - 1
= (nx + ny - y^2 + x^2 - 1)
Now we sum that for all xs and ys in that region. x runs from 0 through n/2. y runs from x to n-x.
So we get:
n/2 n-x
sumLeftRegion = Sum Sum (nx + ny - y² + x² - 1)
x=0 y=x
We can solve this (e.g. using your favorite algebra program and get:
sumLeftRegion = 1/48 * (2 + n)*(-24 - 14n + 6n^2 + 5n^3)
This can be done for all other regions. You would need some few cases (i.e. m > n, m = n, m < n, probably even and odd n and m). The case n > m can be converted to m > n by rotating the grid (which does not change the number of possible triangles). It'll be some work, but in the end you get the result in O(1) because there will be no iterations.
Consider RAIT ABC. If we maintain a corner (A) of the triangle at (0,0), then we can say that for a every positive point (B) along y=1 (so (1,1),(2,1),etc a RAIT exists whose other corner (C) is at (n,n), where Cn = Bx-1. It should be obvious that must also be true for y=2 (starting from B(2,2), y=3 (starting from B(3,3), etc. - you're just doubling, tripling, etc. the cooordinates. Does that help? (I'm no mathematician - in case that's not obvious)
Consider any triangle in the box. It has a unique bounding box (in the sense that it only has one, not that it's the only triangle with that bounding box). So, if you consider every possible bounding box side lengths, (i,j), and count the number of RAIT triangles with this bounding box, (denote this CP(i,j)) then your answer is sum(i=1 to n, sum(j=1 to m,CP(i,j)*(m-j+1))*(n-i+1)). The (m-j+1)*(n-i+1) is counting how many of that size box can fit in the n*m box. So the hard part now is to find CP(i,j). Again, CP(i,j) is the number of RAIT triangles with points on the perimeter of the box with lengths i and j. We can use symmetry to our advantage here. Assume with no loss of generality that the right angle is ABC. Imagine the triangle being aligned with the positive axes.
A
|\
| \
B__C
Now consider rotating it clockwise until it lines back up with itself. There are two possibilities through that process: BC is in quadrants 1 and 2 or in quadrants 3 and 4.
2|1
---
3|4
What we notice here is that in the first case B lies along the bottom or right of the bounding box, and in the second case B lies along the top or left of the bounding box. So wlog we assume that B lies along the bottom or right, excluding the very bottom left corner.
+-----*
| *
| *
+******
Once we calculate how many RAIT triangles have this property we can just double it!
If B is at the top right corner, then there is just one triangle to test for RAIT-ness, same if it's in the bottom right corner. If it's along the right wall, then there are i triangles to check (placing C at each point along the top, and calculating the third point to see if it forms the given bounding box). Similarly, if it's along the bottom wall, then there are j triangles to check.
This is definitely worse than O(m*n), it's probably somewhere around O(m^2*n^2), but hopefully this helps somehow.
EDIT
We can actually do a little better in our testing triangles. With a little geometric intuition, we can see that if B is along the bottom, and closer to the bottom right corner, then C is in the top right corner. Similarly if it's closer to the bottom left corner, then A is in the top right corner. So we can just consider half of B's positions, and for each position we only need to consider one possible triangle. (The argument when B is on the right is similar).

Resources