/** * adds another mapDataStore * * @param mapDataStore the mapDataStore to add * @param useStartZoomLevel if true, use the start zoom level of this mapDataStore as the start zoom level * @param useStartPosition if true, use the start position of this mapDataStore as the start position */ public void addMapDataStore(MapDataStore mapDataStore, boolean useStartZoomLevel, boolean useStartPosition) { if (this.mapDatabases.contains(mapDataStore)) { throw new IllegalArgumentException("Duplicate map database"); } this.mapDatabases.add(mapDataStore); if (useStartZoomLevel) { this.startZoomLevel = mapDataStore.startZoomLevel(); } if (useStartPosition) { this.startPosition = mapDataStore.startPosition(); } if (null == this.boundingBox) { this.boundingBox = mapDataStore.boundingBox(); } else { this.boundingBox = this.boundingBox.extendBoundingBox(mapDataStore.boundingBox()); } }
@Override public void close() { for (MapDataStore mdb : mapDatabases) { mdb.close(); } }
/** * Extracts substring of preferred language from multilingual string using * the preferredLanguage setting. */ protected String extractLocalized(String s) { return MapDataStore.extract(s, preferredLanguage); }
/** * Returns the timestamp of the data used to render a specific tile. * <p/> * If the tile uses data from multiple data stores, the most recent timestamp is returned. * * @param tile A tile. * @return the timestamp of the data used to render the tile */ @Override public long getDataTimestamp(Tile tile) { switch (this.dataPolicy) { case RETURN_FIRST: for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(tile)) { return mdb.getDataTimestamp(tile); } } return 0; case RETURN_ALL: case DEDUPLICATE: long result = 0; for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(tile)) { result = Math.max(result, mdb.getDataTimestamp(tile)); } } return result; } throw new IllegalStateException("Invalid data policy for multi map database"); }
private MapReadResult readLabels(Tile tile, boolean deduplicate) { MapReadResult mapReadResult = new MapReadResult(); for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(tile)) { MapReadResult result = mdb.readLabels(tile); if (result == null) { continue; } boolean isWater = mapReadResult.isWater & result.isWater; mapReadResult.isWater = isWater; mapReadResult.add(result, deduplicate); } } return mapReadResult; }
MapReadResult mapReadResult = this.mapDataStore.readMapData(rendererJob.tile); processReadMapData(renderContext, mapReadResult); renderContext.renderTheme.matchHillShadings(this, renderContext); bitmap = this.graphicFactory.createTileBitmap(rendererJob.tile.tileSize, rendererJob.hasAlpha); bitmap.setTimestamp(rendererJob.mapDataStore.getDataTimestamp(rendererJob.tile)); renderContext.canvasRasterer.setCanvasBitmap(bitmap); if (!rendererJob.hasAlpha && rendererJob.displayModel.getBackgroundColor() != renderContext.renderTheme.getMapBackground()) { Rectangle insideArea = this.mapDataStore.boundingBox().getPositionRelativeToTile(rendererJob.tile); if (!rendererJob.hasAlpha) { renderContext.canvasRasterer.fillOutsideAreas(renderContext.renderTheme.getMapBackgroundOutside(), insideArea);
private MapReadResult readMapData(Tile tile, boolean deduplicate) { MapReadResult mapReadResult = new MapReadResult(); for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(tile)) { MapReadResult result = mdb.readMapData(tile); if (result == null) { continue; } boolean isWater = mapReadResult.isWater & result.isWater; mapReadResult.isWater = isWater; mapReadResult.add(result, deduplicate); } } return mapReadResult; }
private MapReadResult readPoiData(Tile upperLeft, Tile lowerRight, boolean deduplicate) { MapReadResult mapReadResult = new MapReadResult(); for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(upperLeft)) { MapReadResult result = mdb.readPoiData(upperLeft, lowerRight); if (result == null) { continue; } boolean isWater = mapReadResult.isWater & result.isWater; mapReadResult.isWater = isWater; mapReadResult.add(result, deduplicate); } } return mapReadResult; }
public void setMapFile(final String mapFile) { if ((mapFile == null) || (mapFile.equals(mapFile_))) return; mapFile_ = mapFile; if (mapDatabase_ != null) mapDatabase_.close(); if (theme_ != null) theme_.decrementRefCount(); mapDatabase_ = new MapFile(new File(mapFile)); InMemoryTileCache tileCache = new InMemoryTileCache(2); mapGenerator_ = new DatabaseRenderer( mapDatabase_, AndroidGraphicFactory.INSTANCE, tileCache, new TileBasedLabelStore(tileCache.getCapacityFirstLevel()), true, true, null ); mapBounds_ = mapDatabase_.boundingBox(); final GraphicFactory gf = AndroidGraphicFactory.INSTANCE; final XmlRenderTheme theme = InternalRenderTheme.OSMARENDER; theme_ = new RenderThemeFuture(gf, theme, displayModel_); new Thread(theme_).start(); zoomBounds_ = -1; }
private BoundingBox getMapBoundingBox() { Collection<Layer> values = mapsToLayers.values(); if (!values.isEmpty()) { Layer layer = values.iterator().next(); if (layer instanceof TileRendererLayer) { TileRendererLayer tileRendererLayer = (TileRendererLayer) layer; return toBoundingBox(tileRendererLayer.getMapDataStore().boundingBox()); } } return null; }
/** * Extracts the initial position from the map file, falling back onto the value supplied * by getDefaultInitialPosition if there is no initial position coded into the map file. * You will only need to override this method if you do not want the initial position extracted * from the map file. * * @return the initial position encoded in the map file or a fallback value. */ protected MapPosition getInitialPosition() { MapDataStore mapFile = getMapFile(); if (mapFile.startPosition() != null) { Byte startZoomLevel = mapFile.startZoomLevel(); if (startZoomLevel == null) { // it is actually possible to have no start zoom level in the file startZoomLevel = new Byte((byte) 12); } return new MapPosition(mapFile.startPosition(), startZoomLevel); } else { return getDefaultInitialPosition(); } }
/** * Reads data for an area defined by the tile in the upper left and the tile in * the lower right corner. The default implementation combines the results from * all tiles, a possibly inefficient solution. * Precondition: upperLeft.tileX <= lowerRight.tileX && upperLeft.tileY <= lowerRight.tileY * * @param upperLeft tile that defines the upper left corner of the requested area. * @param lowerRight tile that defines the lower right corner of the requested area. * @return map data for the tile. */ public MapReadResult readLabels(Tile upperLeft, Tile lowerRight) { if (upperLeft.tileX > lowerRight.tileX || upperLeft.tileY > lowerRight.tileY) { new IllegalArgumentException("upperLeft tile must be above and left of lowerRight tile"); } MapReadResult result = new MapReadResult(); for (int x = upperLeft.tileX; x <= lowerRight.tileX; x++) { for (int y = upperLeft.tileY; y <= lowerRight.tileY; y++) { Tile current = new Tile(x, y, upperLeft.zoomLevel, upperLeft.tileSize); result.add(readLabels(current), false); } } return result; }
/** * @return the start point (may be null). */ public LatLong getStartPosition() { if (this.mapDataStore != null) { return this.mapDataStore.startPosition(); } return null; }
/** * @return the start zoom level (may be null). */ public Byte getStartZoomLevel() { if (this.mapDataStore != null && null != this.mapDataStore.startZoomLevel()) { return this.mapDataStore.startZoomLevel(); } return DEFAULT_START_ZOOM_LEVEL; }
/** * Reads only labels for tile. Labels are pois as well as ways that carry a name tag. * It is permissible for the MapDataStore to return more data. * This default implementation returns all map data, which is inefficient, but works. * * @param tile tile for which data is requested. * @return label data for the tile. */ public MapReadResult readLabels(Tile tile) { return readMapData(tile); }
@Override public boolean supportsTile(Tile tile) { for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(tile)) { return true; } } return false; } }
/** * Reads POI data for an area defined by the tile in the upper left and the tile in * the lower right corner. The default implementation combines the results from * all tiles, a possibly inefficient solution. * Precondition: upperLeft.tileX <= lowerRight.tileX && upperLeft.tileY <= lowerRight.tileY * * @param upperLeft tile that defines the upper left corner of the requested area. * @param lowerRight tile that defines the lower right corner of the requested area. * @return map data for the tile. */ public MapReadResult readPoiData(Tile upperLeft, Tile lowerRight) { if (upperLeft.tileX > lowerRight.tileX || upperLeft.tileY > lowerRight.tileY) { new IllegalArgumentException("upperLeft tile must be above and left of lowerRight tile"); } MapReadResult result = new MapReadResult(); for (int x = upperLeft.tileX; x <= lowerRight.tileX; x++) { for (int y = upperLeft.tileY; y <= lowerRight.tileY; y++) { Tile current = new Tile(x, y, upperLeft.zoomLevel, upperLeft.tileSize); result.add(readPoiData(current), false); } } return result; }
/** * Whether the tile is stale and should be refreshed. * <p/> * This method is called from {@link #draw(org.mapsforge.core.model.BoundingBox, byte, org.mapsforge.core.graphics.Canvas, org.mapsforge.core.model.Point)} to determine whether the tile needs to * be refreshed. * <p/> * A tile is considered stale if the timestamp of the layer's {@link #mapDataStore} is more recent than the * {@code bitmap}'s {@link org.mapsforge.core.graphics.TileBitmap#getTimestamp()}. * <p/> * When a tile has become stale, the layer will first display the tile referenced by {@code bitmap} and attempt to * obtain a fresh copy in the background. When a fresh copy becomes available, the layer will replace is and update * the cache. If a fresh copy cannot be obtained for whatever reason, the stale tile will continue to be used until * another {@code #draw(BoundingBox, byte, Canvas, Point)} operation requests it again. * * @param tile A tile. * @param bitmap The bitmap for {@code tile} currently held in the layer's cache. */ @Override protected boolean isTileStale(Tile tile, TileBitmap bitmap) { return this.mapDataStore.getDataTimestamp(tile) > bitmap.getTimestamp(); }
MapReadResult mapReadResult = this.mapDataStore.readMapData(rendererJob.tile); processReadMapData(renderContext, mapReadResult); renderContext.renderTheme.matchHillShadings(this, renderContext); bitmap = this.graphicFactory.createTileBitmap(rendererJob.tile.tileSize, rendererJob.hasAlpha); bitmap.setTimestamp(rendererJob.mapDataStore.getDataTimestamp(rendererJob.tile)); renderContext.canvasRasterer.setCanvasBitmap(bitmap); if (!rendererJob.hasAlpha && rendererJob.displayModel.getBackgroundColor() != renderContext.renderTheme.getMapBackground()) { Rectangle insideArea = this.mapDataStore.boundingBox().getPositionRelativeToTile(rendererJob.tile); if (!rendererJob.hasAlpha) { renderContext.canvasRasterer.fillOutsideAreas(renderContext.renderTheme.getMapBackgroundOutside(), insideArea);
private MapReadResult readLabels(Tile upperLeft, Tile lowerRight, boolean deduplicate) { MapReadResult mapReadResult = new MapReadResult(); for (MapDataStore mdb : mapDatabases) { if (mdb.supportsTile(upperLeft)) { MapReadResult result = mdb.readLabels(upperLeft, lowerRight); if (result == null) { continue; } boolean isWater = mapReadResult.isWater & result.isWater; mapReadResult.isWater = isWater; mapReadResult.add(result, deduplicate); } } return mapReadResult; }