views:

105

answers:

1

Assume I have a point at the following location:

Latitude: 47°36′N Longitude: 122°19′W

Around the above point, I draw a 35Km radius. I have another point now or several and I want to see if they fall within the 35Km radius? How can I do this? Is it possible with Linq given the coordinates (lat, long) of both points?

+3  A: 

Sure. Assume you have a function that computes the Haversine distance between two Positions (consisting of a latitude and longitude coordinate). If you don't you can find one here. Then simply use the function as the selector in a Where clause. If using LINQ to SQL, you'll need to materialize them to your Position objects so that the you can use the Haversine function on them as LINQ to objects; there isn't a translation to SQL, though you could probably create a table-valued function that does the same thing if you really don't want to return all the points first.

var origin = new Position( 47.6, 122.3 );
var close = positions.Where( p => Haversine.Distance( origin, p, DistanceType.Km ) <= 35 );
tvanfosson
I will give this a shot and let you know.
Xaisoft
Hi. I have it partly working, but I am a little confused on what you mean by materialize them to Position objects? Can you help me out with that.
Xaisoft
@Xaisoft, because LINQ can't translate the call to the Haversine function to SQL, it needs to work with them as objects. This means that, if you are getting the points from a DB, you need to fetch them into memory before the Where clause. The easiest way to do that is to insert a ToList() in the chain before it. That will cause the query to be materialized (executed and brought into memory) where you can work with them as objects. (cont)
tvanfosson
If the number of results returned would be too big, you might want to filter them first. One way to do this would be to calculate a square around your point -- i.e., calculate the min/max latitude/longitude that would be within 35km (35km ~= 0.32deg at the equator). Note that longitude gets smaller as you get near the poles so this is inexact. Find the points within your square and materialize them, then run the Haversine function, which accounts for the differences as you near the poles.
tvanfosson
Its only 50 points, so it is not too big. Let me see if I understand you correctly. I can read all 50 points into a a collection of Position objects that contain a lat and long property and then run the haversine function between my point and the 50 other points.
Xaisoft
Yes. They have to be in memory for the function to be applied: `db.MyTable.Select( t => new { Position = Position( t.Lat, t.Long ), ID = t.ID } ).ToList().Where( p => Haversine.Distance( origin, p.Position, DistanceType.Km ) <= 35 );`
tvanfosson