I am working on a website in which I have the User's Location Lat and Long saved in my Location table. Now I want to use a filter SearchByDistance which have values: 5km, 10km, 15km through which the user can get the results according to the specified Range.
Now what I actually wants to do is to get the input from the user say 5km and get the results from my table which falls with in the range of user's saved LatLong in the Location table and 5km to that LatLong. I google on this and found some links like:
How do I find the lat/long that is x km north of a given lat/long
http://msdn.microsoft.com/en-us/library/system.device.location.geocoordinate.getdistanceto%28v=vs.110%29.aspx
But I am unable to get my requirement from the above. Please help. Thanks
I think your approach can be, first create a circle (your center will be user lat and long) with the given radius say 5KM or 10Km and then find the rows from the Polygon Rings. I wrote it for esri maps. Hope it will solve your problem
Polygon areaOfInterset;
void CreateCircle(double radius)
{
var point = new MapPoint(Your Lat and Long);// This will be user lat and long on which you want to draw a circle
var graphic = new Graphic();
var circle = new ESRI.ArcGIS.Client.Geometry.PointCollection();
int i = 0;
while (i <= 360)
{
double degree = (i * (Math.PI / 180));
double x = point.X + Math.Cos(degree) * radius;
double y = point.Y + Math.Sin(degree) * radius;
circle.Add(new MapPoint(x, y));
i++;
}
var rings = new ObservableCollection<ESRI.ArcGIS.Client.Geometry.PointCollection> { circle };
areaOfInterset = new Polygon { Rings = rings};
}
Now next task is to find the rows. For that you can use below code inside the loop.
foreach(MapPoint selectedRow in DatabaseRowsToBeSearched)
{
var isExist = IsInsideCircle(selectedRow)
}
bool IsInsideCircle(MapPoint location)
{
var isInside = false;
foreach (var shape in areaOfInterset.Rings)
{
for (int i = 0, j = shape.Count - 1; i < shape.Count; j = i++)
{
if ((((shape[i].Y <= location.Y) && (location.Y < shape[j].Y)) ||
((shape[j].Y <= location.Y) && (location.Y < shape[i].Y))) &&
(location.X < (shape[j].X - shape[i].X) * (location.Y - shape[i].Y) / (shape[j].Y - shape[i].Y) + shape[i].X))
{
isInside = !isInside;
}
}
}
return isInside;
}
Related
I have a 2D grid of cells, like so:
I want to find the "centroids," or the places in each room that can see the most other cells. For example, "centroid" 1 can see 500 other cells, "centroid" 2 can see 400 other cells (NOT included in the first 500), and so on (if there's a better name for this let me know).
I'm currently doing this with the code below.
public void SetCentroids(CellWalkableState[,] grid)
{
centroids = new List<((int, int), int)>();
List<(int, int)> cellsCopy = new List<(int, int)>();
for (int i = 0; i < cells.Count; i++)
{
cellsCopy.Add(cells[i]);
}
Debug.Log(DateTime.Now.ToString("o") + " - Setting centroids for room with " + cells.Count + " cells");
var perCellInView = cellsCopy.AsParallel().Select(x => (x, StaticClass.FindInView(x, grid))).ToList();
var force_start = perCellInView.First();
Debug.Log(DateTime.Now.ToString("o") + " - got in view");
var perCellInViewOrdered = perCellInView.AsParallel().OrderByDescending(xxx => xxx.Item2.Count);
var force_start_1 = perCellInViewOrdered.First();
Debug.Log(DateTime.Now.ToString("o") + " - sorted");
List<(int, int)> roomCellsAdded = new List<(int, int)>();
while(roomCellsAdded.Count < (cells.Count*0.9))
{
if(cellsCopy.Count == 0)
{
Debug.LogError("something is wrong here.");
}
var centroid = perCellInViewOrdered.First().x;
var centroidCells = perCellInViewOrdered.First().Item2;
if(centroidCells.Count == 0)
{
Debug.Log("this shouldnt be happening");
break;
}
roomCellsAdded.AddRange(centroidCells);
centroids.Add((centroid, centroidCells.Count));
Debug.Log(DateTime.Now.ToString("o") + " - added centroids, " + roomCellsAdded.Count + " cells in view");
var loopPerCellInView = perCellInView.AsParallel().Where(x => centroids.Select(y => y.Item1).Contains(x.x) == false).Select(x => (x.x, x.Item2.Except(roomCellsAdded).ToList())).ToList();
Debug.Log(DateTime.Now.ToString("o") + " - excluded");
perCellInViewOrdered = loopPerCellInView.AsParallel().OrderByDescending(xxx => xxx.Item2.Count);
Debug.Log(DateTime.Now.ToString("o") + " - resorted");
}
}
public static List<(int, int)> FindInView((int,int) start, CellWalkableState[,] grid)
{
List<(int, int)> visible = new List<(int, int)>() { start };
bool alive = true;
int r = 1;
var length_x = grid.GetLength(0);
var length_y = grid.GetLength(1);
List<(int, int)> searched = new List<(int, int)>();
List<double> angles = new List<double>();
while(alive)
{
//alive = false;
int newR = r;
int count = CountFromR(newR);
var angleInc = 360.0 / count;
var rNexts = Enumerable.Repeat(1, count).ToArray();
for (int i = 0; i < count; i++)
{
var angle = angleInc * i;
if(angles.Contains(angle) == false)
{
angles.Add(angle);
float cos = Mathf.Cos((float)(Mathf.Deg2Rad * angle));
float sin = Mathf.Sin((float)(Mathf.Deg2Rad * angle));
var b = r;
var p = i % (r * 2);
var d = math.sqrt(math.pow(b, 2) + math.pow(p, 2));
var dScaled = d / r;
bool keepGoing = true;
while(keepGoing)
{
var rCur = dScaled * (rNexts[i]);
var loc = (start.Item1 + Mathf.RoundToInt(rCur * cos), start.Item2 + Mathf.RoundToInt(rCur * sin));
if (searched.Contains(loc) == false)
{
searched.Add(loc);
if (loc.Item1 >= 0 && loc.Item1 < length_x && loc.Item2 >= 0 && loc.Item2 < length_y)
{
if (grid[loc.Item1, loc.Item2] == CellWalkableState.Interactive || grid[loc.Item1, loc.Item2] == CellWalkableState.Walkable)
{
visible.Add(loc);
}
else
{
keepGoing = false;
}
}
else
{
keepGoing = false; // invalid, stop
}
}
else
{
if (visible.Contains(loc) == false)
{
keepGoing = false; // can stop, because we can't see past this place
}
}
if(keepGoing)
{
rNexts[i]++;
}
}
}
}
angles = angles.Distinct().ToList();
searched = searched.Distinct().ToList();
visible = visible.Distinct().ToList();
if(rNexts.All(x => x <= r))
{
alive = false;
}
else
{
r = rNexts.Max();
}
}
return visible;
}
static int CountFromR(int r)
{
return 8 * r;
}
The "short" summary of the code above is that each location first determines what cells around itself it can see. That becomes a list of tuples, List<((int,int), List<(int,int)>)>, where the first item is the location and the second is all cells it views. That main list is sorted by the count of the sublist, such that the item with the most cells-it-can-vew is first. That's added as a centroid, and all cells it can view are added to a second ("already handled") list. A modified "main list" is formed, with each sublist now excluding anything in the second list. It loops doing this until 90% of the cells have been added.
Some output:
2021-04-27T15:24:39.8678545-04:00 - Setting centroids for room with 7129 cells
2021-04-27T15:45:26.4418515-04:00 - got in view
2021-04-27T15:45:26.4578551-04:00 - sorted
2021-04-27T15:45:27.3168517-04:00 - added centroids, 4756 cells in view
2021-04-27T15:45:27.9868523-04:00 - excluded
2021-04-27T15:45:27.9868523-04:00 - resorted
2021-04-27T15:45:28.1058514-04:00 - added centroids, 6838 cells in view
2021-04-27T15:45:28.2513513-04:00 - excluded
2021-04-27T15:45:28.2513513-04:00 - resorted
2021-04-27T15:45:28.2523509-04:00 - Setting centroids for room with 20671 cells
This is just too slow for my purposes. Can anyone suggest alternate methods of doing this? For all of the cells essentially the only information one has is whether they're "open" or one can see through them or not (vs something like a wall).
An approximate solution with fixed integer slopes
For a big speedup (from quadratic in the number of rooms to linear), you could decide to check just a few integer slopes at each point. These are equivalence classes of visibility, i.e., if cell x can see cell y along such a line, and cell y can see cell z along the same line, then all 3 cells can see each other. Then you only need to compute each "visibility interval" along a particular line once, rather than per-cell.
You would probably want to check at least horizontal, vertical and both 45-degree diagonal slopes. For horizontal, start at cell (1, 1), and move right until you hit a wall, let's say at (5, 1). Then the cells (1, 1), (2, 1), (3, 1) and (4, 1) can all see each other along this slope, so although you started at (1, 1), there's no need to repeat the computation for the other 3 cells -- just add a copy of this list (or even a pointer to it, which is faster) to the visibility lists for all 4 cells. Keep heading right, and repeat the process as soon as you hit a non-wall. Then begin again on the next row.
Visibility checking for 45-degree diagonals is slightly harder, but not much, and checking for other slopes in which we advance 1 horizontally and some k vertically (or vice versa) is about the same. (Checking for for general slopes, like for every 2 steps right go up 3, is perhaps a bit trickier.)
Provided you use pointers rather than list copies, for a given slope, this approach spends amortised constant time per cell: Although finding the k horizontally-visible neighbours of some cell takes O(k) time, it means no further horizontal processing needs to be done for any of them. So if you check a constant number of slopes (e.g., the four I suggested), this is O(n) time overall to process n cells. In contrast, I think your current approach takes at least O(nq) time, where q is the average number of cells visible to a cell.
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;
}
}
}
}
}
}
}
im work on temperature data ,and i want to interpolate the data to any location that i specify . my programming language is asp.net4 c#. i dont know how can i determine the sill,range,nugget for experimental variogram or theoratical variogram?
i make the following code to calculate these variables in experimental variogram :
public void Calculate_EmpericalVari_nugget_sill_range()
{
double H=0,VaiogramValue;
int N = KnownPoints.Count;
for (int j = 0; j < N; j++)//calculate the emperical variogram
{
for (int i = 0; i < N; i++)
{
H = AucledianDistance(KnownPoints[i].X, KnownPoints[i].Y,
KnownPoints[j].X, KnownPoints[j].Y);
VaiogramValue = 0.5 * Math.Pow((KnownPoints[i].Z - KnownPoints[j].Z), 2);
Emper_Variogram[i][j] = VaiogramValue;
if (H==0) nugget = VaiogramValue;
if (sill < VaiogramValue)
{
sill = VaiogramValue;
range = H;
}
}
}
}
I work according to the following that sill is the max value and range is the distance when i get the sill and nugget is the value at distance equal zero?
does this right? and do they remain constants when i calculate the theoretical semivariogram
I have 2 lists containing points (x,y and z) and would like to find the closest points.
I assume I need to do something like this:
for (int i = 0; i < myarray1.Count; i++)
{
for (int j = 0; j < myarray2.Count; j++)
{
// Calculate the quadratic distance between 2 points (point in index i and j)
// Then store the minimum distance I guess?
}
}
another option is to use Kd-tree
using the Nearest neighbour search will give you a O(log n) complexity to find the nearest point to a given set of points, and your code will have O( n log n), instead of O (n^2).
see here for implementation and example of how to use it.
double min_dist = DOUBLE_MAX;
for (i = 0; i < myarray1.Count; i++)
{
for (j = 0; j < myarray2.Count; j++)
{
curr_dist = dist(a[i],a[j]);
if( min_dist > curr_dist)
{
min_dist = curr_dist;
}
}
}
where
double dist(Point a, Point b) {
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)+pow(a.z-b.z,2);
}
To compute the distance:
double sqr(double x) {return x*x;}
double distance(MyPoint a, MyPoint b) {
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)+sqr(a.z-b.z);
}
Then in the second loop you store the minimum distance found so far:
double d = distance(myarray1[i],myarray2[j]);
if (d<min_d) min_d = d;
where min_d is defined at the beginning:
double min_d = Float.MAX_VALUE;
In C# I would do this using Linq.
First I would define the function that calculates the distance between two points as in Emanuelle Paolini's answer:
public double Distance(Point p1, Point p2)
{
return Math.Sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p1.y) * (p1.y - p1.y) + (p1.z - p1.z) * (p1.z - p1.z));
}
Then I would query the two lists as follows:
var distanceQuery = from p1 in myarray1
from p2 in myarray2
select Dist(p1, p2);
And finally I would retrieve the minimum distance:
var minimumDistance = distanceQuery.Min();
Formula is
Math.sqrt(Math.pow(Math.abs(x1-x2),2) + Math.pow(Math.abs(y1-y2),2)+ Math.pow(Math.abs(z1-z2),2))
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.