Buildings overzoom: use TileSeparator (#518)
This commit is contained in:
parent
27a3c5a926
commit
345b57c57a
@ -91,8 +91,7 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
|
||||
@Override
|
||||
public boolean process(MapTile tile, RenderBuckets buckets, MapElement element,
|
||||
RenderStyle style, int level) {
|
||||
// FIXME check why some buildings are processed up to 4 times (should avoid overhead)
|
||||
// FIXME fix artifacts at tile borders
|
||||
// FIXME artifacts at tile borders in last extraction zoom as they're clipped
|
||||
|
||||
if (!(style instanceof ExtrusionStyle))
|
||||
return false;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2018 devemux86
|
||||
* Copyright 2018 Gustl22
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
@ -19,12 +20,14 @@ import org.oscim.backend.canvas.Bitmap;
|
||||
import org.oscim.core.MapElement;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.utils.geom.TileClipper;
|
||||
import org.oscim.utils.geom.TileSeparator;
|
||||
|
||||
class OverzoomDataSink implements ITileDataSink {
|
||||
|
||||
private final ITileDataSink sink;
|
||||
|
||||
private final TileClipper clipper;
|
||||
private final TileSeparator separator;
|
||||
private final float dx, dy, scale;
|
||||
|
||||
OverzoomDataSink(ITileDataSink sink, Tile overzoomTile, Tile tile) {
|
||||
@ -37,12 +40,19 @@ class OverzoomDataSink implements ITileDataSink {
|
||||
float buffer = 32 * CanvasAdapter.getScale();
|
||||
clipper = new TileClipper((dx - buffer) / scale, (dy - buffer) / scale,
|
||||
(dx + Tile.SIZE + buffer) / scale, (dy + Tile.SIZE + buffer) / scale);
|
||||
separator = new TileSeparator(dx / scale, dy / scale,
|
||||
(dx + Tile.SIZE) / scale, (dy + Tile.SIZE) / scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(MapElement element) {
|
||||
if (!clipper.clip(element))
|
||||
return;
|
||||
if (element.isBuilding() || element.isBuildingPart()) {
|
||||
if (!separator.separate(element))
|
||||
return;
|
||||
} else {
|
||||
if (!clipper.clip(element))
|
||||
return;
|
||||
}
|
||||
element.scale(scale, scale);
|
||||
element.translate(-dx, -dy);
|
||||
sink.process(element);
|
||||
|
@ -37,6 +37,7 @@ import org.oscim.tiling.TileSource;
|
||||
import org.oscim.tiling.source.mapfile.header.SubFileParameter;
|
||||
import org.oscim.utils.Parameters;
|
||||
import org.oscim.utils.geom.TileClipper;
|
||||
import org.oscim.utils.geom.TileSeparator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -206,6 +207,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
private final TileProjection mTileProjection;
|
||||
private final TileClipper mTileClipper;
|
||||
private final TileSeparator mTileSeparator;
|
||||
|
||||
private final MapFileTileSource mTileSource;
|
||||
|
||||
@ -229,6 +231,7 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
mTileProjection = new TileProjection();
|
||||
mTileClipper = new TileClipper(0, 0, 0, 0);
|
||||
mTileSeparator = new TileSeparator(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public MapFileTileSource getTileSource() {
|
||||
@ -406,9 +409,9 @@ public class MapDatabase implements ITileDataSource {
|
||||
// private long mCurrentRow;
|
||||
// private long mCurrentCol;
|
||||
|
||||
private int xmin, ymin, xmax, ymax;
|
||||
private int xmin, ymin, xmax, ymax, xSmin, ySmin, xSmax, ySmax;
|
||||
|
||||
private void setTileClipping(QueryParameters queryParameters, long mCurrentRow, long mCurrentCol) {
|
||||
private synchronized void setTileClipping(QueryParameters queryParameters, long mCurrentRow, long mCurrentCol) {
|
||||
long numRows = queryParameters.toBlockY - queryParameters.fromBlockY;
|
||||
long numCols = queryParameters.toBlockX - queryParameters.fromBlockX;
|
||||
|
||||
@ -421,28 +424,29 @@ public class MapDatabase implements ITileDataSource {
|
||||
else
|
||||
buffer = (int) (16 * CanvasAdapter.getScale() + 0.5f);
|
||||
|
||||
xmin = -buffer;
|
||||
ymin = -buffer;
|
||||
xmax = Tile.SIZE + buffer;
|
||||
ymax = Tile.SIZE + buffer;
|
||||
xmin = ymin = -buffer;
|
||||
xmax = ymax = Tile.SIZE + buffer;
|
||||
xSmin = ySmin = 0;
|
||||
xSmax = ySmax = Tile.SIZE;
|
||||
|
||||
if (numRows > 0) {
|
||||
int w = (int) (Tile.SIZE / (numCols + 1));
|
||||
int h = (int) (Tile.SIZE / (numRows + 1));
|
||||
|
||||
if (mCurrentCol > 0)
|
||||
xmin = (int) (mCurrentCol * w);
|
||||
xSmin = xmin = (int) (mCurrentCol * w);
|
||||
|
||||
if (mCurrentCol < numCols)
|
||||
xmax = (int) (mCurrentCol * w + w);
|
||||
xSmax = xmax = (int) (mCurrentCol * w + w);
|
||||
|
||||
if (mCurrentRow > 0)
|
||||
ymin = (int) (mCurrentRow * h);
|
||||
ySmin = ymin = (int) (mCurrentRow * h);
|
||||
|
||||
if (mCurrentRow < numRows)
|
||||
ymax = (int) (mCurrentRow * h + h);
|
||||
ySmax = ymax = (int) (mCurrentRow * h + h);
|
||||
}
|
||||
mTileClipper.setRect(xmin, ymin, xmax, ymax);
|
||||
mTileSeparator.setRect(xSmin, ySmin, xSmax, ySmax);
|
||||
}
|
||||
|
||||
//private final static Tag mWaterTag = new Tag("natural", "water");
|
||||
@ -957,12 +961,13 @@ public class MapDatabase implements ITileDataSource {
|
||||
|
||||
// Avoid clipping for buildings, which slows rendering.
|
||||
// But clip everything if buildings are displayed.
|
||||
if ((!e.tags.containsKey(Tag.KEY_BUILDING)
|
||||
&& !e.tags.containsKey(Tag.KEY_BUILDING_PART))
|
||||
|| queryParameters.queryZoomLevel >= BuildingLayer.MIN_ZOOM) {
|
||||
if (!mTileClipper.clip(e)) {
|
||||
if (!e.tags.containsKey(Tag.KEY_BUILDING)
|
||||
&& !e.tags.containsKey(Tag.KEY_BUILDING_PART)) {
|
||||
if (!mTileClipper.clip(e))
|
||||
continue;
|
||||
} else if (queryParameters.queryZoomLevel >= BuildingLayer.MIN_ZOOM) {
|
||||
if (!mTileSeparator.separate(e))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
e.simplify(1, true);
|
||||
|
||||
|
79
vtm/src/org/oscim/utils/geom/TileSeparator.java
Normal file
79
vtm/src/org/oscim/utils/geom/TileSeparator.java
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2013 Hannes Janetzek
|
||||
* Copyright 2018 Gustl22
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.utils.geom;
|
||||
|
||||
import org.oscim.core.GeometryBuffer;
|
||||
|
||||
public class TileSeparator {
|
||||
private float xmin;
|
||||
private float xmax;
|
||||
private float ymin;
|
||||
private float ymax;
|
||||
|
||||
public TileSeparator(float xmin, float ymin, float xmax, float ymax) {
|
||||
this.xmin = xmin;
|
||||
this.ymin = ymin;
|
||||
this.xmax = xmax;
|
||||
this.ymax = ymax;
|
||||
}
|
||||
|
||||
public void setRect(float xmin, float ymin, float xmax, float ymax) {
|
||||
this.xmin = xmin;
|
||||
this.ymin = ymin;
|
||||
this.xmax = xmax;
|
||||
this.ymax = ymax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Separates a poly geometry from tile (doesn't clip it).
|
||||
*
|
||||
* @param geom the geometry to be separated
|
||||
* @return true if geometry is inside the tile, false otherwise
|
||||
*/
|
||||
public boolean separate(GeometryBuffer geom) {
|
||||
if (!geom.isPoly())
|
||||
return false;
|
||||
|
||||
int pointPos = 0;
|
||||
|
||||
for (int indexPos = 0, n = geom.index.length; indexPos < n; indexPos++) {
|
||||
int len = geom.index[indexPos];
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
if (len < 6) {
|
||||
pointPos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
int end = pointPos + len;
|
||||
|
||||
for (int i = pointPos; i < end; ) {
|
||||
float cx = geom.points[i++];
|
||||
float cy = geom.points[i++];
|
||||
|
||||
if (cx >= xmin && cx < xmax && cy >= ymin && cy < ymax) {
|
||||
/* current is inside */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
pointPos += len;
|
||||
}
|
||||
geom.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user