I am developing an android mapping app using OSMDroid. I am attempting to use free custom aerial imagery, completely independent of google and/or bing api's. Please, do not propose ANY solution that uses their mapping api's.
I have managed to display satellite imagery by including this code:
mapView.setTileSource(TileSourceFactory.MAPQUESTAERIAL);
BUT, tile server does not offer tiling above 11 zoom and i need to get wee closer than that (say 15-16?).
Using ARCGis tile server, I manage to display satellite imagery even to 16 layer zoom level, but tiles are shuffled around.
mapControl = (MapController) mapView.getController();
mapControl.setZoom(11);
String[] urlArray = {"http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/"};
mapView.setTileSource(new XYTileSource("ArcGisOnline", null, 0, 18, 256, ".png",urlArray ));
Basemap tiles are shuffled and do not correspond to lat/lon, but overlay is ok.
The tile server probably uses a different scheme for retrieving tiles. Try flipping the X and Y coordinates. Slippy map servers (osm) use the Z/X/Y.ext format. ArgGis and several others use Z/Y/X.ext format. All other coordinates are the same. This means the solution is simple, override the getTileURLString method and supply the coordinates in whatever format the server wants.
Osmdroid has an example for doing exactly this.
https://github.com/osmdroid/osmdroid/blob/master/OpenStreetMapViewer/src/main/java/org/osmdroid/samplefragments/SampleCustomTileSource.java
The relevant bit a code this
mMapView.setTileSource(new OnlineTileSourceBase("USGS Topo", 0, 18, 256, "",
new String[] { "http://basemap.nationalmap.gov/ArcGIS/rest/services/USGSTopo/MapServer/tile/" }) {
#Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + aTile.getZoomLevel() + "/" + aTile.getY() + "/" + aTile.getX()
+ mImageFilenameEnding;
}
});
You'll also want to purge the cache after this change since it has the wrong coordinates
Related
I'm developing a App which display a Google map and a bunch of markers on it. There's a lot of markers so I divided them in smaller groups and display only those, which are in some bounds depending on the current position of the camera.
To do that I'm using the GoogleMap.OnCameraIdleListener. First I remove the listener, do my calculations and drawing and then I restore the listener to the Fragment containing my map:
#Override
public void onCameraIdle() {
mMap.setOnCameraIdleListener(null);
clearMap();
findTheMarkersInBounds();
displayTheMarkers();
mMap.setOnCameraIdleListener(this);
}
This way I only draw the markers I need to display and the performance is way better then having 1000 markers on the map at once. I also draw about the same number of polylines but that's not the point now.
For some strange reasons, after some panning and zooming the maps doesn't respond anymore. Can't zoom it nor pan it. App displays a dialog that it is not responding and I should wait or close the app. No erros are displayed in logcat. I can't exactly tell when this happens. Sometimes after the first pan, sometimes I can move around 2-3 minutes. Same thing happens on the emulator and on the physical device.
Anyone experienced something like this? Thanks!
Or am I approaching this the wrong way? How else should I optimize the map to display about 1000 markers and polylines. (The markers have text on them, so it can't be the same Bitmap and all of the polylines can have different colors and need to be clickable, so I can't combine them into one large polyline)
EDIT. A little more info about my methods:
After all the marker positions are loaded from the internal database, I do a for-loop through all of them and based on their position and I place them to the corresponding region. Its an 2D array of lists.
My whole area is divided to 32x32 smaller rectangular areas. When I'm searching for the markers to display, I determine which region is in view and display only those markers, which are in this area.
This way I don't need to loop over all of the markers.
My methods (very simplified) look like this:
ArrayList<MarkerObject> markersToDisplay = new ArrayList<MarkerObject>();
private void findTheMarkersInBounds() {
markersToDisplay.clear();
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
int[] regionCoordinates = getRegionCoordinates(bounds); // i, j coordinates of my regions [0..31][0..31]
markersToDisplay.addAll(subdividedMarkers[regionCoordinates[0]][regionCoordinates[1]]);
}
private void drawMarkers() {
if ((markersToDisplay != null) && (markersToDisplay.size() > 0)) {
for (int i=0; i<markersToDisplay.size(); i++) {
MarkerObject mo = markersToDisplay.get(i);
LatLng position = new LatLng(mo.gpsLat, mo.gpsLon);
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(createMarker(getContext(), mo.title));
GroundOverlay m = mMap.addGroundOverlay(groundOverlayOptions.image(bitmapDescriptor).position(position, 75));
m.setClickable(true);
}
}
}
It is hard to help you without source code of findTheMarkersInBounds() and displayTheMarkers(), but seems, you need different approach to increase performance, for example:
improve your findTheMarkersInBounds() logic if it possible;
runfindTheMarkersInBounds() in separate thread and show not all markers in same time, but one by one (or bunch of 10..20 at one time) during findTheMarkersInBounds() searching;
improve your displayTheMarkers() if it possible, actually may be use custom drawing on canvas (like in this answer) instead of creating thousands Marker objects.
For question updates:
Small improvements (first, because they are used for main):
pass approximately max size of markersToDisplay as constructor parameter:
ArrayList<MarkerObject> markersToDisplay = new ArrayList<MarkerObject>(1000);
Instead for (int i=0; i<markersToDisplay.size(); i++) {
use for (MarkerObject mo: markersToDisplay) {
Do not create LatLng position every time, create it once and store in MarkerObject fields.
Main improvement:
This lines are the source of issues:
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(createMarker(getContext(), mo.title));
GroundOverlay m = mMap.addGroundOverlay(groundOverlayOptions.image(bitmapDescriptor).position(position, 75));
IMHO using Ground Overlays for thousands of markers showing is bad idea. Ground Overlay is for several "user" maps showing over default Google Map (like local plan of Park or Zoo details). Use custom drawing on canvas like on link above. But if you decide to use Ground Overlays - do not recreate them every time: create it once, store references to them in MarkerObject and reuse:
// once when marker created (just example)
mo.overlayOptions = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(createMarker(getContext(), mo.title)))
.position(mo.position, 75))
.setClickable(true);
...
// in your drawMarkers() - just add:
...
for (MarkerObject mo: markersToDisplay) {
if (mo.overlayOptions == null) {
mo.overlayOptions = createOverlayOptionsForThisMarker();
}
mMap.addGroundOverlay(mo.overlayOptions)
}
But IMHO - get rid of thousands of Ground Overlays at all - use custom drawing on canvas.
After further investigation and communication with the google maps android tech support we came to a solution. There's a bug in the GroundOverlay.setZIndex() method.
All you have to do is to update to the newest API version. The bug is not present anymore in Google Maps SDK v3.1.
At this moment it is in Beta, but the migration is pretty straightforward.
I am really new in this routing and maps area. I have a basic, maybe stupid, question. I use osmdroid to show a tile from a URL that looks like this
http://tile01-cdn.maptoolkit.net/terrain/15/17789/11515.png
Where 15 represents the zoom,
17789 the X value and
11515 the Y value
Now when I want to use osmdroid to show this tile in the map I don't know what kind of TileSource should I use. The most obvious is the XYTileSource but the constructor does not have any x y parameters to pass, but I see on the internet a lot of questions/answers where people use the same object but with a different constructor. I am guessing here that the code has changed in the lib. The current constructor:
XYTileSource(String aName, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding, String[] aBaseUrl)
So my question is how can I show this tile map of mine in the osmdroid map, what kind of ITileSource should I use? Should I implement my own custom one?
this is how I tried to do it:
final ITileSource tileSource = new XYTileSource("Maverik", 15, 17789, 11515, ".png", new String[] {"http://tile01-cdn.maptoolkit.net/terrain/"});
tileProvider.setTileSource(tileSource);
and I get an empty MapView.
Purpose of osmdroid is to display world map - with a lot of tiles. And to display the appropriate tiles depending on where the "map view" is centered (this center being defined with: a latitude, a longitude, and a zoom level).
If this is also what you want:
1) As examples, look at default tile sources included in osmdroid, in TileSourceFactory
2) Then you could try something like:
OnlineTileSourceBase tileSource = new XYTileSource("Maverik",
0, 17,
256, ".png",
new String[] {
"http://tile01-cdn.maptoolkit.net/terrain/",
"http://tile02-cdn.maptoolkit.net/terrain/",
"http://tile03-cdn.maptoolkit.net/terrain/"
});
mapView.setTileSource(tileSource);
You may also want ton consult the osmdroid wiki and the source for the sample application. There's tons of examples on how to use just about every tile source that we know of. We're also adding more as they are discovered.
https://github.com/osmdroid/osmdroid/wiki
You don't need to worry about X and Y coordinates. They actually aren't lat/lon coordinates but are grid references. Open Street Maps, and many other tile sources, use the same or similar tile coordinate system. Start with the world in one image. Zoom =1 divide it into 4 parts. That's your X,Y and Zoom coordinates. Zoom =2 level, divid the four tiles we started with into 4 again, and we have 16 tiles.
I'm developing an android app using google maps android sdk v2 and want to allow users to download maps and use them offline.
To display the tiles I use a custom TileProvider implementation as described here.
I need to know the URL to download a google maps tile (vector tile if possible) based on latitude, longitude and zoom parameters (e.g. something like this )
Before anyone comments that it's violating google maps' terms, I can tell you it's ok to download a small amount of tiles specifically for this use case (see section 10.5.d in their terms here).
This is the link
http://mt1.google.com/vt/lyrs=y&x=1325&y=3143&z=13
lyrs parameters are :
y = hybrid
s = satelite
t = train
m = map
By Overriding getTile in your TileProvider, You get the needed X and Y and Zoom. there is no need to do anything.
#Override
public Tile getTile(int x, int y, int zoom) {
// DO YOUR STUFF HERE
}
I use OpenStreetMap on a responsive Website and have some display issues.
The map is displayed very well on my Samsung S4 with Android.
The Map is not displayed on my iPad2 with OS5 or Sony Z with Android
I use
map = new OpenLayers.Map("basicMap");
var mapnik = new OpenLayers.Layer.OSM();
map.addLayer(mapnik);
I thought the error is here
map.setCenter(new OpenLayers.LonLat(3, 3) // Center of the map
.transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
new OpenLayers.Projection("EPSG:900913") // to Spherical Mercator Projection
), 15 // Zoom level
);
but the use of transform() without parameters was not successful.
any suggestions ?
I am working on custom map app and i want to use google map tiles for background ? There is one class TileProvider in api but i don't know how to initialize it every time i try it goes something like this ?
TileProvider tileProvider=new TileProvider() {
#Override
public Tile getTile(int i, int i2, int i3) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
};
how to override getTile function to get tiles from google map server?
Any example will be appreciated ?I know getTile function need x,y and zoom value to return tile.
So quick answer is that you can get the Google Map tiles from the following URL:
http://mt1.google.com/vt/lyrs={t}&x={x}&y={y}&z={z}
Where {t} is the type of map (satellite, road, hybrid, etc) and the other attributes are specifying the coordinates and zoom level.
The possible values for {t} are as follows:
Default - m
Roads only - h
Roads simplified - r
Satellite - s
Satellite hybrid - y
Terrain - t
Terrain hybrid - p
That being said you do want to make sure what you're doing is NOT a violation of the terms & services. Specifically Google WILL allow you to cache their tiles provided that you are doing so ONLY in order to improve performance and that you delete their tiles at least every 30 days, and finally you don't pull down their tiles in an attempt to make your own mapping service.
You may want to read the Google Maps Terms of Service - https://developers.google.com/maps/terms - specifically section 10.1.1