Hello I'm having a little trouble on this one aspect in my code that I'm working on. It deals with points and returns true or not if it's diagonal to other points in my arrayList of Points. Here my code so far:
private List<Point> point;
public void check()
{
for (int i = 0; i < point.Count; i++)
{
validSpot(i);
}
}
One note, your graph has your y upside down from the way an array stores it.
You could treat your indexes as points on a graph. To find what falls on the diagonal use slope intercept form. y = m x + b. Since you only want diagonals, valid slopes are limited to 1 and -1. Then you just have to define the line that passes through the point of interest and test if the point in question satisfies one of the equations for m = -1 or m = 1. Since the slope is known you only need one point to define the line.
public bool func(int[] knownPt,int xTest, int yTest)
{
//knownPt is int[]{x,y}
// y = m*x + (yi - xi)
return yTest== xTest + knownPt[1] - KnownPt[0] || yTest == -xTest +knownPt[1] + KnownPt[0];
}
As a walk through here is m = -1
yi = -xi + b
yi + xi = b
since b = yi + xi
y = -x + (yi + xi)
Related
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:
Number of steps in the 8 directions: n, ne, e, se, s, sw, w, nw
Number of steps in the 4 directions: n, e, s, w
Linear distance between the cells (Pythagoras)
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.
Good day everyone, I'm writing my own pathfinding script, first had it on paper then started coding and let me tell you, it's much harder in practice than in theory. So, I've ran into a problem, which I of course can't solve.
The problem presents itself in the following images:1) In this shot, the waypoint is set to (6,6) and returns no errors.
2) Note the 2 points in the upper right corner, one shows no direction the other shows up. Error is the node that points upwards. In this shot, the waypoint is moved to (7,5) at which point it starts throwing errors starting from the last index. The more I move the waypoint closer to the bottom-right corner, the more points at X=13 down the Y axis throws exceptions.
Relevant code:
for (int x = 0; x < map.sizeX; x++)
{
for (int y = 0; y < map.sizeY; y++)
{
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable )
{
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
foreach (Vector3 direction in map.GetDirections())
{
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2 )
{
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
grid[x, y].direction = direction;
dot = dot2;
}
}
}
}
}
}
This Index out of Bounds error is only thrown when I add the check to see if the point towards the direction is passable or not. Another thing to note is that I use direction.y where the directions are actually stored in x and z. For some reason if I use the z instead of y, it stops working completely.
When in doubt, try walking through a test case to see what goes wrong.
Let's say we're in the second image, x = 13, y = 12
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable )
(13, 12) is not our target point, and is passable, so we pass this test and proceed to the next line...
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
heading ends up being something like (0.659, 0, 0.753) here, though if you have some y offsets it might be shorter since you normalize it before zeroing the y.
foreach (Vector3 direction in map.GetDirections())
I don't know what order your directions are stored in, so I'll just guess here:
{(0, 0, 1), (1, 0, 1), (1, 0, 0), (1, 0, -1)...}
Starting with (0, 0, 1) then...
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2 )
dot is still 1, and dot2 is 0.753 so we pass this test, check that the cell above is passable (even though that points wildly away from the direction we want to go! More on that soon), set dot = dot2 and try the next direction:
(1, 0, 1) normalizes to (0.707, 0, 0.707). dot is 0.753 and dot2 is 0.466 + 0.532 = 0.998 so we fail the dot > dot2 test and skip this one.
Here's the killer: (1, 0, 0)
dot is still 0.753 and dot2 is 0.659, so we pass the dot > dot2 test, and proceed to check the cell in that direction:
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
No kidding an error is thrown! We were already at x = 13 (ie. map.sizeX - 1) and we added 1, so we're off the edge of the board!
So, this error is easy to detect just by walking through the problem case.
Possible fixes (from most to least hacky):
Do bounds checking whenever you try to access an adjacent cell, and skip it if it would lead off the map.
Add a border of unused grid cells around your map, so checking one cell off the edge never poses a problem.
Consider switching to a more conventional, well-studied pathfinding algorithm, like Breadth-first search (all moves cost the same) or Djikstra's algorithm (distinct move costs) if you want to populate the entire grid with pathing information, or A* if you want the shortest point-to-point path.
Make a simple function that checks if you are within the bounds of the map.grid 2D array before doing if (map.grid[x + (int)direction.x, y + (int)direction.y].passable).
Check if map.grid[x + (int)direction.x is less than map.sizeX-1
then check if map.grid[ y + (int)direction.y] is less than map.sizeY-1.
If both conditions are met, go ahead with the if (map.grid[x + (int)direction.x, y + (int)direction.y].passable).
Here is a simple function to simplify that:
bool isWithinBound(Vector3 direction, int sizeX, int sizeY, int x, int y)
{
return ((x + (int)direction.x < sizeX - 1) && (y + (int)direction.y < sizeY - 1));
}
Now you can just do:
for (int x = 0; x < map.sizeX; x++)
{
for (int y = 0; y < map.sizeY; y++)
{
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable)
{
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
foreach (Vector3 direction in map.GetDirections())
{
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2)
{
//Check if we are within bounds
if (isWithinBound(direction, map.sizeX, map.sizeY, x, y))
{
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
grid[x, y].direction = direction;
dot = dot2;
}
}
}
}
}
}
}
I have two lists filled with (x, y) data points; one of the lists being the main list and the other being a list I want to compare against.
So for example, in the main list I try to find "gaps" in the data; say I'm looking at two x data points x1 = 21 and x2 = 24. The difference between those two points is greater than deltaX = 1. So what I'd like to do, is look through the second list, and find all data points between x1 = 21 and x2 = 24 to "fill in the gap".
I have something like this:
double diffX = Math.Abs(datapoints1[i + 1].X - datapoints1[i].X);
if (diffX > deltaX)
{
datapoints1.AddRange(LookBetween(datapoints1[i + 1].X, datapoints1[i].X);
}
.
.
.
private IEnumerable<PointXY> LookBetween(double upperLimit, double lowerLimit)
{
return datapoints2.Where(x => x.X < upperLimit && x.X > lowerLimit);
}
LookBetween seems to return a boolean because nothing gets added to the main list. How can I get it to return a list of the x, y values that match the criteria based on the gap of x?
It seems like you're trying to do a pairwise iteration through neighbors in datapoints1.
Using the function linked above, you might have something like:
var pairs = datapoints1.Pairwise((d1, d2) => new
{
x1 = d1.X,
x2 = d2.X,
diffX = Math.Abs(d1.X - d2.X),
});
var gaps = from pair in pairs
where pair.diffX > deltaX
from dp2 in datapoints2
where pair.x1 < dp2.X && dp2.X < pair.x2
select dp2;
Or using your LookBetween function...
var gaps = from pair in pairs
where pair.diffX > deltaX
from dp2 in LookBetween(pair.x2, pair.x1)
select dp2;
I'm trying to write an implementation of the parking lot test for random number generators. Here are the sources that I'm getting my information about the test from: Intel math library documentation and Page 4 of this paper along with the phi function for probability density listed here.
I wrote an implementation of the test in C#. It uses a 100x100 grid whose values are initially set to null. I then use the random number generator to generate random integers for x and y. If that index of the grid and it's neighbors are empty, that index gets set to 1. Otherwise, nothing happens because there was a "crash".
I ran it using C# System.Random generator. I don't believe the results are correct because I always get very near 3079 points parked, which is about 500 short of the average I'm supposed to get. It's also yields a p-value of 2.21829146215425E-90.
My code is below. Does anyone have any experience with this or can anyone see something that I might be doing incorrectly in my implementation? Any help would be greatly appreciated.
private void RunParkingLotTest()
{
points = new int?[100,100];
int parked = 0;
for (int i = 0; i < 12000; i++)
{
int x = random.Next(100);
int y = random.Next(100);
if (IsSafeToPark(x, y))
{
points[x, y] = 1;
parked++;
}
}
Console.WriteLine("Parked: " + parked + "\nP value: " + PhiFunction((parked-3523)/21.9));
}
private bool IsSafeToPark(int x, int y)
{
return PointIsEmpty(x, y)
&& LeftOfPointIsEmpty(x, y)
&& RightOfPointIsEmpty(x, y)
&& BelowPointIsEmpty(x, y)
&& AbovePointIsEmpty(x, y);
}
private bool AbovePointIsEmpty(int x, int y)
{
if (y == 99)
{
return true;
}
else
return points[x, y + 1] == null;
}
private bool BelowPointIsEmpty(int x, int y)
{
if (y == 0)
{
return true;
}
else
return points[x, y - 1] == null;
}
private bool RightOfPointIsEmpty(int x, int y)
{
if (x == 99)
{
return true;
}
else
return points[x + 1, y] == null;
}
private bool LeftOfPointIsEmpty(int x, int y)
{
if (x == 0)
{
return true;
}
else
return points[x - 1, y] == null;
}
private bool PointIsEmpty(int x, int y)
{
return points[x, y] == null;
}
private double PhiFunction(double x)
{
//ϕ(x) = (2π)−½e−x2/2
return ((1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(-(Math.Pow(x, 2)) / 2));
}
edit - The problems with my original implementation were
I was plotting squares instead of disks
I only plotted points at integer values. I should have used decimal values instead.
As a result of the above two, I needed to change my distance check
Thanks to Chris Sinclair and mine z for help in figuring this out. The final code is posted below.
I'm going to take a stab at this, and admittedly, I have not attempted any such test, so forgive me if I'm way off. In general though, the .NET Random implementation is pretty good and I've never had issues with it, so I wouldn't suspect that initially especially since you're properly reusing the same instance instead of creating new ones.
Reading from the parking.pdf, and from the Intel documentation, it seems that they're using discs, and compute the distance from their centre points. Your implementation is using squares (array of 1 distance between spots) and thus ignoring diagonals.
From the pdf:
If disks were being used, the distance between the particles r =
p(x(i) − z)2 + (y(i) − z)2 would need to be less than or equal to one.
Does it matter whether one uses disks or squares? An indication of the
importance of which geometric figure is parked can be obtained by
comparing the area occupied by a square of side 1.0 to the area of a
disk of diameter 1.0. The ratio of the areas, disk to square, is π/4.
Therefore, it would be anticipated that more disks could be placed in
a box than squares in the same number of tries.
And the Intel doc:
The test assumes a next random point (x, y) successfully ”parked”, if
it is far enough from every previous successfully ”parked” point. The
sufficient distance between the points (x1, y1) and (x2, y2) is
min(|x1 - x2|,|y1 - y2|) > 1.
I'm guessing that the π/4 disk to square ratio and the differences between how many discs can fit vs squares might be why you're seeing a different number. (although right now I fail to see a directly relationship between 3523 and 3070 and π/4. 3523 * π/4 = 2767, which is close, but I'm sure if there's a relationship it's slightly more complex than just simple multiplication.)
Not a great answer, but my best guess.
EDIT: Interestingly enough, I did a quick implementation using discs with 1 unit diameter and getting results around 4000 parked. So maybe there's a bit more to this than my untrained self can grasp (or maybe .NET's Random doesn't pass the test?) Anyway, here's my disc implementation:
List<Point> parkedCars = new List<Point>();
Random random = new Random();
void Main()
{
int parked = 0;
for (int i = 0; i < 12000; i++)
{
double x = random.NextDouble() * 100;
double y = random.NextDouble() * 100;
Point pointToPark = new Point(x, y);
if (IsSafeToPark(pointToPark))
{
parkedCars.Add(pointToPark);
parked++;
}
}
Console.WriteLine("Parked: " + parked);
}
private bool IsSafeToPark(Point pointToPark)
{
//make sure it's "inside" the box
if (pointToPark.X < 0.5 || pointToPark.X > 99.5
|| pointToPark.Y < 0.5 || pointToPark.Y > 99.5)
return false;
if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
return false;
return true;
}
private double Distance(Point p1, Point p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}
Using my likely too simple application of the π/4 ratio yields about 3142. A bit closer, but it seems very incorrect.
EDIT: As #mike z pointed out, my test using directly distance is incorrect. According to the parameters of the test, which I forgot about, just checks that the X and Y distance are greater than 1. Changing my Distance check to:
Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y))
Yields a much closer result around 3450, which is pretty close. If I take out my "//make sure it's "inside" the box" check, averaged over 10 tries gets 3531!
So my final, "working" code is:
public struct Point
{
public double X,Y;
public Point(double x, double y)
{
this.X = x;
this.Y = y;
}
}
List<Point> parkedCars = new List<Point>();
Random random = new Random();
void Main()
{
int parked = 0;
for (int i = 0; i < 12000; i++)
{
double x = random.NextDouble() * 100;
double y = random.NextDouble() * 100;
Point pointToPark = new Point(x, y);
if (IsSafeToPark(pointToPark))
{
parkedCars.Add(pointToPark);
parked++;
}
}
Console.WriteLine("Parked: " + parked);
}
private bool IsSafeToPark(Point pointToPark)
{
if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
return false;
return true;
}
private double Distance(Point p1, Point p2)
{
return Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
}
EDIT: I ran the test 100 times twice, and averaged the results to 3521.29 and 3526.74 respectively. Not sure if this means there still something slightly more to this, but perhaps this is just indicative of rounding or floating point precision differences between .NET and Fortran.
I found this code on the website http://rosettacode.org/wiki/Closest-pair_problem and I adopted the C# version of the divide and conquer method of finding the closest pair of points but what I am trying to do is adapt it for use to only find the closest point to one specific point. I have googled quite a bit and searched this website to find examples but none quite like this. I am not entirely sure what to change so that it only checks the list against one point rather than checking the list to find the two closest. I'd like to make my program operate as fast as possible because it could be searching a list of several thousand Points to find the closest to my current coordinate Point.
public class Segment
{
public Segment(PointF p1, PointF p2)
{
P1 = p1;
P2 = p2;
}
public readonly PointF P1;
public readonly PointF P2;
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
}
public float LengthSquared()
{
return (P1.X - P2.X) * (P1.X - P2.X)
+ (P1.Y - P2.Y) * (P1.Y - P2.Y);
}
}
public static Segment Closest_BruteForce(List<PointF> points)
{
int n = points.Count;
var result = Enumerable.Range(0, n - 1)
.SelectMany(i => Enumerable.Range(i + 1, n - (i + 1))
.Select(j => new Segment(points[i], points[j])))
.OrderBy(seg => seg.LengthSquared())
.First();
return result;
}
public static Segment MyClosestDivide(List<PointF> points)
{
return MyClosestRec(points.OrderBy(p => p.X).ToList());
}
private static Segment MyClosestRec(List<PointF> pointsByX)
{
int count = pointsByX.Count;
if (count <= 4)
return Closest_BruteForce(pointsByX);
// left and right lists sorted by X, as order retained from full list
var leftByX = pointsByX.Take(count / 2).ToList();
var leftResult = MyClosestRec(leftByX);
var rightByX = pointsByX.Skip(count / 2).ToList();
var rightResult = MyClosestRec(rightByX);
var result = rightResult.Length() < leftResult.Length() ? rightResult : leftResult;
// There may be a shorter distance that crosses the divider
// Thus, extract all the points within result.Length either side
var midX = leftByX.Last().X;
var bandWidth = result.Length();
var inBandByX = pointsByX.Where(p => Math.Abs(midX - p.X) <= bandWidth);
// Sort by Y, so we can efficiently check for closer pairs
var inBandByY = inBandByX.OrderBy(p => p.Y).ToArray();
int iLast = inBandByY.Length - 1;
for (int i = 0; i < iLast; i++)
{
var pLower = inBandByY[i];
for (int j = i + 1; j <= iLast; j++)
{
var pUpper = inBandByY[j];
// Comparing each point to successivly increasing Y values
// Thus, can terminate as soon as deltaY is greater than best result
if ((pUpper.Y - pLower.Y) >= result.Length())
break;
Segment segment = new Segment(pLower, pUpper);
if (segment.Length() < result.Length())
result = segment;// new Segment(pLower, pUpper);
}
}
return result;
}
I used this code in my program to see the actual difference in speed and divide and conquer easily wins.
var randomizer = new Random(10);
var points = Enumerable.Range(0, 10000).Select(i => new PointF((float)randomizer.NextDouble(), (float)randomizer.NextDouble())).ToList();
Stopwatch sw = Stopwatch.StartNew();
var r1 = Closest_BruteForce(points);
sw.Stop();
//Debugger.Log(1, "", string.Format("Time used (Brute force) (float): {0} ms", sw.Elapsed.TotalMilliseconds));
richTextBox.AppendText(string.Format("Time used (Brute force) (float): {0} ms", sw.Elapsed.TotalMilliseconds));
Stopwatch sw2 = Stopwatch.StartNew();
var result2 = MyClosestDivide(points);
sw2.Stop();
//Debugger.Log(1, "", string.Format("Time used (Divide & Conquer): {0} ms", sw2.Elapsed.TotalMilliseconds));
richTextBox.AppendText(string.Format("Time used (Divide & Conquer): {0} ms", sw2.Elapsed.TotalMilliseconds));
//Assert.Equal(r1.Length(), result2.Length());
You can store the points in a better data structure that takes advantage of their position. Something like a quadtree.
The divide and conquer algorithm that you are trying to use doesn't really apply to this problem.
Don't use this algorithm at all, just go through the list one at a time comparing the distance to your reference point and at the end return the point that was the closest. This will be O(n).
You can probably add some extra speed ups but this should be good enough.
I can write some example code if you want.
You're mixing up two different problems. The only reason divide and conquer for the closest pair problem is faster than brute force is that it avoids comparing every point to every other point, so that it gets O(n log n) instead of O(n * n). But finding the closest point to just one point is just O(n). How can you find the closest point in a list of n points, while examining less than n points? What you're trying to do doesn't even make sense.
I can't say why your divide and conquer runs in less time than your brute force; maybe the linq implementation runs slower. But I think you'll find two things: 1) Even if, in absolute terms, your implementation of divide and conquer for 1 point runs in less time than your implementation of brute force for 1 point, they still have the same O(n). 2) If you just try a simple foreach loop and record the lowest distance squared, you'll get even better absolute time than your divide and conquer - and, it will still be O(n).
public static float LengthSquared(PointF P1, PointF P2)
{
return (P1.X - P2.X) * (P1.X - P2.X)
+ (P1.Y - P2.Y) * (P1.Y - P2.Y);
}
If, as your question states, you want to compare 1 (known) point to a list of points to find the closest then use this code.
public static Segment Closest_BruteForce(PointF P1, List<PointF> points)
{
PointF closest = null;
float minDist = float.MaxValue;
foreach(PointF P2 in points)
{
if(P1 != P2)
{
float temp = LengthSquared(P1, P2);
if(temp < minDist)
{
minDist = temp;
closest = P2;
}
}
}
return new Segment(P1, closest);
}
However, if as your example shows, you want to find the closest 2 points from a list of points try the below.
public static Segment Closest_BruteForce(List<PointF> points)
{
PointF closest1;
PointF closest2;
float minDist = float.MaxValue;
for(int x=0; x<points.Count; x++)
{
PointF P1 = points[x];
for(int y = x + 1; y<points.Count; y++)
{
PointF P2 = points[y];
float temp = LengthSquared(P1, P2);
if(temp < minDist)
{
minDist = temp;
closest1 = P1;
closest2 = P2;
}
}
}
return new Segment(closest1, closest2);
}
note the code above was written in the browser and may have some syntax errors.
EDIT Odd... is this an acceptable answer or not? Down-votes without explanation, oh well.