Convert meters to decimal degrees - c#

I need to convert meters to decimal degrees in C#. I read on Wikipedia that 1 decimal degree equals 111.32 km. But it is on equator, so if I'm located above/below it my the conversion will be wrong?
I assume this is wrong:
long sRad = (long.Parse(sRadTBx.Text)) / (111.32*1000);
EDIT: I need this search radius to find nearby users
long myLatitude = 100;
long myLongitude = 100;
long sRad = /* right formula to convert meters to decimal degrees*/
long begLat = myLatitude - searchRad;
long endLat = myLatitude + searchRad;
long begLong = myLongitude - searchRad;
long endLong = myLongitude + searchRad;
List<User> FoundUsers = new List<User>();
foreach (User user in db.Users)
{
// Check if the user in the database is within range
if (user.usrLat >= begLat && user.usrLat <= endLat && user.usrLong >= begLong && user.usrLong <= endLong)
{
// Add the user to the FoundUsers list
FoundUsers.Add(user);
}
}

Also from that very same Wikipedia article:
As one moves away from the equator towards a pole, however,
one degree of longitude is multiplied by
the cosine of the latitude,
decreasing the distance, approaching zero at the pole.
So this would be a function of latitude:
double GetSRad(double latitude)
{
return 111.32 * Math.Cos(latitude * (Math.PI / 180));
}
or similar.
edit: So for going the other way around, converting meters to decimal degrees, you need to do this:
double MetersToDecimalDegrees(double meters, double latitude)
{
return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}

Christopher Olsson already has a good answer, but I thought I'd fill in some of the theory too.
I've always found this webpage useful for these formulas.
A quick note on the concept
Think about the actual geometry going on.
As it stands, you are currently doing nothing more than scaling the input. Imagine the classic example of a balloon. Draw two lines on the balloon that meet at the bottom and the top. These represent lines of longitude, since they go "up and down." Quotes, of course, since there aren't really such concepts, but we can imagine. Now, if you look at each line, you'll see that they vary in distance as you go up and down their lengths. Per the original specification, they meet at the top of the balloon and the bottom, but they don't meet anywhere else. The same is true of lines of longitude. Non-Euclidean geometry tells us that lines intersect exactly twice if they intersect at all, which can be hard to conceptualize. But because of that, the distance between our lines is effectively reflected across the equator.
As you can see, the latitude greatly affects the distance between your longitudinal lines. They vary from the closest at the north and south poles, to the farthest away at the equator.
Latitudinal lines are a bit easier. They do not converge. If you're holding our theoretical balloon straight up and down, with the poles pointed straight up and straight down that is, lines of latitude will be parallel to the floor. In a more generalized sense, they will be perpendicular to the axis (a Euclidean concept) made by the poles of the longitudinal lines. Thus, the distance is constant between latitudes, regardless of your longitude.
Your implementation
Now, your implementation relies on the idea that these lines are always at a constant distance. If that was the case, you'd be able to do take a simple scaling approach, as you have. If they were, in fact, parallel in the Euclidean sense, it would be not too dissimilar to the concept of converting from miles per hour to kilometers per hour. However, the variance in distance makes this much more complicated.
The distance between longitudes at the north pole is zero, and at the equator, as your cited Wikipedia page states, it's 111.32 kilometers. Consequently, to get a truly accurate result, you must account for the latitude you're looking for. That's why this gets a little more complicated.
Getting Realistic Results
Now, the formula you want, given your recent edit, it seems that you're looking to incorporate both latitude and longitude in your assessment. Given your code example, it seems that you want to find the distance between two coordinates, and that you want it to work well at short distances. Thus, I will suggest, as the website I pointed you to at the beginning of this posts suggests, a Haversine formula. That website gives lots of good information on it, but this is the formula itself. I'm copying it directly from the site, symbols and all, to make sure I don't make any stupid typos. Thus, this is, of course, JavaScript, but you can basically just change some cases and it will run in C#.
In this, φ is latitude, λ is longitude, θ is the bearing (in radians, clockwise from north), δ is the angular distance (in radians) d/R; d being the distance travelled, R the earth’s radius
var R = 6371; // km
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
I think the only thing that must be noted here is that R, as declared in the first line, is the radius of the earth. As the comment suggests, we're already working in kilometers so you may or may not have to change that for your implementation. It's easy enough, fortunately, to find the (average) radius of the earth in your favorite units by doing a search online.
Of course, you'll also want to note that toRadians is simply the input multiplied by Math.PI, then divided by 180. Simple enough.
Alternative
This doesn't really look relevant to your case, but I will include it. The aforementioned formula will give accurate results, but it will be at the cost of speed. Obviously, it's a pretty small deal on any individual record, but as you build up to handle more and more, this might become an issue. If it does, and if you're dealing in a fairly centralized locale, you could work off the immense nature of our planet and find numbers suitable for the distance between one degree of latitude and longitude, then treat the planet as "more or less Euclidean" (flat, that is), and use the Pythagorean Theorem to figure the values. Of course, that will become less and less accurate the further away you get from your original test site (I'd just find these numbers, personally, by asking Google Earth or a similar product). But if you're dealing with a dense cluster of users, that will be way, way, way faster than running a flurry of formulas to the Math class to work out.
Another, more abstract alternative
You might also want to think about where you're doing this logic. Here I begin to overstep my reach a bit, but if you happen to be storing your data in SQL Server, it already has some really cool geography functionality built right in that will handle distance calculations for you. Just check out the GEOGRAPHY type.
Edit
This is a response to a comment, suggesting that the desired result is really a rectangle denoting boundaries. Now, I would advise against this, because it isn't really a search "radius" as your code may suggest.
But if you do want to stick to that method, you'll be looking at two separate distances: one for latitude and one for longitude. This is also from that webpage. φ1 is myLatitude, and λ1 is myLongitude. This formula accepts a bearing and starting coordinates, then gives the resulting position.
var φ2 = Math.asin( Math.sin(φ1)*Math.cos(d/R) + Math.cos(φ1)*Math.sin(d/R)*Math.cos(brng) );
var λ2 = λ1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(φ1), Math.cos(d/R)-Math.sin(φ1)*Math.sin(φ2));
You could use that to determine the boundaries of your search rectangle.

Related

Unity/C# Adding two areas represented by two vectors

I have two areas, which are both given in there bounds.size. Now the z-axis doesnt matter for me, since im working in 2D. I want to add these vectors so i have a vector, which represents the jointed area. Simply adding these vectors the normal way does not work. The way the area looks in the end is not important, its just important that the size is the same as, both areas combined.
Edit: I have the bounds.size of two polygoncolliders and i want to get a value that represents the bounds.size of the two polygoncolliders combined
area 1 and area 2 combined
The way the area looks in the end is not important, its just important that the size is the same as, both areas combined.
As there are nigh infinite possibilities otherwise, I'm going to limit myself to results where x = y, for the simple reason that you don't end up with silly vectors like (0.5,80000) but rather a more balanced (200,200).
This isn't all that hard when you look at it algebraically:
float result_area = first_area + second_area;
Calculating the area is easy:
float area = myVector.X * myVector.Y;
Thus rendering the sum of the areas also easy:
float result_area = myFirstVector.X * myFirstVector.Y + mySecondVector.X * mySecondVector.Y;
For the sake of example, let's say first_area = 50 and second_area = 350, thus resulting in result_area = 400;
Since we are limited to results where x = y, the result is the square root of the area:
float theSquareRoot = Math.Sqrt(result_area);
myResultVector.X = theSquareRoot;
myResultVector.Y = theSquareRoot;
As I said, there are many other possible result vectors. For other cases, you're either going to have to define a given ratio (e.g. a ratio of 1 : 4 would give you (10,40) for the same example), but the calculation is a bit harder and you mentioned that you don't care about the exact shape anyway.
You could also just make a vector where X = result_area and Y = 1 (or vice versa), without having to calculate a square root.
Note that you've overengineered it. The area of an object is a onedimensional value (a number); yet you're expressing it using a twodimensional value (a number pair) to represent them.
Since you don't care about particular X/Y values, only what their product is, I would suggest you avoid vectors where possible, so you don't make it unnecessarily complicated.

Check for equality of doubles in a list with a threshold

I am working on a method wich should decide whether or not a curve has a nearly constant slope or not.
There are of course x,y points involved. What I did so far is dividing y of each data point by its x to get the slope of that data point. I store this slopes in a List<double>
I think so far I am on the right track (tell me please, if I am not!). Now it's time to decide about being dealing with a constant curve or not, so I ended up with the method below:
private bool IsConstantSlope(List<double> slopes)
{
var max = slopes.Max();
var min = slopes.Min();
var diff = max - min;
return (diff > 0.01) ? false : true;
}
So what I do here checking for maximum and minimum values of slopes and compare it to a custom threshold which I beleive is not good at all.
This method works good for perfectly constant sloped lines, but I want to give it some felexibility, I don't think comparing the difference of max and min values to a constant number is a good practice.
I will appriciate more ideas!
There are ofcource x,y points involved. what I did so far is dividing
y of each data point by its x to get the slope of that data point. I
store this slopes in a List
Strictly speaking a point does not have a slope, what you are measuring here is the slope of the line that connects your point (x,y) and the point (0,0). So if you are doing this for an ordered set of points, then the notion of having a single line is not quite correct. You dont even have the set of slopes of lines that connect adjacent points. Also in your function
return (max > 0.01) || (min < -0.01);
is better if your threshold is 0.01.
If what you really want is a line that fits or approximates the set of points then you first need to perform some kind of straight line regression to your data and test the gradient of this approximating line to see if it is within your threshold limits.
This might be a useful read http://en.wikipedia.org/wiki/Simple_linear_regression
Alternatively, you can order your points by their x value, then work out the slope between each consecutive pair (effectively generating a polyline) and store these in your list and then use your slope camparison function.
I would design a recursive algorithm, working on the whole set of slopes. Considering only the min/max slopes doesn't tell anything about the whole curve.
First of all, I would establish which is the requirement that two slopes A and B must fulfill in order to determine a "constant slope". Then, I would consider the first (A) and last (B) values in your list: do the two values statisfy the requirement? No: no constant slope; Yes: subdivide the range (A,B) into two subranges: (A,M), (M,B) where M is the value equidistant, in the list, from A and B. Then you apply the same algorithm to the two subranges. The number of subranges depends on the accuracy you want to achieve.

Fast algorithm to find the x closest points to a given point on a plane

I would like to find a fast algorithm in order to find the x closest points to a given point on a plane.
We are actually dealing with not too many points (between 1,000 and 100,000), but I need the x closest points for every of these points. (where x usually will be between 5 and 20.)
I need to write it in C#.
A bit more context about the use case: These points are coordinates on a map. (I know, this means we are not exactly talking about a plane, but I hope to avoid dealing with projection issues.) In the end points that have many other points close to them should be displayed in red, points that have not too many points close to them should be displayed green. Between these two extremees the points are on a color gradient.
What you need is a data structure appropriate for organizing points in a plane. The K-D-Tree is often used in such situations. See k-d tree on Wikipedia.
Here, I found a general description of Geometric Algorithms
UPDATE
I ported a Java implementation of a KD-tree to C#. Please see User:Ojd/KD-Tree on RoboWiki. You can download the code there or you can download CySoft.Collections.zip directly from my homepage (only download, no docu).
For a given point (not all of them) and as the number of points is not extreme, you could calculate the distance from each point:
var points = new List<Point>();
Point source = ...
....
var closestPoints = points.Where(point => point != source).
OrderBy(point => NotReallyDistanceButShouldDo(source, point)).
Take(20);
private double NotReallyDistanceButShouldDo(Point source, Point target)
{
return Math.Pow(target.X - source.X, 2) + Math.Pow(target.Y - source.Y, 2);
}
(I've used x = 20)
The calculation are based on doubles so the fpu should be able to do a decent job here.
Note that you might get better performance if Point is a class rather than a struct.
You need to create a distance function, then calculate distance for every point and sort the results, and take the first x.
If the results must be 100% accurate then you can use the standard distance function:
d = SQRT((x2 - x1)^2 + (y2 - y1)^2)
To make this more efficent. lets say the distance is k. Take all points with x coordinates between x-k and x+k. similarly take, y-k and y+k. So you have removed all excess coordinates. now make distance by (x-x1)^2 + (y-y1)^2. Make a min heap of k elements on them , and add them to the heap if new point < min(heap). You now have the k minimum elements in the heap.

C# find all Latitude and Longitude within a mile

Given a lat and long value, is there any way of finding all lat and longs that are within a specified distance? I have a db table of lat and long values which are locations of let's say street lamps, given a lat long pair how could I find all those that are within a particular distance?
I guess drawing a circle from the starting point and finding all lat and longs contained would be the best way however, I don't have the skills to do this. I am a c# developer by trade but need a few pointers in the whole geocoding world.
You could use the Haversine Formula (see #tdammers answer) to calculate a distance between each point (Lat, Long) in your table and the given point. You will have to iterate over the entire collection in order to evaluate each point individually.
Or, if you are using SQL Server 2008, then geospatial support is built-in. Each record would store the location as a geography type (possibly in addition to two discrete columns to hold Latitude and Longitude, if it's easier to have those values broken out), and then you can construct a simple SQL query:
DECLARE #Point geography = 'POINT(-83.12345 45.12345)' -- Note: Long Lat ordering required when using WKT
SELECT *
FROM tblStreetLamps
WHERE location.STDistance(#point) < 1 * 1609.344 -- Note: 1 mile converted to meters
Another similar possibility is to bring the SQL Spatial types into your .NET application. The redistributable is found here: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=CEB4346F-657F-4D28-83F5-AAE0C5C83D52 (under Microsoft® System CLR Types for SQL Server® 2008 R2).
Then, the querying can be done via LINQ. Note: This saves you from implementing the Haversine by yourself, otherwise the process of querying would be the same.
var yourLocation = SqlGeography.Point(Latitude, Longitude, 4326);
var query = from fac in FacilityList
let distance = SqlGeography
.Point(fac.Lat, fac.Lon, 4326)
.STDistance(yourLocation)
.Value
where distance < 1 * 1609.344
orderby distance
select fac;
return query.Distinct().ToList();
The haversine formula gives you the distance (in meters; converting to miles is trivial) between two lat/lon points. From there, you can probably find the reverse...
I'm a little late for answering this, but I came up with a trick years ago to do essentially the same for satellite fields of view.
There are two points on earth where you exactly know the latitude and longitude of every point a given distance from your location. Those points are the North and South poles. So let’s put the point you want at North pole. One nautical mile away is the circle of longitudes with latitude 90 degrees minus 1 minute, or 90 – 1/60 degrees = 89.9833 degrees North latitude, since 1 minute of arc = 1 nautical mile.
Now that you have the locus of longitudes one mile from the pole with latitude 89.9833, you essentially rotate the earth until the lat/long you want is where the pole used to be. This process is called “The Rotation of the Map Graticules”. The math for this is straight forward, once you’ve thought about the equations awhile. I have them buried somewhere, so I can’t get to the code easily, however the process, with the equations is in John Snyder’s book “Map Projections: A Working Manual”. You can get the pdf free at http://pubs.usgs.gov/pp/1395/report.pdf. The explanation is on pages 29 – 32.
Chuck Gantz
some time ago I was solving a problem how to get POIs along the road. I made use of quadtree, that means dividing the whole area into cells and subcells recursively. Each POI belongs to only one cell. Having these cells you can easily do high level calculation on cell level and after that search only cells with intersection. It's more game development technique but can be used here as well. Here is something about it on Wiki:
http://en.wikipedia.org/wiki/Quadtree

How to get the closest significant population centre from a latitude and longitude?

I'm currently trying to reverse geocode a series of lat/long co-ordinates using the Virtual Earth/Bing Maps web services. Whilst I can successfully retrieve an address for the positions I also need to be able to retrieve the closest significant population centre for the position so I can display a heading and distance to the centre of the nearest town/city/metropolis etc. This is for cases where the location is travelling between locations e.g. on a highway/motorway.
Has anyone out there got any ideas how to do this as I've been banging my head against it for a few days now and I've gotten nowhere!
Cheers in advance...
I think it is safe to assume that the nearest city is always quite close compared with the size of the Earth, so you can use a simple pythagoras triangle.
Suppose you are at (lat0, long0) and a trial city is at (lat1, long1).
Horizontal (EW) distance is roughly
d_ew = (long1 - long0) * cos(lat0)
This is multiplied by cos(lat0) to account for longitude lines getting closer together at high latitude.
Vertical (NS) distance is easier
d_ns = (lat1 - lat0)
So the distance between the two points is
d = sqrt(d_ew * d_ew + d_ns * d_ns)
You can refine this method for more exacting tasks, but this should be good enough for the nearest city.
For comparing distances, it will be fine to compare d squared, which means you can omit the sqrt operation.
try using the wikipedia location service, documented here
http://www.geonames.org/export/wikipedia-webservice.html
It sounds like you're looking for a database of latitudes and longitudes of major cities, so you can calculate distances.
This is a link to a page giving a few dozen, world-wide.
There may be others, most likely US-centric (but that may be what you want).
I would do the following:
table 1:
T_CityPopulation
Fields:
CityTownInfo,Population,LonLat
Then compute distance between your current LonLat for each record in table 1, using a threshold value ignore towns/citys over x miles. Then sort the results by Population.
EDIT:
Even if you don't want to maintain a table, it has to be stored somewhere, I think if you maintained it yourself at least you have control over it, vs relying on another service.

Categories