Label layer: use ZoomLimiter for overzoom (#544)

This commit is contained in:
Gustl22 2018-05-25 17:06:23 +02:00 committed by Emux
parent c8068d5835
commit 9e52e9e848
No known key found for this signature in database
GPG Key ID: 64ED9980896038C3
2 changed files with 75 additions and 10 deletions

View File

@ -1,8 +1,9 @@
/*
* Copyright 2012, 2013 Hannes Janetzek
* Copyright 2017 Wolfgang Schramm
* Copyright 2017 devemux86
* Copyright 2017-2018 devemux86
* Copyright 2017 Andrey Novikov
* Copyright 2018 Gustl22
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@ -24,13 +25,16 @@ import org.oscim.event.Event;
import org.oscim.layers.Layer;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileManager;
import org.oscim.layers.tile.ZoomLimiter;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.map.Map;
import org.oscim.map.Viewport;
import org.oscim.utils.async.SimpleWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LabelLayer extends Layer implements Map.UpdateListener, TileManager.Listener {
public class LabelLayer extends Layer implements Map.UpdateListener, TileManager.Listener,
ZoomLimiter.IZoomLimiter {
static final Logger log = LoggerFactory.getLogger(LabelLayer.class);
@ -38,19 +42,31 @@ public class LabelLayer extends Layer implements Map.UpdateListener, TileManager
private static final long MAX_RELABEL_DELAY = 100;
// Sane default to allow render themes to work
private static final int ZOOM_LIMIT = Viewport.MAX_ZOOM_LEVEL;
private final LabelPlacement mLabelPlacer;
private final Worker mWorker;
private final ZoomLimiter mZoomLimiter;
public LabelLayer(Map map, VectorTileLayer l) {
this(map, l, new LabelTileLoaderHook());
}
public LabelLayer(Map map, VectorTileLayer l, VectorTileLayer.TileLoaderThemeHook h) {
this(map, l, h, ZOOM_LIMIT);
}
public LabelLayer(Map map, VectorTileLayer l, VectorTileLayer.TileLoaderThemeHook h,
int zoomLimit) {
super(map);
l.getManager().events.bind(this);
l.addHook(h);
mLabelPlacer = new LabelPlacement(map, l.tileRenderer());
mZoomLimiter = new ZoomLimiter(l.getManager(), map.viewport().getMinZoomLevel(),
map.viewport().getMaxZoomLevel(), zoomLimit);
mLabelPlacer = new LabelPlacement(map, l.tileRenderer(), mZoomLimiter);
mWorker = new Worker(map);
mRenderer = new TextRenderer(mWorker);
}
@ -86,6 +102,16 @@ public class LabelLayer extends Layer implements Map.UpdateListener, TileManager
}
}
@Override
public void addZoomLimit() {
mZoomLimiter.addZoomLimit();
}
@Override
public void removeZoomLimit() {
mZoomLimiter.removeZoomLimit();
}
public void clearLabels() {
mWorker.cancel(true);
}

View File

@ -1,5 +1,7 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016 devemux86
* Copyright 2018 Gustl22
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@ -21,7 +23,9 @@ import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileRenderer;
import org.oscim.layers.tile.TileSet;
import org.oscim.layers.tile.ZoomLimiter;
import org.oscim.map.Map;
import org.oscim.map.Viewport;
import org.oscim.renderer.bucket.SymbolBucket;
import org.oscim.renderer.bucket.SymbolItem;
import org.oscim.renderer.bucket.TextItem;
@ -31,6 +35,9 @@ import org.oscim.utils.geom.OBB2D;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Set;
import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
import static org.oscim.layers.tile.MapTile.State.READY;
@ -53,6 +60,7 @@ public class LabelPlacement {
private final TileSet mTileSet = new TileSet();
private final TileRenderer mTileRenderer;
private final Map mMap;
private final ZoomLimiter mZoomLimiter;
/**
* list of current labels
@ -67,9 +75,13 @@ public class LabelPlacement {
*/
private int mRelabelCnt;
public LabelPlacement(Map map, TileRenderer tileRenderer) {
/* Zoom level of current tiles (initial value doesn't matter) */
private Integer mZoom = Viewport.MIN_ZOOM_LEVEL;
public LabelPlacement(Map map, TileRenderer tileRenderer, ZoomLimiter zoomLimiter) {
mMap = map;
mTileRenderer = tileRenderer;
mZoomLimiter = zoomLimiter;
}
/**
@ -294,7 +306,13 @@ public class LabelPlacement {
boolean updateLabels(LabelTask work) {
/* get current tiles */
boolean changedTiles = mTileRenderer.getVisibleTiles(mTileSet);
int lastZoom = mZoom;
mZoom = mTileRenderer.getVisibleTiles(mTileSet, true);
boolean changedTiles = mZoom != null;
// set to last zoom in case of tiles didn't change
if (!changedTiles)
mZoom = lastZoom;
if (mTileSet.cnt == 0) {
return false;
@ -307,10 +325,31 @@ public class LabelPlacement {
if (!changedTiles && !changedPos)
return false;
if (mZoom < mZoomLimiter.getMinZoom() || mZoom > mZoomLimiter.getMaxZoom())
return false;
mRelabelCnt++;
MapTile[] tiles = mTileSet.tiles;
int zoom = tiles[0].zoomLevel;
int cnt = mTileSet.cnt;
MapTile[] tiles;
int zoom;
if (mZoom > mZoomLimiter.getZoomLimit()) {
// render from zoom limit tiles (avoid duplicates and null)
Set<MapTile> hashTiles = new HashSet<>();
for (int i = 0; i < cnt; i++) {
MapTile t = mZoomLimiter.getTile(mTileSet.tiles[i]);
if (t == null)
continue;
hashTiles.add(t);
}
cnt = hashTiles.size();
tiles = hashTiles.toArray(new MapTile[cnt]);
zoom = mZoomLimiter.getZoomLimit();
} else {
tiles = mTileSet.tiles;
zoom = mZoom;
}
/* estimation for visible area to be labeled */
int mw = (mMap.getWidth() + Tile.SIZE) / 2;
@ -398,7 +437,7 @@ public class LabelPlacement {
}
/* add way labels */
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
for (int i = 0; i < cnt; i++) {
MapTile t = tiles[i];
if (!t.state(READY | NEW_DATA))
continue;
@ -411,7 +450,7 @@ public class LabelPlacement {
}
/* add caption */
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
for (int i = 0; i < cnt; i++) {
MapTile t = tiles[i];
if (!t.state(READY | NEW_DATA))
continue;
@ -453,7 +492,7 @@ public class LabelPlacement {
}
/* add symbol items */
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
for (int i = 0; i < cnt; i++) {
MapTile t = tiles[i];
if (!t.state(READY | NEW_DATA))
continue;