Finding nearest coordinate to other coordinate - c#

Given an array of geo coordinates and another geo coordinate, I would like to find the nearest coordinate(s) to it.
For example, given the array:
lat long
52.525782 13.316927
52.526409 13.319083
52.525678 13.320317
And the point: 52.525730, 13.314556, then the first point 52.525782, 13.316927 will be returned, as it is the closest one.
Is the only way of acheiving it is looping through all the array and finding the distance between the points? What happens if the array contains too much coordinates?

You can try it using LINQ, but the inner workings of LINQ would still loop over your collection. For example:
//Your list with coordinates
List<GeoCoordinate> coords = new List<GeoCoordinate>();
//The coord you want to compare
GeoCoordinate crd = new GeoCoordinate();
//Sorts the list based on the proximity of the coords to crd
var sortedCoords = coords.OrderBy(x => x.GetDistanceTo(crd)).ToList();
I know it doesn't use an array, but I find using lists is easier.
I think that should work, let me know if it does!

struct coord
{
public double lat;
public double lon;
}
public void Main(coord coord)
{
var coords = new[]{ new coord(){lat=1, lon=1} };
var closest = coords.Min(p => Math.Abs(p.lat - coord.lat) + Math.Abs(p.lon - coord.lon));
}

Related

Finding an item in linear graph using LINQ

I have a list of positions denoted by X and Y. [{3,4}, {5,5}, {6,5},{7,8}]
public class Position {
public int X { get; set; }
public int Y { get; set; }
}
I need to find positions which will be present in the linear graph Starting
x=1 and y=0. [{1,0},{2,1},{3,2},{4,3}, ...].
I do not have the list which denotes the graph. I am looking for a way to find the positions based on starting point of the graph.
I can create the list of possibilities and find the matching positions. Before I do that I want to know is there a better approach?
The points are on a straight line. The formula for the points you mention is: y = x - 1. You can apply this formula in a where clause:
var x = new List<Position>();
...
var pointsOnLine = x.Where(p => p.Y == p.X -1);
You can do this also if you have another line or formula.

how can I convert circleF object to array object using emgu c#

I am new at EmguCV & C# and I have a project that find circles' info (centers' X & Y coordinates) from USB Camera. According to these coordinates, prototype machine moves rollers with stepper motor x-axis or y-axis.
I used CircleF with HoughCircles and found coordinates with this code:
CircleF[] circles = imgProcessed.HoughCircles(new Gray(100), new Gray(50), 2, imgProcessed.Height / 4, 30, 45)[0];
I want to create 2d array from CircleF to apply array process and apply mathematical operations to circles' X and Y values.
I thought that if I convert "circles" CircleF to array, these processes are easier.
I know CircleF is a kind of array, but I cannot apply some array process (like sorting) on it. I want to sort X values of circles' centers from small to large. I cannot do that like Array.Sort(circles)
Does anybody help me about this situation?
or if it is possible to apply array process on CircleF, how can I apply?
Code samples would be useful. Thanks for now.
What exactly do you mean by "array process"? CircleF basically just "wraps" the center coordinate of the circle along with the radius and area. Take a look at the following which is taken from the Emgu.Cv.dll:
public struct CircleF : IEquatable<CircleF>
{
public CircleF(PointF center, float radius);
public double Area { get; }
public PointF Center { get; set; }
[XmlAttribute("Radius")]
public float Radius { get; set; }
public bool Equals(CircleF circle2);
}
So when iterating your array of CircleF structs you can:
for(int i=0;i < circles.Length;i++){
var currCircleF = circles[i];
//do something with currCircleF, e.g. change radius,center,etc.
}
To sort the array of circles according to the value of center X:
var sortedCircleFbyX = circles.OrderBy(c => c.Center.X).ToArray();
The result is an array of CircleF. You can then perform processing like:
//do more processing
foreach (var circleF in sortedCircleFbyX)
{
MoveStepperMotor(circleF.Center);
}

Jagged Multidimensional Arrays in C#

Note: I define a 'Jagged Multidimensional' specifically as jmArray[][,].
I'm trying to wrap my head around the use of this type of array, in order to hold simple coordinates, a pair of Integers. This array will be used to create a 3x3 grid, so in my head I'm seeing:
jmArray[N][X,Y]
Where N is the number of the grid slice, and X,Y are the coordinates of the slice. So:
jmArray[2][3,2]
Would mean that slice 2 lies at coordinate 3,2.
I've been trying to assign values to each slice, but I'm stuck somewhere...
jmArray[0][,] = new int[1,2] {{3,3}};
A little help in understanding how to do this properly would be nice.
Unless I'm misunderstanding you, a simpler way to do this would be to create a dictionary of size 3 tuples.
var space = Dictionary<Tuple<int, int, int>, TPointValue>;
// Fill up space with some points
space[Tuple.Create(3,3,1)] = new TPointValue(42);
// Retrieve point from 3d space
TPointValue point3_3_1 = space[Tuple.Create(3,3,1)];
I'll concede that in its current form, this approach makes retrieval of planes or basis lines cumbersome and inefficient compared to jagged arrays, although it does makes assignment and retrieval of points very efficient.
However: if you were to wrap this data structure in a class of your own that provides methods for accessing planes/lines etc, you could very easily and efficiently calculate the keys required to obtain any set of points beforehand, eg. those within a plane/line/polygon, and then access these points very efficiently.
PS: Note that the value at a point need not be some fancy type like TPointValue, it could be just a string or float or whatever you like.
You can achieve it like this:
int[][,] jmArray = new int[3][,];
jmArray[0] = new int[1,2] {{3,3}};
Instead of a complicated array a simple class with meaningful names might work better:
class Slice
{
int X = 0;
int Y = 0;
public Slice()
{
}
public Slice(int _X, int _Y)
{
X = _X;
Y = _Y;
}
}
Slice[] Slices = new Slice[9];
The index of the array will be the position of the slice.

Searching XML for coordinates using LINQ

I am not looking for any code, just advice on a particular aspect of a project.
I have an XML file that contains coordinates and the building name and I want to be able to capture the coordinates of where the person is (I'm going to be creating a mobile application so this is ok).
Is the senario above possible using a LINQ statement in C#? If so, is it possible to get a close match? i.e. if the person isn't exactly in the coordinates, show him/her the nearest match.
I'm NOT specifically looking for any code just any hints, tips, or advanced tutorials on LINQ would be helpful.
Thanks
You can use System.Device.Location.GeoCoordinate class for this
List<GeoCoordinate> listTakenFromXml = ......
double lat = ......
double lon = ........
var nearest = new GeoCoordinate(lat, lon).NearestPoint(listTakenFromXml);
public static class SoExtensions
{
public static GeoCoordinate NearestPoint(this GeoCoordinate loc, IEnumerable<GeoCoordinate> coords)
{
GeoCoordinate minLoc = null;
double minDist = double.MaxValue;
foreach (var c in coords)
{
var dist = c.GetDistanceTo(loc);
if ( dist < minDist)
{
minDist = dist;
minLoc = c;
}
}
return minLoc;
}
}
See Calculate distance, bearing and more between Latitude/Longitude points and use the method which bests suits your situation. Once you have the calculation if you have a set of points in a list, then Linq to Object's extensions can help you with determining your logic as needed.

Is there an algorithm to compute miles between coordinates?

I want to be able to display a Bing map in a Windows 8/Store app with an array of pushpins/waypoints at a zoom setting that will show every location, but no more than that - IOW, I want as much detail as possible while still showing all of the locations/coordinates.
I have this pseudocode:
public static int GetMapZoomSettingForCoordinates(List<String> coordinatesList)
{
string furthestNorth = GetFurthestNorth(coordinatesList);
string furthestSouth = GetFurthestSouth(coordinatesList);
string furthestEast = GetFurthestEast(coordinatesList);
string furthestWest = GetFurthestWest(coordinatesList);
int milesBetweenNorthAndSouthExtremes = GetMilesBetween(furthestNorth, furthestSouth);
int milesBetweenEastAndWestExtremes = GetMilesBetween(furthestEast, furthestWest);
int greaterCardinalDistance = Math.Max(milesBetweenNorthAndSouthExtremes, milesBetweenEastAndWestExtremes);
return GetZoomSettingForDistance(greaterCardinalDistance);
}
...but the "sticking point" (the hard part) are the "milesBetween" functions. Is there an existing algorithm for computing the miles between two coordinates?
I do realize this is a U.S.-centric bunch of code for now (miles vs. kilometers); that is, for now, as designed.
UPDATE
This is my new pseudocode (actual compiling code, but untested):
public static int GetMapZoomSettingForCoordinates(List<string> coordinatePairsList)
{
List<double> LatsList = new List<double>();
List<double> LongsList = new List<double>();
List<string> tempList = new List<string>();
foreach (string s in coordinatePairsList)
{
tempList.AddRange(s.Split(';'));
double dLat;
double.TryParse(tempList[0], out dLat);
double dLong;
double.TryParse(tempList[0], out dLong);
LatsList.Add(dLat);
LongsList.Add(dLong);
tempList.Clear();
}
double furthestNorth = GetFurthestNorth(LatsList);
double furthestSouth = GetFurthestSouth(LatsList);
double furthestEast = GetFurthestEast(LongsList);
double furthestWest = GetFurthestWest(LongsList);
int milesToDisplay =
HaversineInMiles(furthestWest, furthestNorth, furthestEast, furthestSouth);
return GetZoomSettingForDistance(milesToDisplay);
}
private static double GetFurthestNorth(List<double> longitudesList)
{
double northernmostVal = 0.0;
foreach (double d in longitudesList)
{
if (d > northernmostVal)
{
northernmostVal = d;
}
}
return northernmostVal;
}
...I still don't know what GetZoomSettingForDistance() should be/do, though...
UPDATE 2
This is "more better":
public static int GetMapZoomSettingForCoordinates(List<Tuple<double, double>> coordinatePairsList)
{
var LatsList = new List<double>();
var LongsList = new List<double>();
foreach (Tuple<double,double> tupDub in coordinatePairsList)
{
LatsList.Add(tupDub.Item1);
LongsList.Add(tupDub.Item2);
}
double furthestNorth = GetFurthestNorth(LongsList);
double furthestSouth = GetFurthestSouth(LongsList);
double furthestEast = GetFurthestEast(LatsList);
double furthestWest = GetFurthestWest(LatsList);
int milesToDisplay =
HaversineInMiles(furthestWest, furthestNorth, furthestEast, furthestSouth);
return GetZoomSettingForDistance(milesToDisplay);
}
UPDATE 3
I realized that my logic was backwards, or wrong, at any rate, regarding meridians of longitude and parallels of latitude. While it's true that meridians of longitude are the vertical lines ("drawn" North-to-South or vice versa) and that parallels of latitude are the horizontal lines ("drawn" East-to-West), points along those line represent the North-South location based on parallels of latitude, and represent East-West locations based on meridians of longitude. This seemed backwards in my mind until I visualized the lines spinning across (longitude) and up and over (latitude) the earth, rather than simply circling the earth like the rings of Saturn do; what also helped get my perception right was reminding myself that it is the values of the meridians of longitude that determine in which time zone one finds themselves. SO, the code above should change to pass latitudes to determine furthest North and furthest South, and conversely pass longitudes to determine furthest East and furthest West.
You can use the Haversine formula to compute the distance along the surface of a sphere.
Here's a C++ function to compute the distance using the Earth as the size of the sphere. It would easily be convertible to C#.
Note that the formula can be simplified if you want to just find the distance either latitudinally or longitudinally (which it sounds like you are trying to do).
To get the straight line distance you use the Pythagorean Theorem to find the hypotenuse.
d = ((delta x)^2 + (delta y)^2)^.5
Basically square both the changes in the x direction and the y direction, add them, then take the square root.
in your pseudo code it looks like you could have many points and you want to find a maximum distance that should encompass all of them, which makes sense if you are trying to figure out a scale for the zoom of the map. The same formula should work, just use milesBetweenEastAndWestExtremes for delta x, and milesBetweenNorthAndSouthExtremes for delta y. You may opt to add a fixed amount to this just to make sure you don't have points right on the very edge of the map.

Categories