Check if point inside random boxes - algorithm

Edit: I've worked a solution. Feel free to contact me if you come across this in the future and need something similar.
--
Instead of generating random points on a plane, how would you check if a given coordinate is equal to a random point? Or inside a random bounding box?
For example you have a plane with integer coordinates. That plane is somehow populated with random bounding boxes (generated using a formula, not data). The goal is to check if a given (x, y) is within one of those boxes.
I can find many references on how to generate random points but not much for doing it in this more backwards way (I guess you'd call it 'functional'?).
I have managed to make an algorithm that splits the plane into 100x100 squares, and within each square is a bounding box that is randomly placed. But is it possible with an algorithm that places the boxes more organically?
Edit: Here's an example algorithm I used for a simple "random point within a 100x100 grid" (from memory, might be missing something):
// check if equal to a random point within the point's grid square
boolean isRandomCenter(x, y) {
// offset relative to origin of grid square
int offsetX = x mod 100
int offsetY = y mod 100
// any random seed will do
int randomSeed = x * y
// random position of point for this square
int randomOffsetX = random(50, randomSeed)
int randomOffsetY = random(50, randomSeed)
if (offsetX == randomOffsetX && offsetY == randomOFfsetY)
return true
return false
}

Well, I don't know if I exactly understand your problem, but the condition to know if a given point M(x, y) plotted in a 2 dimensional Euclidian space represented with two axes x and y is inside a box represented with two opposites points A(xa, ya) and B(xb, yb) is pretty simple.
Let's define a function isInsideTheBox(x, y, xa, ya, xb, yb) returning true if M is inside the box and false else :
bool isInsideTheBox(int x, int y, int xa, int ya, int xb, int yb)
{
// We assume xa < xb and ya < yb
return (x >= xa && x <= xb && y >= ya && y <= yb);
}

I am answering the question: check if a point is over a random point.
If the coordinates are real, the probability of an overlap is null and the question is virtually useless. So I assume discrete coordinates.
If the question regards random points that have already been drawn, the only way is to remember the random points in some container as you draw them (array, sorted, list, search tree, hash table).
If the question regards points that might be drawn at that location, the answer is "true" in the whole domain (where the distribution is nonzero). You need to model the domain geometrically to perform point-in-... queries.
If the question is about pseudo-random or quasi-random points, I don't think there is any shortcut and you should proceed as for the truly random case (unless the generator is really poor).

Related

Convert a bivariate draw in a univariate draw in Matlab

I have in mind the following experiment to run in Matlab and I am asking for an help to implement step (3). Any suggestion would be very appreciated.
(1) Consider the random variables X and Y both uniformly distributed on [0,1]
(2) Draw N realisation from the joint distribution of X and Y assuming that X and Y are independent (meaning that X and Y are uniformly jointly distributed on [0,1]x[0,1]). Each draw will be in [0,1]x[0,1].
(3) Transform each draw in [0,1]x[0,1] in a draw in [0,1] using the Hilbert space filling curve: under the Hilbert curve mapping, the draw in [0,1]x[0,1] should be the image of one (or more because of surjectivity) point(s) in [0,1]. I want pick one of these points. Is there any pre-built package in Matlab doing this?
I found this answer which I don't think does what I want as it explains how to obtain the Hilbert value of the draw (curve length from the start of curve to the picked point)
On wikipedia I found this code in C language (from (x,y) to d) which, again, does not fulfil my question.
EDIT This answer does not address updated version of the question, which explicitly asks about constructing Hilbert curve. Instead, this answer addresses a related question on construction of bijective mapping, and the relation to uniform distribution.
Your problem in not really well defined. If you only need the resulting distribution to be uniform, nothing is stopping you from simply picking f:(X,Y)->X. Result would be uniform regardless of whether X and Y are correlated. From your post I can only presume that what you want, in fact, is for the resulting transformation to be bijective, or as close to it as possible given machine precision limitations.
Worth noting that unless you need the algorithm that is best in preserving locality (which is clearly not required for resulting distribution to be bijective, not to mention uniform), there's no need to bother constructing Hilbert curves that you mention in your question. They have just as much to do with the solution as any other space-filling curve, and are incredibly computationally intensive.
So assuming you're looking for a bijective mapping, your question is equivalent to asking whether the set of points in a [unit] square has the same cardinality as the set of points in a [unit] line segment, and if it is, how to construct that bijection, i.e. 1-to-1 correspondence. The intuition says the square should have a higher cardinality, and Cantor spent 3 years trying to prove that, eventually proving quite the opposite - that these sets are in fact equinumerous. He was so surprised at his discovery that he wrote:
I see it, but I don't believe it!
The most commonly referred to bijection, fulfilling** this criteria, is the following. Represent x and y in their decimal form, i.e. x=0. x1 x2 x3 x4 x5..., and y=0. y1 y2 y3 y4 y5..., and let f:(X,Y)->Z be z=0. x1 y1 x2 y2 x3 y3 x4 y4 x5 y5..., i.e. alternating the decimals of the two numbers. The idea behind the bijection is trivial, though a rigorous proof requires quite a bit of prior knowledge.
** The caveat is that if we take e.g. x = 1/3 = 0.33333... and y = 1/5 = 0.199999... = 0.200000..., we can see there are two sequences corresponding to them: z = 0.313939393939... and z = 0.323030303030.... To overcome this obstacle we have to prove that adding a countable set to an uncountable one does not change the cardinality of the latter.
In reality we have to deal with machine precision and not pure math, which strictly speaking means both sets are actually finite and hence not equinumerous (assuming you store result with the same precision as original numbers). Which means we're simply forced to do some assumptions and loose some information, such as, in this case, the last half of significant digits of x and y. That is, unless we use a different data type that allows to store result with a double precision, compared to that of original variables.
Finally, sample implementation in Matlab:
x = rand();
y = rand();
chars = [num2str(x, '%.17f'); num2str(y, '%.17f')];
z = str2double(['0.' reshape(chars(:,3:end), 1, [])]);
>> cellstr(['x=' num2str(x, '%.17f'); 'y=' num2str(y, '%.17f'); 'z=' num2str(z, '%.17f')])
ans =
'x=0.65549803980353738'
'y=0.10975505072305158'
'z=0.61505947958500362'
Edit This answers the original request for a transformation f(x,y) -> t ~ U[0,1] given x,y ~ U[0,1], and additionally for x and y correlated. The updated question asks specifically for a Hilbert curve, H(x,y) -> t ~ U[0,1] and only for x,y ~ U[0,1] so this answer is no longer relevant.
Consider a random uniform sequence in [0,1] r1, r2, r3, .... You are assigning this sequence to pairs of numbers (x1,y1), (x2,y2), .... What you are asking for is a transformation on pairs (x,y) which yield a uniform random number in [0,1].
Consider the random subsequence r1, r3, ... corresponding to x1, x2, .... If you trust that your number generator is random and uncorrelated in [0,1], then the subsequence x1, x2, ... should also be random and uncorrelated in [0,1]. So the rather simple answer to the first part of your question is a projection onto either the x or y axis. That is, just pick x.
Next consider correlations between x and y. Since you haven't specified the nature of the correlation, let's assume a simple scaling of the axes,
such as x' => [0, 0.5], y' => [0, 3.0], followed by a rotation. The scaling doesn't introduce any correlation since x' and y' are still independent. You can generate it easily enough with a matrix multiply:
M1*p = [x_scale, 0; 0, y_scale] * [x; y]
for matrix M1 and point p. You can introduce a correlation by taking this stretched form and rotating it by theta:
M2*M1*p = [cos(theta), sin(theta); -sin(theta), cos(theta)]*M1*p
Putting it all together with theta = pi/4, or 45 degrees, you can see that larger values of y are correlated with larger values of x:
cos_t = sin_t = cos(pi/4); % at 45 degrees, sin(t) = cos(t) = 1/sqrt(2)
M2 = [cos_t, sin_t; -sin_t, cos_t];
M1 = [0.5, 0.0; 0.0, 3.0];
p = random(2,1000);
p_prime = M2*M1*p;
plot(p_prime(1)', p_prime(2)', '.');
axis('equal');
The resulting plot* shows a band of uniformly distributed numbers at a 45 degree angle:
Further transformations are possible with shear, and if you are clever about it, translation (OpenGL uses 4x4 transformation matrices so that translation can be represented as a linear transform matrix, with an extra dimension added before the transformation steps and removed before they are done).
Given a known affine correlation structure, you can transform back from random points (x',y') to points (x,y) where x and y are independent in [0,1] by solving Mk*...*M1 p = p_prime for p, or equivalently, by setting p = inv(Mk*...*M1) * p_prime, where p=[x;y]. Again, just pick x, which will be uniform in [0,1]. This doesn't work if the transformation matrix is singular, e.g., if you introduce a projection matrix Mj into the mix (though if the projection is the first step you can still recover).
* You may notice that the plot is from python rather than matlab. I don't have matlab or octave sitting in front of me right now, so I hope I got the syntax details right.
You could compute the hilbert curve from f(x,y)=z. Basically it's a hamiltonian path traversal. You can find a good description at Nick's spatial index hilbert curve quadtree blog. Or take a look at monotonic n-ary gray code. I've written an implementation based on Nick's blog in php:http://monstercurves.codeplex.com.
I will focus only on your last point
(3) Transform each draw in [0,1]x[0,1] in a draw in [0,1] using the Hilbert space filling curve: under the Hilbert curve mapping, the draw in [0,1]x[0,1] should be the image of one (or more because of surjectivity) point(s) in [0,1]. I want pick one of these points. Is there any pre-built package in Matlab doing this?
As far as I know, there aren't pre-built packages in Matlab doing this, but the good news is that the code on wikipedia can be called from MATLAB, and it is as simple as putting together the conversion routine with a gateway function in a xy2d.c file:
#include "mex.h"
// source: https://en.wikipedia.org/wiki/Hilbert_curve
// rotate/flip a quadrant appropriately
void rot(int n, int *x, int *y, int rx, int ry) {
if (ry == 0) {
if (rx == 1) {
*x = n-1 - *x;
*y = n-1 - *y;
}
//Swap x and y
int t = *x;
*x = *y;
*y = t;
}
}
// convert (x,y) to d
int xy2d (int n, int x, int y) {
int rx, ry, s, d=0;
for (s=n/2; s>0; s/=2) {
rx = (x & s) > 0;
ry = (y & s) > 0;
d += s * s * ((3 * rx) ^ ry);
rot(s, &x, &y, rx, ry);
}
return d;
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int n; /* input scalar */
int x; /* input scalar */
int y; /* input scalar */
int *d; /* output scalar */
/* check for proper number of arguments */
if(nrhs!=3) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Three inputs required.");
}
if(nlhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
}
/* get the value of the scalar inputs */
n = mxGetScalar(prhs[0]);
x = mxGetScalar(prhs[1]);
y = mxGetScalar(prhs[2]);
/* create the output */
plhs[0] = mxCreateDoubleScalar(xy2d(n,x,y));
/* get a pointer to the output scalar */
d = mxGetPr(plhs[0]);
}
and compile it with mex('xy2d.c').
The above implementation
[...] assumes a square divided into n by n cells, for n a power of 2, with integer coordinates, with (0,0) in the lower left corner, (n-1,n-1) in the upper right corner.
In practice, a discretization step is required before applying the mapping. As in every discretization problem, it is crucial to choose the precision wisely. The snippet below puts everything together.
close all; clear; clc;
% number of random samples
NSAMPL = 100;
% unit square divided into n-by-n cells
% has to be a power of 2
n = 2^2;
% quantum
d = 1/n;
N = 0:d:1;
% generate random samples
x = rand(1,NSAMPL);
y = rand(1,NSAMPL);
% discretization
bX = floor(x/d);
bY = floor(y/d);
% 2d to 1d mapping
dd = zeros(1,NSAMPL);
for iid = 1:length(dd)
dd(iid) = xy2d(n, bX(iid), bY(iid));
end
figure;
hold on;
axis equal;
plot(x, y, '.');
plot(repmat([0;1], 1, length(N)), repmat(N, 2, 1), '-r');
plot(repmat(N, 2, 1), repmat([0;1], 1, length(N)), '-r');
figure;
plot(1:NSAMPL, dd);
xlabel('# of sample')

What is the best way to check all pixels within certain radius?

I'm currently developing an application that will alert users of incoming rain. To do this I want to check certain area around user location for rainfall (different pixel colours for intensity on rainfall radar image). I would like the checked area to be a circle but I don't know how to do this efficiently.
Let's say I want to check radius of 50km. My current idea is to take subset of image with size 100kmx100km (user+50km west, user+50km east, user+50km north, user+50km south) and then check for each pixel in this subset if it's closer to user than 50km.
My question here is, is there a better solution that is used for this type of problems?
If the occurrence of the event you are searching for (rain or anything) is relatively rare, then there's nothing wrong with scanning a square or pixels and then, only after detecting rain in that square, checking whether that rain is within the desired 50km circle. Note that the key point here is that you don't need to check each pixel of the square for being inside the circle (that would be very inefficient), you have to search for your event (rain) first and only when you found it, check whether it falls into the 50km circle. To implement this efficiently you also have to develop some smart strategy for handling multi-pixel "stains" of rain on your image.
However, since you are scanning a raster image, you can easily implement the well-known Bresenham circle algorithm to find the starting and the ending point of the circle for each scan line. That way you can easily limit your scan to the desired 50km radius.
On the second thought, you don't even need the Bresenham algorithm for that. For each row of pixels in your square, calculate the points of intersection of that row with the 50km circle (using the usual schoolbook formula with square root), and then check all pixels that fall between these intersection points. Process all rows in the same fashion and you are done.
P.S. Unfortunately, the Wikipedia page I linked does not present Bresenham algorithm at all. It has code for Michener circle algorithm instead. Michener algorithm will also work for circle rasterization purposes, but it is less precise than Bresenham algorithm. If you care for precision, find a true Bresenham on somewhere. It is actually surprisingly diffcult to find on the net: most search hits erroneously present Michener as Bresenham.
There is, you can modify the midpoint circle algorithm to give you an array of for each y, the x coordinate where the circle starts (and ends, that's the same thing because of symmetry). This array is easy to compute, pseudocode below.
Then you can just iterate over exactly the right part, without checking anything.
Pseudo code:
data = new int[radius];
int f = 1 - radius, ddF_x = 1;
int ddF_y = -2 * radius;
int x = 0, y = radius;
while (x < y)
{
if (f >= 0)
{
y--;
ddF_y += 2; f += ddF_y;
}
x++;
ddF_x += 2; f += ddF_x;
data[radius - y] = x; data[radius - x] = y;
}
Maybe you can try something that will speed up your algorithm.
In brute force algorithm you will probably use equation:
(x-p)^2 + (y-q)^2 < r^2
(p,q) - center of the circle, user position
r - radius (50km)
If you want to find all pixels (x,y) that satisfy above condition and check them, your algorithm goes to O(n^2)
Instead of scanning all pixels in this circle I will check only only pixels that are on border of the circle.
In that case, you can use some more clever way to define circle.
x = p+r*cos(a)
y = q*r*sin(a)
a - angle measured in radians [0-2pi]
Now you can sample some angles, for example twenty of them, iterate and find all pairs (x,y) that are border for radius 50km. Now check are they on the rain zone and alert user.
For more safety I recommend you to use multiple radians (smaller than 50km), because your whole rain cloud can be inside circle, and your app will not recognize him. For example use 3 incircles (r = 5km, 15km, 30km) and do same thing. Efficiency of this algorithm only depends on number of angles and number of incircles.
Pseudocode will be:
checkRainDanger()
p,q <- position
radius[] <- array of radii
for c = 1 to length(radius)
a=0
while(a<2*pi)
x = p + radius[c]*cos(a)
y = q + radius[c]*sin(a)
if rainZone(x,y)
return true
else
a+=pi/10
end_while
end_for
return false //no danger
r2=r*r
for x in range(-r, +r):
max_y=sqrt(r2-x*x)
for y in range(-max_y, +max_y):
# x,y is in range - check for rain

Find coordinates inside a rectangular area constructed by lat/long GPS pairs

I've never deal much with location-based data, so very much new to the whole GPS coding related questions. I have a problem that I don't seem to find a very efficient way in solving it or maybe there's an algorithm that I'm not too sure.
Let said you have given 4 lat/long coordinates which construct some kind of a rectangular area: (X0, Y0), (X1, Y0), (X0, Y1), (X1, Y1)
-----------------------------------
| b |
| a |
| | d
| |
| c |
-----------------------------------
e
Is there a way to find all the point that are inside the given rectangular area : a, b, c
And all the points outside of the area? e, d
I can easily to construct a 2D matrix to do this, but that's only if the coordinates are in integer, but with lat/long pairs, the coordinates are usually in float numbers which we cannot use it to construct a 2D table.
Any cool ideas?
Edited 1:
What about this Ray-casting algorithm? Is this a good algorithm to be used for GPS coordinates which is a float number?
If your rectangle is axis-aligned, #Eyal's answer is the right one (and you actually don't need 8 values but 4 are enough).
If you deal with a rotated rectangle (will work for any quadrilateral), the ray-casting method is appropriate: consider the horizontal line Y=Yt through your test point and find the edges that cross it (one endpoint above, one endpoint below). There will be 0 or 2 such edges. In case 0, you are outside. Otherwise, compute the abscissas of the intersections of these edges with the line. If 0 or 2 intersection are on the left of the test point, you are outside.
Xi= Xt + (Yt - Y0) (X1 - X0) / (Y1 - Y0)
An alternative solution to #YvesDaoust's and #EyalSchneider's is to find the winding number or the crossing number of each point (http://geomalgorithms.com/a03-_inclusion.html). This solution scales to a polygon of any number of vertices (regardless of axis-alignment).
The Crossing Number (cn) method
- which counts the number of times a ray starting from the point P crosses the polygon boundary edges. The point is outside when this "crossing number" is even; otherwise, when it is odd, the point is inside. This method is sometimes referred to as the "even-odd" test.
The Winding Number (wn) method
- which counts the number of times the polygon winds around the point P. The point is outside only when this "winding number" wn = 0; otherwise, the point is inside.
Incidentally, #YvesDaoust's solution effectively calculates the crossing number of the point.
There is an unlimited number of points inside a rectangle, so you have to define a
step with (distane between two points).
You could just iterate with two nested loops,
lat, lon coordinates can be converted to integer using a multiplication factor of:
multiply with 1E7 (10000000) to get maximum acuracy of 1cm, or
10000000: 1cm
1000000: 10cm
100000: 1m
10000: 10m
1000: 100m
100: 1km
10: 11km
1: 111km
Now iterate
// convert to spherical integer rectangle
double toIntFact = 1E7;
int x = (int) (x0 * toIntFact);
int y = (int) (y0 * toIntFact);
int tx1 = x1 * toIntFact;
int ty1 = y1 * toIntFact;
int yStep = 100000; // about 1.11 m latitudinal span. choose desired step above in list
int xStep = (int) (yStep / cos(Math.toRadians(y0))); // longitude adaption factor depending of cos(latitude); more acurate (symetric) is to use cos of centerLatitude: (y0 + y1) / 2;
for (int px = x; px < tx1; px+= xStep) {
for (int py = y; py < ty1; py+= yStep) {
drawPoint(px, py); // or whatever
}
}
This should give an point set with same distances inbetween point for about some kilometer wide rectangles.
The code does not work when overlapping the Datum limit (-180 to 180 jump) or
when overlapping the poles. Delivers useable results up to latitude 80° N or S.
This code uses some kind of implicit equidistant (equirectangular) projection (see the division by cos(centerLat) to correct the fact that 1 degree of latitude is another distance measured in meters than one degree of longitude.
If the size of the rectangle exceeds some ten or hundred kilomters, then depending on your requirements have to use an advanced projection: e.g convert lat, lon with an WGS84 to UTM conversion. The result are coordinates in meters, which then you iterate analog.
But are you sure that this is what you want?
Nobody wants to find all atoms inside a rectangle.
May all screen pixels, or a method isInsideRectangle(lat,lon, Rectangle);
So think again for what you need that.

Algorithm to store particle position on a grid (Chaining mesh)

I have a particle distribution, i.e. a set of 3D array x,y and z that give the positions of N particles. I divide my domain into cells and I would like to program an algorithm which gives me how many particles I have in a cell.
I am looking for something that doesn't use too much memory. If the distribution of particles were mono-dimensional a smart idea is to sort the particles with decreasing x.
In this way we only need to save, for every cell, the particle with smaller x within the cell. For example I know that the 7th particle is the particle with the smaller x that belong to cell i. Therefore, in cell i, we have to find particles 0 to 7.
My question is: how can I extend this to 3D? Or, how can I build a chaining mesh?
This is not a trivial problem. You might want to look at R-trees and indeed Spatial databases in general.
I think your problem can be solved much easier.
Make a 3D-array of 'cells'. Loop through your particles and increment value of a cell current particle belongs to.
Sample code:
cells = int[X][Y][Z]
for p in particles:
cx = cast_to_int((p.x / maxX) * X)
cy = cast_to_int((p.y / maxY) * Y)
cz = cast_to_int((p.z / maxZ) * Z)
cells[cx][cy][cz]++
UPD: works only if all cells have the same correspondent sizes (i.e. x1 = x2 = xn, y1 = y2 = yn...).

Algorithm for finding nearest object on 2D grid

Say you have a 2D grid with each spot on the grid having x number of objects (with x >=0). I am having trouble thinking of a clean algorithm so that when a user specifies a coordinate, the algorithm finds the closest coordinate (including the one specified) with an object on it.
For simplicity's sake, we'll assume that if 2 coordinates are the same distance away the first one will be returned (or if your algorithm doesn't work this way then the last one, doesn't matter).
Edit: A coordinate that is 1 away must be either 1 up, down, left or right. Coordinates that are away diagonally are 2.
As a side note, what is a great, free, online reference for algorithms?
Update
With new information:
Assuming that a coordinate diagonally
is 2 away
This algorithm would work. The algorithm searches outwards in a spiral kinda way testing each point in each 'ring' started from the inside.
Note that it does not handle out of bounds situations. So you should change this to fit your needs.
int xs, ys; // Start coordinates
// Check point (xs, ys)
for (int d = 1; d<maxDistance; d++)
{
for (int i = 0; i < d + 1; i++)
{
int x1 = xs - d + i;
int y1 = ys - i;
// Check point (x1, y1)
int x2 = xs + d - i;
int y2 = ys + i;
// Check point (x2, y2)
}
for (int i = 1; i < d; i++)
{
int x1 = xs - i;
int y1 = ys + d - i;
// Check point (x1, y1)
int x2 = xs + i;
int y2 = ys - d + i;
// Check point (x2, y2)
}
}
Old version
Assuming that in your 2D grid the distance between (0, 0) and (1, 0) is the same as (0, 0) and (1, 1). This algorithm would work. The algorithm searches outwards in a spiral kinda way testing each point in each 'ring' started from the inside.
Note that it does not handle out of bounds situations. So you should change this to fit your needs.
int xs, ys; // Start coordinates
if (CheckPoint(xs, ys) == true)
{
return (xs, ys);
}
for (int d = 0; d<maxDistance; d++)
{
for (int x = xs-d; x < xs+d+1; x++)
{
// Point to check: (x, ys - d) and (x, ys + d)
if (CheckPoint(x, ys - d) == true)
{
return (x, ys - d);
}
if (CheckPoint(x, ys + d) == true)
{
return (x, ys - d);
}
}
for (int y = ys-d+1; y < ys+d; y++)
{
// Point to check = (xs - d, y) and (xs + d, y)
if (CheckPoint(x, ys - d) == true)
{
return (xs - d, y);
}
if (CheckPoint(x, ys + d) == true)
{
return (xs - d, y);
}
}
}
If you have a list of objects
If you had all the positions of all the objects in a list, this would be a lot easier as you wouldn't need to search all the empty squares and could perform 2D distance calculations to determine the one closest to you. Loop through your list of objects and calculate the distance as follows:
Define your two points. Point 1 at (x1, y1) and Point 2 at (x2, y2).
xd = x2-x1
yd = y2-y1
Distance = SquareRoot(xd*xd + yd*yd)
Then simply pick the one with the shortest distance.
If you only have a 2D array
If however the problem as described assumes a 2D array where the locations of the objects cannot be listed without first searching for all of them, then you are going to have to do a spiral loop.
Searching for 'Spiral Search Method' comes up with a few interesting links. Here is some code that does a spiral loop around an array, however this doesn't work from an arbitrary point and spiral outwards, but should give you some good ideas about how to achieve what you want.
Here is a similar question about filling values in spiral order in a 2D array.
Anyway, here is how I would tackle the problem:
Given point P, create a vector pair that specifies an area around P.
So if P = 4,4
Then your vector pair would be 3,3|5,5
Loop each value in those bounds.
for x = 3 to 5
for y = 3 to 5
check(x,y)
next
next
If a value is found, exit. If not, increase the bounds by one again. So in this case we would go to 2,2|6,6
When looping to check the values, ensure we haven't gone into any negative indexes, and also ensure we haven't exceeded the size of the array.
Also if you extend the bounds n times, you only need to loop the outer boundary values, you do not need to recheck inner values.
Which method is faster?
It all depends on:
The density of your array
Distribution technique
Number of objects
Density of Array
If you have a 500x500 array with 2 objects in it, then looping the list will always outperform doing a spiral
Distribution technique
If there are patterns of distribution (IE the objects tend to cluster around one another) then a spiral may perform faster.
Number of objects
A spiral will probably perform faster if there are a million objects, as the list technique requires you to check and calculate every distance.
You should be able to calculate the fastest solution by working out the probability of a space being filled, compared to the fact that the list solution has to check every object every time.
However, with the list technique, you may be able to do some smart sorting to improve performance. It's probably worth looking into.
If your objects are dense, then just searching the nearby points will probably be the best way to find the nearest object, spiraling out from the center. If your objects are sparse, then a quadtree or related data structure (R-tree, etc.) is probably better. Here is a writeup with examples.
I do not know of a good online algorithm reference, but I can say that if you are going to write more than the occasional line of code, saving your pennies to buy CLRS will be worth the money. There are lectures based on this book online that have been painstakingly annotated by Peteris Krumins, but they only cover part of the book. This is one of the few books that you need to own.
The following simple solution assumes that you can afford storing extra information per grid cell, and that the time cost of adding new objects to the grid is allowed to be relatively high.
The idea is that every cell holds a reference to the closest occupied cell, thus allowing O(1) query time.
Whenever an object is added to position (i,j), perform a scan of the surrounding cells, covering rings of increasing size. For each cell being scanned, evaluate its current closest occupied cell reference, and replace it if necessary. The process ends when the last ring being scanned isn't modified at all. In the worst case the process scans all grid cells, but eventually it becomes better when the grid becomes dense enough.
This solution is simple to implement, may have a significant space overhead (depending on how your grid is organized in memory), but provides optimal query time.
A simple BFS from starting coordinate in 4 directions is sufficient to find the closest point on the grid with the object.

Resources