Say I have an grid of 100by100.
Now I have a location on 23,70.
How can I find all XY points on this grid within a distance of 5?
Say I have an grid of 100by100.
Now I have a location on 23,70.
How can I find all XY points on this grid within a distance of 5?
Your question is a little vague, but there might be some simple methods to do it quickly depending on your requirements and definitions.
Assuming that we're talking about a unit-square grid there are 3 primary ways to define the distance:
The first is the simplest, being simply a square from [x - 5, y - 5]
to [x + 5, y + 5]
. Quick enough to calculate on the fly.
Second option is a diamond shape which satisfies the following function:
static bool InRange(Point C, Point P) => (Math.Abs(P.X - C.X) + Math.Abs(P.Y - C.Y)) <= 5;
And finally, linear distance uses Pythagoras to find the distance between the cells and compares that to your threshold value. The final shape will depend on how you handle overlap. You could use the following test function:
static bool InRange(Point C, Point P) => ((P.X - C.X) * (P.X - C.X)) + ((P.Y - C.Y) * (P.Y - C.Y)) <= 25;
Note that in all cases the possible solution range falls in the square defined by the first solution, so you don't have to test every single cell on your grid. At most there are 24 tests (for a distance of 5) modified by the size of the grid.
Here's a general solution building on the above, using LINQ because I like it:
public static IEnumerable<Point> PointsInRange(this Point C, int range, int method)
{
// select filter function
Func<int, int, bool> filter = (x, y) => true;
if (method == 1)
filter = (x, y) => (Math.Abs(x) + Math.Abs(y)) <= range;
else if (method == 2)
filter = (x, y) => (x * x + y * y) <= (range * range);
// apply filter to all cells in potential range
var validOffsets =
from dx in Enumerable.Range(-range, range * 2 + 1)
from dy in Enumerable.Range(-range, range * 2 + 1)
where (dx != 0 || dy != 0) && filter(dx, dy)
select new { dx, dy };
// offset from center and clip to grid
var result =
from o in validOffsets
let x = C.x + o.dx
let y = C.y + o.dy
where x >= 0 && x < 100 && y >= 0 && y < 100
select new Point(x, y);
return result;
}
There are a few speed-ups you can apply, as always.
Of course if you only ever want to get the valid cells for a specific range (5 for instance) then you can reduce it further by specifying the valid offsets in an array instead of calculating them as above. You can cut the whole start of the method and replace it with a constant array with the shape you want. Or combine the two ideas and cache the answers so that you have the flexibility of arbitrary range and the speed of computing the valid offsets only once.