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 2012, 2013 Hannes Janetzek
* Copyright 2017 Wolfgang Schramm * Copyright 2017 Wolfgang Schramm
* Copyright 2017 devemux86 * Copyright 2017-2018 devemux86
* Copyright 2017 Andrey Novikov * Copyright 2017 Andrey Novikov
* Copyright 2018 Gustl22
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * 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.Layer;
import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileManager; import org.oscim.layers.tile.TileManager;
import org.oscim.layers.tile.ZoomLimiter;
import org.oscim.layers.tile.vector.VectorTileLayer; import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.map.Map; import org.oscim.map.Map;
import org.oscim.map.Viewport;
import org.oscim.utils.async.SimpleWorker; import org.oscim.utils.async.SimpleWorker;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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); 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; 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 LabelPlacement mLabelPlacer;
private final Worker mWorker; private final Worker mWorker;
private final ZoomLimiter mZoomLimiter;
public LabelLayer(Map map, VectorTileLayer l) { public LabelLayer(Map map, VectorTileLayer l) {
this(map, l, new LabelTileLoaderHook()); this(map, l, new LabelTileLoaderHook());
} }
public LabelLayer(Map map, VectorTileLayer l, VectorTileLayer.TileLoaderThemeHook h) { 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); super(map);
l.getManager().events.bind(this); l.getManager().events.bind(this);
l.addHook(h); 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); mWorker = new Worker(map);
mRenderer = new TextRenderer(mWorker); 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() { public void clearLabels() {
mWorker.cancel(true); mWorker.cancel(true);
} }

View File

@ -1,5 +1,7 @@
/* /*
* Copyright 2013 Hannes Janetzek
* Copyright 2016 devemux86 * Copyright 2016 devemux86
* Copyright 2018 Gustl22
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * 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.MapTile;
import org.oscim.layers.tile.TileRenderer; import org.oscim.layers.tile.TileRenderer;
import org.oscim.layers.tile.TileSet; import org.oscim.layers.tile.TileSet;
import org.oscim.layers.tile.ZoomLimiter;
import org.oscim.map.Map; import org.oscim.map.Map;
import org.oscim.map.Viewport;
import org.oscim.renderer.bucket.SymbolBucket; import org.oscim.renderer.bucket.SymbolBucket;
import org.oscim.renderer.bucket.SymbolItem; import org.oscim.renderer.bucket.SymbolItem;
import org.oscim.renderer.bucket.TextItem; import org.oscim.renderer.bucket.TextItem;
@ -31,6 +35,9 @@ import org.oscim.utils.geom.OBB2D;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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.NEW_DATA;
import static org.oscim.layers.tile.MapTile.State.READY; import static org.oscim.layers.tile.MapTile.State.READY;
@ -53,6 +60,7 @@ public class LabelPlacement {
private final TileSet mTileSet = new TileSet(); private final TileSet mTileSet = new TileSet();
private final TileRenderer mTileRenderer; private final TileRenderer mTileRenderer;
private final Map mMap; private final Map mMap;
private final ZoomLimiter mZoomLimiter;
/** /**
* list of current labels * list of current labels
@ -67,9 +75,13 @@ public class LabelPlacement {
*/ */
private int mRelabelCnt; 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; mMap = map;
mTileRenderer = tileRenderer; mTileRenderer = tileRenderer;
mZoomLimiter = zoomLimiter;
} }
/** /**
@ -294,7 +306,13 @@ public class LabelPlacement {
boolean updateLabels(LabelTask work) { boolean updateLabels(LabelTask work) {
/* get current tiles */ /* 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) { if (mTileSet.cnt == 0) {
return false; return false;
@ -307,10 +325,31 @@ public class LabelPlacement {
if (!changedTiles && !changedPos) if (!changedTiles && !changedPos)
return false; return false;
if (mZoom < mZoomLimiter.getMinZoom() || mZoom > mZoomLimiter.getMaxZoom())
return false;
mRelabelCnt++; mRelabelCnt++;
MapTile[] tiles = mTileSet.tiles; int cnt = mTileSet.cnt;
int zoom = tiles[0].zoomLevel; 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 */ /* estimation for visible area to be labeled */
int mw = (mMap.getWidth() + Tile.SIZE) / 2; int mw = (mMap.getWidth() + Tile.SIZE) / 2;
@ -398,7 +437,7 @@ public class LabelPlacement {
} }
/* add way labels */ /* add way labels */
for (int i = 0, n = mTileSet.cnt; i < n; i++) { for (int i = 0; i < cnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (!t.state(READY | NEW_DATA)) if (!t.state(READY | NEW_DATA))
continue; continue;
@ -411,7 +450,7 @@ public class LabelPlacement {
} }
/* add caption */ /* add caption */
for (int i = 0, n = mTileSet.cnt; i < n; i++) { for (int i = 0; i < cnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (!t.state(READY | NEW_DATA)) if (!t.state(READY | NEW_DATA))
continue; continue;
@ -453,7 +492,7 @@ public class LabelPlacement {
} }
/* add symbol items */ /* add symbol items */
for (int i = 0, n = mTileSet.cnt; i < n; i++) { for (int i = 0; i < cnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (!t.state(READY | NEW_DATA)) if (!t.state(READY | NEW_DATA))
continue; continue;