I am working on an app that have over 2 millions of user. It is going to introduce location based feature. From the very beginning we want to provide the user a location based notification which will be changed based on their location/region. I am using PostGIS and Mapbox technologies. I have a custom polygon which is the indicator of different region. I know I can use a ST_Within of PostGIS to get the polygon info by sending longitude and latitude to server everytime. I am using the folloing function to get the region
CREATE OR REPLACE FUNCTION getRegion(getlng numeric, getlat numeric, OUT outregion text)
as $$
BEGIN
SELECT region into outregion
FROM mypolygon
WHERE ST_Within(
ST_GeometryFromText(
'POINT('|| getlng ||' '|| getlat ||')', 4326
),
geom);
END; $$
LANGUAGE PLPGSQL;
and calling the function by
SELECT getRegion(getlng, getlat);
But as there are millions of user it will increase the load on database server and need to be increased the TPS. Is there any other way to get the polygon/region from point beside using postgis directly? The region polygon is changable, not constant.
There is a method called ray-casting and recently mapbox is supporting query withing vector tiles. Is ray-casting or query within vector tiles will be a better approach for doing the same thing? (Again remember, the polygon is not constant.)
In a nutshell, I actually want to know the best practices using currently by the community to reduce the load on server and save time.
1) You will have to index your polygons using some grid (may be UTM, Google tiles or your own custom grid)
2) Identify grid of user location
3) Now fetch the polygons which lie on the same grid .In the best case you will get only single polygon and you will not have to use ST_Within.
4) Now if you get multiple polygons use ST_Within with only these polygons instead of the entire list of polygons
This Algo will save lot of memory and processing as ST_Within is a very heavy process.
Note: I have been using this approach from past 4 years and it has done wonders in terms of time and memory saving
Related
I have an ever increasing list of places identified by lat/long stored in my database. Now at the UI front there is a screen with a place auto-complete textbox means if I type a location there a drop down will appear with places and when I select the place the camera will move there. Also it is required that I display locations nearby (locations as stored in my database). Now the question is how to do this? I can use
SphericalUtil.computeDistanceBetween()
But the problem is I can't fetch all lat/long from my database and calculate distance without hampering performance.
You would need to compute the distances in your database. There are two basic options:
Implement your own distance method in your database:
If your positions are close to each other and close to the test lat/lng you can use Pythagoras's theorem (a ver basic approach that will not be correct in all the cases)
To address all the possible cases you can implement yor own haversine formula (the haversine formula gives great-circle distances between two points on a sphere from their longitudes and latitudes and is used to compute distances in the SphericalUtil.computeDistanceBetween() method).
Use a GIS database. You can use SpatiaLite for Android and use the ST_Distance function to filter your positions:
SELECT *
FROM yourtable
WHERE ST_DISTANCE(Geometry, MakePoint(yourXcoordinate, yourYcoordinate)) < yourdistance
I'm using Graphhopper as a routing service for my Android project and I want to know how can I extract street data (as a polygon) from *.osm.pbf format?
Later I want to use that data so that I could detect if user is within boundaries of that street.
Edit:
I've used Osmosis as it was referenced in this answer (selecting highways) but when I try to investigate xml after extraction I still don't understand how can I get a particular street since there still are some other objects left (like houses, bus stops).
Well I guess here are a few misunderstandings, so I go trough your wishes step by step:
OSM street data
What grasshopper uses aren't street polygones (closed shapes) nor simple street lineshapes. It processes pure OSM data and creates a so called routing-graph presentation. Here are a few informations about the import process itself: https://github.com/graphhopper/graphhopper/wiki/World-Wide-Road-Network
User position on road
This is called reverse geocoding and has different requirements on the indexing structures and models. OSM offers Nominatim as a solution to query like (lat, lon) -> OSM object. Your idea with a spatial buffer is even possible but creates a lot of overhead (here: memory) to preprocess your roadnetwork or doing it on demand for a particular area.
Street data is stored in GraphHopper. You could traverse the full graph e.g. via extending XFirstSearch and then do on checkAdjacent:
boolean checkAdjacent( EdgeIterator iter ) {
PointList pl = iter.fetchGeometry(3);
String name = iter.getName();
}
If you want to get an edge from a location for the "fence-use-case" you can have a look into LocationIndexTree.
Some clarifications:
Routing graphs usually don't contain spatial informations
The routing graph itself does not need this data but still we need this data to display the route etc.
Is there a way then to add weight to a node during the calculation
As explained on the mailing list.
I have a local database with over 2000 locations that I am trying to search through based on the users location. I only want to display a few markers in the Map Fragment nearby the user, but have so far been unable to find a way to do it.
Currently the database is in the form of a csv file, so I can change it to a different type easily. But I was waiting to do so until I could find a utility that can search the coordinates based on a radius around the user. Anybody have any suggestions?
You can define a LatLngBounds object for some box around the user, and then use bounds.contains(LatLng) to determine which of your locations are in that radius. I've used this method for collections of about the same size as yours and it was fast enough for our purposes. You will be searching a rectangle, not a radius, but since the map is a rectangle, maybe that makes more sense anyway?
This is a tricky topic and solution is not straight forward. I am briefly listing down the steps I have used and this works for well over 100k assets in my case.
Assuming you already have logic to get your current location and lets call if as myLocation.
Add your location data in sqlite file and treat location coordinates as nothing more than float.
Use offset as 0.001 which is roughly around 100 m and use the following in the query.
(myTable.lat > (myLocation.lat - offset) AND myTable.lat < (myLocation.lat + offset)) AND
(myTable.lon > (myLocation.lon - offset) AND myTable.lon < (myLocation.lon + offset))
This should give you the list of assets within a small radius
The trick here is to treat location as float and not really location.
For Offset: http://en.wikipedia.org/wiki/Decimal_degrees
I have some locations (lat & long) and I need to show these locations in a listview. I can do this perfectly.
But now I want to show the locations that are ahead of my current location. That means I want to skip the locations that I have already passed during my driving.
Let me clarify more clearly. we have locations like loc1 (lat,lon) , loc2(lat,lon), loc3(lat,lon).. loc100 (lat,lon). during my driving I like to see the locations (loc1 - loc100). But now I want to hide the locations (between loc1 to loc100) which I have passed from my current position/location. Say, I have passed loc1, loc3, loc5 so I need to skip these 3 locations from my listing in listview. To achieve this, I need to know which locations (loc1 - loc100) are behind my current location (gps current location) so that I can skip that locations.
Any idea? how i can achieve this in my code? Please help regarding this.
I would have two data structures (e.g., LinkedList) of Location objects:
unvisitedLocations
visitedLocations
Your list being shown to the user would be based on the contents of the unvisitedLocations data structure.
Based on your real-time location, you will need to detect proximity to each of the Location objects in the unvisitedLocations data structure based on given radius threshold value that you choose. To do this, you can either register each location with the LocationManager.addProximityAlert() methods (which will fire a PendingIntent when detecting proximity), or loop through the unvisitedLocations data structure and do this on your own - something like:
if(currentLocation.distanceTo(unvisitedLocations[i]) < threshold){
visitedLocations.add(unvisitedLocations[i]);
unvisitedLocations.remove(i);
}
This will give you the list of currently visited and unvisitedLocations based on your real-time locations.
Note that as initial size of the unvisitedLocations grows, performance will become an issue since you'd be looping through the entire data structure contents to determine proximity of location for each real-time location update, which can be once per second from GPS. If performance becomes an issue, you should look into moving the proximity detection server-side and using a spatial database, which has special data structures to make proximity detection far less intensive.
According to various references, Google Maps has a query param called sll which does the following:
Latitude,longitude of the point from which the business search
should be performed. You could use this to perform an off-centre
busness search. Google use it so "link to this page" can record a map
that has had the centre moved after performing a business search. When
requesting a route
map.getBounds().getSouthWest().toUrlValue() returns the
same value maps.google.com uses.
So, for instance, if (43.464258, -80.52041) happens to be in Waterloo, Ontario, and (42.24370, -82.98320) happens to be in Windsor, Ontario (many hundreds of kilometers away), then my interpretation of the above documentation would be that the following query:
https://maps.google.ca/maps?saddr=43.464258,-80.52041&daddr=mcdonalds&sll=42.24370,-82.98320
will do a search for "Mcdonalds" from Waterloo, to some McDonald's in Windsor.
Unfortunately, that's not what happens (click for yourself to see!). It ends up doing a search from the saddr point, to the nearest McDonald's to that point. The value of sll doesn't factor into it at all.
But here's where it gets weird! If I omit the sll parameter entirely, then Maps does something completely unexpected: it picks some random McDonald's in Toronto (a city that is many kilometers away from either Waterloo or Windsor). I need to add some sll parameter (for any value) to make Maps return a result in Waterloo (even though what I'm asking for is a result in Windsor).
Am I misinterpreting all the various sources of documentation about this parameter? Is this a bug on Maps' end? And, most importantly, is there any working way to do what I'm trying to do, even if it doesn't involve the sll parameter at all?
I can get it to work with a simple query :
from:43.464258,-80.52041 to:mcdonalds near 42.24370,-82.98320
Which gives the expected result. It won't work without near which is a keyword.
You can also search from:43.464258,-80.52041 to:mcdonalds, Windsor if you have the city name.
About the sll (and sspn) parameters, it doesn't work for directions AFAIK. It only works with searches for a single location.