I'm thinking of using my map coordinates to allow for location based searching and I don't know where to start.
I have a database of coordidinates - When I enter a suburb, I want to display all matches within a given radius. (i.e. search database of long/lat coords and return all coords that are in an x radius of long/lat of suburb searched)
I'm not sure how to achieve this or where to start?
Well it really depends on what database you are using.
the general technique is to use a scaler value function that uses a formula such as:
distance = ACOS(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(lon2-lon1))*6371
then you can write a query like:
select *
from locations
where mydistancefunction(lat1,lng1,locations.lat,locations.lng) < #radius
Are you aware of mysql spatial extensions?Try to create a spatial column in your table i.e. Point and then use the functions that spatial extensions offer so you don't reinvent the wheel
Related
I have a database table with POI's that i want to connect with a record in my Geo table (containing cities, countries).
Within the POI table i have a Lat & Lon field.
Within the Geo table i have 4 coordinates, for West/East and North/South
I'm using Laravel 5 / Eloquent and Mysql. The coordinates are stored as a decimal (11,8). I can add multiple columns if needed.
How can i check if a POI is located within those 4 coordinates?
Mysql supports spatial data types and functions that were designed to make such calculations easy.
Define your POIs as POINT and your rectangle as GEOMETRY. Use the ST_Contains() function to test whether the point is within the rectangle:
select * from yourtable
where st_contains(rectangle_field, point_field)
As far as I know, Laravel does not directly support these daya types and functions, so you have to resort to raw sql.
I'm going to build an app where the users can see points of interest in a predefined radius around their location.
My first idea was to store the latitude and longitude of all POI's in a database and comparing the users location with the POI's location via SQL.
The problem is the performance I think. If there are thousands of POI's and thousands of user requests with their location, it wouldn't be very economically or is this no problem for todays servers?
My next approach was to divide the map in quadrants, and only observing the surrounding quadrants.
tl;dr:
All in all I'm looking for:
a way to do an radius search
at best caching the results for other users
the cache will be updated when a new POI is being registered.
If you have any ideas how to realize something like that, please let me know.
Thank you
Fabian
I think what you are looking for is the Harversine formula, which it allows you to find the distance between two points in a sphere (in this case the Earth). An implementation using SQL would be something like this:
ACOS (
SIN(RADIANS($latitude)) *
SIN(RADIANS(T.latitude))+
COS(RADIANS($latitude)) *
COS(RADIANS(T.latitude))*
COS(RADIANS($longitude-T.longitud)))*6378.137 AS distance
Adding this to the select of your query will return a column called distance calculating (in Km) how far is the point ($latitude,$longitude), normally the user, from (T.latitude,T.longitude), normally the element of the table.
In case you want to filter, and don't show elements further than a certain distance you can make a condition like:
HAVING distance<$radius
I imagine that you are using MySQL, if this is the case you have to use HAVING instead of WHERE to make a condition over a computed column (distance).
A complete example of a query would be like this:
SELECT T.*, ACOS (
SIN(RADIANS($latitude)) *
SIN(RADIANS(T.latitude))+
COS(RADIANS($latitude)) *
COS(RADIANS(T.latitude))*
COS(RADIANS($longitude-T.longitud)))*6378.137 AS distance
FROM your_table as T
HAVING distance < $radius
ORDER BY distance LIMIT $limit
If you want to optimize a bit more the performance add a limit to the query so you will have for example the 10 nearest places.
Take your time to consider Spatial data types aswell since they were specificly made for this kind of work.
Note that I do not recommend you to insert your php variables directly into your query, is really unsecure, I did that only as an example.
Hope this helps you.
I would like to implement a search by distance on a website.
There must be a user in a living city can find all users living within 100 or 200 km for example.
I have a table in my database that stores all the cities and their coordinates.
I thought to create another table that would store the distance between all cities but my data base contains 36,000 cities and it may make a lot of records ...
How could I make this search more simply knowing that my project will be developed with Symfony and Doctrine?
Thank you beforehand
You can use the correct answer here to determine the distance between co-ordinates.
Measuring the distance between two coordinates in PHP
For performance reasons you need to use geospatial index to efficiently query such a database. For example MongoDB has a feature for this.
If performance is not an issue you can simply store locations in relational database table and calculate distances in SQL. See this question for some information about this solution: Geo-Search (Distance) in PHP/MySQL (Performance)
I've done some reading so far and I am at a crossroads.
My situation is this:
Table with a list of lat/lng values ( we can take these to be "cities" ) with a radius
Table with a list of movement values, including a lat/lng
My requirement is that I return the list of movements and include the nearest city (if it's within the radius). I've so far used the haversine formula in PHP to do this for each record I return but it's not particularly efficient.
My two options I've found is either to:
1/ create a stored procedure in MySQL to do the Haversine that side (something like this: Proximity Search )
2/ use a "bounding box" method of positioning the cities instead of a circle. This is not a big problem and would allow the sql to be simplified. However, in some cases the typical logic of determining whether the point lies between the top left and bottom right will not work if the lat and lng are in negatives. In PHP, to work around this, I would do a quick "if" where I'd check if the top-left lat/lng is greater than the bottom-right and use AND/OR depending on the result.
After some extra reading I found this question here on SO.
https://stackoverflow.com/a/5548877/1749630
This answer was exactly what I needed to point me in the right direction. In this way I am now using a sub-select in order to find the city.
If someone posts a better answer than this one I'll mark that instead of this one :)
I'm out of my element here so please forgive me if I dont ask this correctly/clearly.
I have a table of users with lat/long for each one.
I get a query from a federal agency that provides either a polygon or a circle like this:
<polygon>38.47,-120.14 38.34,-119.95 38.52,-119.74 38.62,-119.89 38.47,-120.14</polygon>
<circle>32.9525,-115.5527 0</circle>
Given either of these two inputs, I need to return all users within the polygon or circle.
I've looked all over, read all the mysql spatial docs etc. and I am either missing a step or just not grokking the query method.
ANY help would be appreciated!
Have you read http://howto-use-mysql-spatial-ext.blogspot.com/ ?
This is the answer that I came up with and appears to be working:
First, I altered the table by adding a field to hold the spatial points created from the users lat/lon:
ALTER TABLE users ADD location POINT NOT NULL;
UPDATE users set location = PointFromText(CONCAT('POINT(',lat,' ',lon,')'))
CREATE SPATIAL INDEX location ON users(location);
From there, I'm using this to query to find the users within the polygon:
SET #bbox = 'POLYGON((38.47,-120.14 38.34,-119.95 38.52,-119.74 38.62,-119.89 38.47,-120.14))';
SELECT * , AsText( location )
FROM users
WHERE Intersects( location, GeomFromText( #bbox ) ) ;
For new users I created a trigger to update the location from the lat/lon (user can't be added without a lat\lon):
DROP TRIGGER IF EXISTS `users_insert_defaults`;
DELIMITER //
CREATE TRIGGER `users_insert_defaults` BEFORE INSERT ON `users`
FOR EACH ROW SET NEW.location = PointFromText(CONCAT('POINT(',NEW.lat,' ',NEW.lon,')'))
//
DELIMITER ;
For a circle, you would need to compute the distance from the circle center to each of the lat/lon's in your persons list. If the distance is less than the radius of the circle, that person is inside the circle. Typical formula for computing distances between 2 lat/lon's along the 'great circle' is called the haversine formula. The website below shows this formula in javascript.
http://www.movable-type.co.uk/scripts/latlong.html
For a general polygon, this is much harder.
For general point in a polygon, the Point Inclusion Test seems to work assuming a trivial Equirectanglular projection (x = lon, y = lat).