I have a MySQL table with cities, and for each city I have the geo coordinates. I want to build a query that determines the nearest city given coordinates of any random position. Can anyone give me an example?
Maybe I misunderstood the question, but if you have:
[X1,Y1] - the coordinates of your position
[Xn,Yn] - for each city
Then why not just calculate the distance using the simple sqrt((X1-Xn)^2 + (Y1-Yn)^2) formula?
You could optimize it further be making some clever selects, to only get the vicinity of the position from the DB and then run the distance measuring on these cities.
http://www.davidus.sk/web/main/index/article_id/8
There you go, distance is actually a radius. It will return all cities within it.
Related
I have a SQL database set of places to which I am assigned coordinates (lat, long). I would like to ask those points that lie within a radius of 5km from my point inside. I wonder how to construct a query in a way that does not collect unnecessary records?
Since you are talking about small distances of about 5 km and we are probably not in the direct vicinity of the north or south pole we can work with an approximated grid system of longitude and latitude values. Each degree in latidude is equivalent to a distance of km_per_lat=6371km*2*pi/360degrees = 111.195km. The distance between two longitudinal lines that are 1 degree apart depends on the actual latitude:
km_per_long=km_per_lat * cos(lat)
For areas here in North Germany (51 degrees north) this value would be around 69.98km.
So, assuming we are interested in small distances around lat0 and long0 we can safely assume that the translation factors for longitudinal and latitudinal angles will stay the same and we can simply apply the formula
SELECT 111.195*sqrt(power(lat-#lat0,2)
+power(cos(pi()/180*#lat0)*(long-#long0),2)) dist_in_km FROM tbl
Since you want to use the formula in the WHERE clause of your select you could use the following:
SELECT * FROM tbl
WHERE 111.195*sqrt(power(lat-#lat0,2)
+power(cos(pi()/180*#lat0)*(long-#long0),2)) < 5
The select statement will work for latitude and longitude values given in degree (in a decimal notation). Because of that we have to convert the value inside the cos() function to radians by multiplying it with pi()/180.
If you have to work with larger distances (>500km) then it is probably better to apply the appropriate distance formula used in navigation like
cos(delta)=cos(lat0)*cos(lat)*cos(long-long0) + sin(lat0)*sin(lat)
After calculating the actual angle delta by applying acos() you simply multiply that value by the earth's radius R = 6371km = 180/pi()*111.195km and you have your desired distance (see here: Wiki: great circle distance)
Update (reply to comment):
Not sure what you intend to do. If there is only one reference position you want to compare against then you can of course precompile your distance calculation a bit like
SELECT #lat0:=51,#long0:=-9; -- assuming a base position of: 51°N 9°E
SELECT #rad:=PI()/180,#fx:=#rad*6371,#fy:=#fx*cos(#rad*#lat0);
Your distance calculation will then simplify to just
SELECT #dist:=sqrt(power(#fx*(lat-#lat0),2)+power(#fy*(long-#long0),2))
with current positions in lat and long (no more cosine functions necessary). It is up to you whether you want to store all incoming positions in the database first or whether you want to do the calculations somewhere outside in Spring, Java or whatever language you are using. The equations are there and easy to use.
I would go with Euklid. dist=sqrt(power(x1-x2,2)+power(y1-y2,2)) . It works everywhere. Maybe you have to add a conversion to the x/y-coordinates, if degrees can't be translated in km that easy.
Than you can go and select everything you like WHERE x IS BETWEEN (x-5) AND (x+5) AND y IS BETWEEN (y-5) AND (y+5) . Now you can check the results with Euklid.
With an optimisation of the result order, you can get better results at first. Maybe there's a way to take Euklid to SQL, too.
I would like to find all points that are within N miles of a given area.
E.g. the area is California: Find all points that are within 50 miles of the border of California (not the middle of California).
When using Google Maps the distance is calculated using 'the middle' of the given location, but I need to calculate the distance using the borders of the given location. The location could be any zip code, city or country.
Could that be done by drawing a polygon using California's coordinates on a map and calculate the distance to location B using the points of the polygon?
Is there a more elegant solution to this? Any ideas?
Thanks!
I'm not sure if I understand your requirements completely, but I will give it a try with different interpretations:
1. You want to filter own map points:
This can be done with any GIS or a own service that offers a call like my_points_in_area(bbox). Bbox means here boundingbox and is the 2x lat/lon pair describing the rectangle around your given centerpoint. If you want to be accurate and really just deliver whats within 100km, you might need to test the distance to the POIs once more, as the rectangle will also include points that are a bit more far away.
2. You want to filter OSM data:
You might use a reverse-geocoding service as Nominatim to get informations about points of interests that are within this distance: http://wiki.openstreetmap.org/wiki/Nominatim
Otherwise import the OSM data using osmosis to a PostGIS DB. AFAIK there is (currently) no DB tool for Oracle: http://wiki.openstreetmap.org/wiki/Oracle
I'm sorry if I missed your question, but then please add more details :)
I'm trying to query any locations within a specified distance from another location. The query is not the problem, but the distance returned by geography.STDistance is.
It seems STDistance makes fairly accurate calculations on locations close to the equator, but I need this to work with locations in the nordic countries. Norway, Sweden, Finland and so on...
According to my calculations, made on locations in northern Sweden, the distance is wrong by a factor of around 2.38?!
Expected result is 1070 meters and returned distance is 2537,28850694302 meters
My query looks like this:
DECLARE #g geography = geography::STGeomFromText('POINT(65.580254 22.179428)', 4326)
SELECT name, [pos].STSrid as srdi, [pos].STDistance(#g) as d
FROM [GPSCHAT].[dbo].[USERS]
and the "other location" has coordinates (65,578541 22,202286) (stored with SRID 4326)
I'm guessing this has to do with the distance from the equator (close to the polar circle), but there has to be a way to calculate this more accurately based on the Latitude or am i wrong?
It looks like you're creating your point using 'X, Y'.
When creating a point from text, use 'Y, X' instead.
Check out this MSDN Article for some more info.
Why don't you make use of another spatial reference identifier which fits better the earth curvature around your position. SRID 4326 might not been measured as accurate as other local referential systems
My question is somewhat related to this similar one, which links to a pretty complex solution - but what I want to understand is the result of this:
Using a Mysql Geometry field to store a small polygon I duly ran
select AREA(myPolygon) where id =1
over it, and got an value like 2.345. So can anyone tell me, just what does that number represent seeing as the stored values were long/lat sets describing the polygon?
FYI, the areas I am working on are relatively small (car parks and the like) and the area does not have to be exact - I will not be concerned about the curvature of the earth.
2.345 of what? Thanks, this is bugging me.
The short answer is that the units for your area calculation are basically meaningless ([deg lat diff] * [deg lon diff]). Even though the curvature of the earth wouldn't come into play for the area calculation (since your areas are "small"), it does come into play for the calculation of distance between the lat/lon polygon coordinates.
Since a degree of longitude is different based on the distance from the equator (http://en.wikipedia.org/wiki/Longitude#Degree_length), there really is no direct conversion of your area into m^2 or km^2. It is dependent on the distance north/south of the equator.
If you always have rectangular polygons, you could just store the opposite corner coordinates and calculate area using something like this: PHP Library: Calculate a bounding box for a given lat/lng location
The most "correct" thing to do would be to store your polygons using X-Y (meters) coordinates (perhaps UTM using the WGS-84 ellipsoid), which can be calculated from lat/lon using various libraries like the following for Java: Java, convert lat/lon to UTM. You could then continue to use the MySQL AREA() function.
I am trying to calculate distance between two locations using spatial functions in both Mysql and PostgresSQL. I have taken the latitude and longitude from Google. The details are below
Location one - Lat: 42.260223; Lon: -71.800010
Location two - Lat: 42.245647; Lon: -71.802521
SQL Query used:
SELECT DISTANCE(GEOMFROMTEXT('Point(42.260223 -71.800010)'),GEOMFROMTEXT('Point(42.245647 -71.802521)'))
The both databases are giving the same result 0.014790703059697. But when I calculate distance in other systems the results are different. Please refer the below links
http://www.zip-codes.com/distance_calculator.asp?zip1=01601&zip2=01610&Submit=Search = 1.44 miles
http://www.distancecheck.com/zipcode-distance.php?start=01601&end=01610 = 1.53 miles
So I want to know whether my calculation method/query is right or not. And if it is wrong, then what is the right way of querying the db for the distance.
The simple answer is to use the Haversine formula. This assumes the earth is a sphere, which it isn't, but it's not a bad approximation. This, with lots of other details are described in this presentation:
http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
In the case above, MySql is simply applying the pythagorean theorem: c2 = a^2 + b^2. In this specific case SQRT((42.245647 - 42.260223)^2 + (-71.802521^2 - -71.800010)^2) = 0.014790703.
There are actually two problems with using the MySql distance functon for distance with coordinates on a sphere. (1) MySql is caclulating distance on a plane, not a sphere. (2) The result is coming back in a form of degrees, not miles. To get a true, spherical distance in miles, km, ft etc, you need to convert your lat and long degrees into the units you want to measure by determining the radius from a line through the center of the earth for the latitude(s) you are measuring.
To get a true measure is quite complicated, many individuals and companies have made careers out of this.