I have a MySQL database table with a series of points, which is a specific geometry data type (basically, a lat/lon coordinate). I need to get all the points that are close to some coordinates (close meaning to less that 1 km, let's say).
Now I am getting ALL points from the table and, from PHP, calculating which of them have a distance shorter than the desired distance (1 km).
The problem is that there a thousands of points, so the performance is very poor.
Is there a way to get only those close points directly from the database? I don't guess what function may help me.
Thank you!
Related
I want to calculate distances between two coordinates but sometimes the origin coordinate is over / beyond the destination coordinate. And it is really problematic at one-way roads, because in this case the distance can be eg. 1 km to get back to the destination. In real life it is OK, but actually the real distance is only eg. 10 meters (if I could turn back on one-way roads). So only the direction is wrong.
I can resolve this problem if I call the API twice (origins=my_origin_coordinate&destinations=my_destination_coordinate and origins=my_destination_coordinate&destinations=my_origin_coordinate).
But is there a easier way to get both distance in one query? (to save my query limit...)
The distance matrix allows multiple results in a single query. You can do origins=my_origin_coordinate|my_destination_coordinate&destinations=my_origin_coordinate|my_destination_coordinate in a single request, which will give you both results. That won't really help with your quota though as the quota is based on "elements", and whether you do it in one query or two, it will be the same number of "elements".
I am working with PHP and use MySQL for database. I need a way, to get 5 closest coordinates to a given coordinate from database, which is very fast and at least 80-90% accurate. I have researched a lot. I found havershine formula, spherical law of cosines, bounding square method to compare min and max latitude-longitude values with coordinate in database and other methods which use trigonometric math functions. But all these formulas take a long to return result in database with thousands of entries. Does MySQL provide any function to do it fast?
See this similar question on the GIS Stack site. The performance of your ultimate solution will depend on how many targets are in the reference table you are searching and if you can limit the distance you are interested in (such as closest 5 within 30 miles). I don't think you can reliably optimize the process; you need to calculate the distance for all coordinates in your reference table.
I would like to store thousands of latitude/longitude points in a MySQL db. I was successful at setting up the tables and adding the data using the geospatial extensions where the column 'coord' is a Point(lat, lng).
Problem:
I want to quickly find the 'N' closest entries to latitude 'X' degrees and longitude 'Y' degrees. Since the Distance() function has not yet been implemented, I used GLength() function to calculate the distance between (X,Y) and each of the entries, sorting by ascending distance, and limiting to 'N' results. The problem is that this is not calculating shortest distance with spherical geometry. Which means if Y = 179.9 degrees, the list of closest entries will only include longitudes of starting at 179.9 and decreasing even though closer entries exist with longitudes increasing from -179.9.
How does one typically handle the discontinuity in longitude when working with spherical geometries in databases? There has to be an easy solution to this, but I must just be searching for the wrong thing because I have not found anything helpful.
Should I just forget the GLength() function and create my own function for calculating angular separation? If I do this, will it still be fast and take advantage of the geospatial extensions?
Thanks!
josh
UPDATE:
This is exactly what I am describing above. However, it is only for SQL Server. Apparently SQL Server has a Geometry and Geography datatypes. The geography does exactly what I need. Is there something similar in MySQL?
How does one typically handle the discontinuity in longitude when working with spherical geometries in databases?
Not many people use MySQL for this, because it's geospatial extensions aren't really up to snuff.
From the docs:
"All calculations are done assuming Euclidean (planar) geometry."
The solution is usually to roll your own.
Alternatively, you can fake it -- if your distances are less than a 500 miles or so, then you can treat your latitude and longitude as rectangular coordinates and just use the euclidean distance formula (sqrt(a^2 + b^2)).
Does anyone know of a way to fetch all polygons in a MySQL db within a given distance from a point? The actual distance is not that important since it's calculated for each found polygon later, but it would be a huge optimization to just do that calculation for the polygons that are "close".
I've looked at the MBR and contains functions but the problem is that some of the polygons are not contained within a bounding box drawn around the point since they are very big, but some of their vertices are still close.
Any suggestions?
A slow version (without spatial indexes):
SELECT *
FROM mytable
WHERE MBRIntersects(mypolygon, LineString(Point(#X - #distance, #Y - #distance), Point(#X + #distance, #Y + #distance))
To make use of the spatial indexes, you need to denormalize your table so that each polygon vertex is stored in its own record.
Then create the SPATIAL INDEX on the field which contains the coordinates of the vertices and just issue this query:
SELECT DISTINCT polygon_id
FROM vertices
WHERE MBRContains(vertex, LineString(Point(#X - #distance, #Y - #distance), Point(#X + #distance, #Y + #distance))
The things will be much more easy if you store UTM coordinates in your database rather than latitude and longitude.
I don't think there's a single answer to this. It's generally a question of how to organize your data so that it makes use of the spacial locality inherent to your problem.
The first idea that pops into my head would be to use a grid, assign each point to a square, and check select the square the point is in, and those around it. If we're talking infinite grids, then use a hash-value of the square, this would give you more points than needed (where you have collisions), but will still reduce the amount by a bunch. Of course this isn't immediately applicable to polygons, it's just a brainstorm. A possible approach that might yield too many collisions would be to OR all hashed values together and select all entries where the hashes ANDed with that value is non-zero (not sure if this is possible in MySQL), you might want to use a large amount of bits though.
The problem with this approach is, assuming we're talking spherical coordinates (lat, long generally does) are the singularities, as the grid 'squares' grow narrower as you approach the poles. The easy approach to this is... don't put any points close to the poles... :)
Create a bounding box for all of the polygons and (optionally storing these results in the database will make this a lot faster for complex polygons). You can then compare the bounding box for each polygon with the one round the point at the desired size. Select all the polygons which have intersecting bounding boxes.
I have 2063 locations stored in a mysql table. In one of my processes I need to exclude certain results based on how far away they are from a given point of origin. The problem is, I will need to filter a couple of hundred, maybe a couple of thousand results at a time.
So what would be the best way to do the distance math. Should I do it at run time
1. Find all points connecting to my point of origin
2. loops through the connecting points
3. calculate the distance between the point of origin and the connecting point
4. exclude the connecting point if the distance if too great
or should I create a look up table with the distances between each and every point already figured out. I can avoid duplicate rows since the distance between p1 and p2 would be the same as the distance between p2 and p1, but that would still result in a couple of million rows in the table.
Or.. is there an even better way of doing it?
You could use MySQL's spatial extensions to calculate the distance and even create an R-tree index on the data to optimize the lookup of point within some range.
See the docs for MySQL spatial extensions for details:
http://dev.mysql.com/doc/refman/5.1-maria/en/spatial-extensions.html
How about this:
1. Loop through all points:
2. If abs(a-b) < distance && abs(a-b) < distance then:
3. Do the fancy distance calculation between a and b.
I.e. assuming most points will be outside the "box" defined by the distance you are interested in, you can filter out most points very quickly with step 2 and only calculate the real distance for a much smaller number of points.
Since your data is in a mysql table, you really want a solution that SQL will be able to help you with.
I will assume that each location has an x and y coordinate. Store these as separate entries in the table.
You can quickly narrow your field of search to a box centered on your point of interest.
eg
WHERE X > (MyPosX - Range) AND X < MyPosX + Range)
AND Y > (MyPosY - Range) AND Y < MyPosY + Range)
Once you have a smaller set of items that are likely to be in range, you can use a more iterative approach
Edit: Avoid square root calculations when working out the actual distances though, as these are expensive. eg instead of
sqrt(x*x + y*y) < distance
try
(x*x + y*y) < distance*distance
// distance*distance is a constant and can be calculated once