I have an app that displays recent jobs on a map as pinpoints using Leafletjs.
With Leafletjs, when you want to zoom to the user's detected location, you call something like:
map.locate({'setView' : true, 'timeout' : 10000, maxZoom: 10});
However, for some locations, the zoom level 10 does not contain any job points, so I'd like to dynamically set the zoom so that at least on job is visible to the users.
I know that I can listen for the locate function's success and then check with something like:
map.on('locationfound', function() {
//for marker in markers{
//is point within currently visible bounds
//break on first positive
//else,
//zoom up a level, repeat previous checks
}
}
but that's quite inefficient, especially if I have a large number of points.
Does Leaflet have any built in functions/methods to provide information about layers within the current map view?
If you do some things on the server side, you can probably do the calculations fast enough.
Store the locations in pixel coordinates in your database at some way-zoomed-in zoom level (I use zoom level 23). I call this coordinate system "Vast Coordinate System". Then, to get the tile coordinates for a point at a specific location is IIRC one bitwise shift -- very fast, and something you can do in SQL.
Convert your users' location to pixel coords at that way-zoomed in level.
Iterate on zoom level. Get the tile coord for the user's location at that zoom level, then do an SQL query which counts the number of points on that tile. If > 0, stop.
Your SQL will be something like (sorry, I'm being lazy and doing it from memory/thinking instead of actually trying it out)
SELECT count(*) WHERE (vcsX>>(zoom+8)==userX>>(zoom+8)) AND (vcsY>>(zoom+8)==userY>>(zoom+8));
where vcsX and vcsY are the pixel coordinates in Vast Coordinate System.
Related
My Codename One app features a MapContainer. I need to show points of interest (POIs) on it which coordinates reside on the server. There can be hundreds (maybe thousands in the future) of such POIs on the server. That's why I would like to only download from the server the POIs that can be shown on the map. Consequently I need to get the map boundaries to pass them to the server.
I read this for Android and this other SO question for iOS and the key seems to get the map Projection and the map bounding box. However the getProjection() method or the getBoundingBox() seem not to be exposed.
A solution could be to mix the coordinates from getCameraLocation() which is the map center and getZoom() to infer those boundaries. But it may vary depending on the device (see the shown area can be larger).
How can get the map boundaries in Codename one ?
Any help appreciated,
Cheers,
The problem is in the javadocs for getCoordAtPosition(). This will be corrected. getCoordAtPosition() expects absolute coordinates, not relative.
E.g
Coord NE = currentMap.getCoordAtPosition(currentMap.getWidth(), 0);
Coord SW = currentMap.getCoordAtPosition(0, currentMap.getHeight());
Should be
Coord NE = currentMap.getCoordAtPosition(currentMap.getAbsoluteX() + currentMap.getWidth(), currentMap.getAbsoluteY());
Coord SW = currentMap.getCoordAtPosition(currentMap.getAbsoluteX(), currentMap.getAbsoluteY() + currentMap.getHeight());
I tried this out on the coordinates that you provided and it returns valid results.
EDIT March 21, 2017 : It turns out that some of the platforms expected relative coordinates, and others expected absolute coordinates. I have had to standardize it, and I have chosen to use relative coordinates across all platforms to be consistent with the Javadocs. So your first attempt:
Coord NE = currentMap.getCoordAtPosition(currentMap.getWidth(), 0);
Coord SW = currentMap.getCoordAtPosition(0, currentMap.getHeight());
Will now work in the latest version of the library.
I have also added another method : getBoundingBox() that will get the bounding box for you without worrying about relative/absolute coordinates.
This is probably something that can be exposed easily by forking the project and providing a pull request. We're currently working on updating the map component so this is a good time to make changes and add features.
Even though markers are being groups into clusters, there are still a large of markers that arent included.
i've gone through the options but cannot figure out a way to ... increase the area in which markers get included into the cluster.
You should be able to address this issue by increasing the gridSize option from its default 60 pixels to a higher value when instantiating your MarkerClusterer.
For example, the following instantiation code changes the grid square size of a cluster up from 60 pixels to 120 pixels:
var mc = new MarkerClusterer(map, markers, {
gridSize: 120
});
This should result in a larger cluster catchment area and fewer individual markers.
If not, I'd recommend checking that all of your markers are being included in the clustering process.
The other options you could check are the maxZoom and minimumClusterSize settings. Whilst the following defaults for these options are intended to keenly cluster your markers, if you've adjusted these defaults you may have inadvertently reduced the degree of clustering:
maxZoom: The maximum zoom level at which clustering is enabled or null if
clustering is to be enabled at all zoom levels. The default value is
null.
minimumClusterSize: The minimum number of markers needed in a cluster before the markers are hidden and a cluster marker appears. The default value is 2.
I have trouble getting Map behave properly when calling ZoomToResolution and PanTo
I need to be able to Zoom into specific coordinate and center map.
The only way I got it working is by removing animations:
this.MapControl.ZoomDuration = new TimeSpan(0);
this.MapControl.PanDuration = new TimeSpan(0);
Otherwise if I make call like this:
control.MapControl.ZoomToResolution(ZoomLevel);
control.MapControl.PanTo(MapPoint());
It does one or another (i.e. pan or zoom, but not both). If (after animation) I call this code second time (map already zoomed or panned to needed position/level) - it does second part.
Tried this:
control.MapControl.ZoomToResolution(ZoomLevel, MapPoint());
Same issue, internally it calls above commands
So, my only workaround right now is to set Zoom/Pan duration to 0. And it makes for bad UX when using mouse.
I also tried something like this:
this.MapControl.ZoomDuration = new TimeSpan(0);
this.MapControl.PanDuration = new TimeSpan(0);
control.MapControl.ZoomToResolution(ZoomLevel);
control.MapControl.PanTo(MapPoint());
this.MapControl.ZoomDuration = new TimeSpan(750);
this.MapControl.PanDuration = new TimeSpan(750);
Which seems to be working, but then mouse interaction becomes "crazy". Mouse scroll will make map jump and zoom to random places.
Is there known solution?
The problem is the second operation replaces the previous one. You would have to wait for one to complete before starting the next one. But that probably doesn't give the effect you want.
Instead zoom to an extent, and you'll get the desired behavior. If you don't have the extent but only center and resolution, you can create one using the following:
var zoomToExtent = new Envelope(point.X - resolution * MapControl.ActualWidth/2, point.Y, point.X + resolution * MapControl.ActualWidth/2, point.Y);
Btw it's a little confusing in your code that you call your resolution "ZoomLevel". I assume this is a map resolution, and not a level number right? The esri map control doesn't deal with service-specific levels, but is agnostic to the data's levels and uses a more generic "units per pixels" resolution value.
I'm using PostGIS on ruby/rails, and have created a simple box-like polygon under which I wish to search for land parcels in a county. The st_overlaps tool has worked for this before and it has worked this time, sort of.
So I created the polygon to search for parcels (multi-polygons, as it turns out) underneath it
factory = RGeo::Cartesian.factory
coords = [[1554780, 1101102], [1561921, 1062647], [1634713, 1097531], [1630867, 1140657]]
points = coords.map { |pair| RGeo::WKRep::WKTParser.new.parse("POINT (#{pair.first} #{pair.last})") }
ring = factory.linear_ring(points)
polygon = factory.polygon(ring)
After running the active record call:
Parcel.where{st_overlaps(:parcel_multipolygon, polygon)}
I get 157 results. Far less than expected. I exported them a kml file using a custom script of mine. I will upload it soon for viewing.
What you'll see in that kml once loaded in Google Earth, is a parallelogram of pins marking parcels whose areas (polygons) are clearly saddling the outer ring of the parameter-polygon I created to search under. There are so many parcels along these invisible lines in such a clear, distinct shape, the fact that there are no pins in the middle of the shape clearly indicate that the search results were only at the overlappings of parcel multipolygons with the exterior edges (LinearRing) of the search polygon.
Based on my re-reading of the documentation for st_overlaps, I'm left puzzled as to what seems to be the problem here.
Here's a link to view the kmz export. (coordinates converted to geographic before export). You can view it in your browser. The search-polygon itself is not included, but its easy to see where its exterior ring is
https://docs.google.com/file/d/0B5inC0VAuhH1TXdTbWQ2RngxZk0/edit?usp=sharing
I think it is behaving as expected. St_overlaps will give features that actually lie on top of each other. If you want all features inside the polygon try ST_Intersects.
The sensor module in my project consists of a rotating camera, that collects noisy information about moving objects in the surrounding environment.
The information consists of distance, angle and relative change of the moving objects..
The limiting view range of the camera makes it essential to rotate the camera periodically to update environment information...
I was looking for algorithms / ways to model these information, in order to be able to guess / predict / learn motion properties of these object..
My current proposed idea is to store last n snapshots of each object in a queue. I take weighted average of positions and velocities of moving object, but I think it is a poor method...
Can you state some titles that suit this case?
Thanks
Kalman {Extended, unscented, ... } filters and particle filters only after reading about Kalman filters.
Kalman filters learn and predict the correct data from noisy data with a Gaussian assumption, so it may be of use to you. If you need non-Gaussian methods, look at the particle filter.