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
|
@Override
|
||||||
public boolean process(MapTile tile, RenderBuckets buckets, MapElement element,
|
public boolean process(MapTile tile, RenderBuckets buckets, MapElement element,
|
||||||
RenderStyle style, int level) {
|
RenderStyle style, int level) {
|
||||||
// FIXME check why some buildings are processed up to 4 times (should avoid overhead)
|
// FIXME artifacts at tile borders in last extraction zoom as they're clipped
|
||||||
// FIXME fix artifacts at tile borders
|
|
||||||
|
|
||||||
if (!(style instanceof ExtrusionStyle))
|
if (!(style instanceof ExtrusionStyle))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018 devemux86
|
* Copyright 2018 devemux86
|
||||||
|
* Copyright 2018 Gustl22
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
* 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
|
* 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.MapElement;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.utils.geom.TileClipper;
|
import org.oscim.utils.geom.TileClipper;
|
||||||
|
import org.oscim.utils.geom.TileSeparator;
|
||||||
|
|
||||||
class OverzoomDataSink implements ITileDataSink {
|
class OverzoomDataSink implements ITileDataSink {
|
||||||
|
|
||||||
private final ITileDataSink sink;
|
private final ITileDataSink sink;
|
||||||
|
|
||||||
private final TileClipper clipper;
|
private final TileClipper clipper;
|
||||||
|
private final TileSeparator separator;
|
||||||
private final float dx, dy, scale;
|
private final float dx, dy, scale;
|
||||||
|
|
||||||
OverzoomDataSink(ITileDataSink sink, Tile overzoomTile, Tile tile) {
|
OverzoomDataSink(ITileDataSink sink, Tile overzoomTile, Tile tile) {
|
||||||
@ -37,12 +40,19 @@ class OverzoomDataSink implements ITileDataSink {
|
|||||||
float buffer = 32 * CanvasAdapter.getScale();
|
float buffer = 32 * CanvasAdapter.getScale();
|
||||||
clipper = new TileClipper((dx - buffer) / scale, (dy - buffer) / scale,
|
clipper = new TileClipper((dx - buffer) / scale, (dy - buffer) / scale,
|
||||||
(dx + Tile.SIZE + buffer) / scale, (dy + Tile.SIZE + 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
|
@Override
|
||||||
public void process(MapElement element) {
|
public void process(MapElement element) {
|
||||||
if (!clipper.clip(element))
|
if (element.isBuilding() || element.isBuildingPart()) {
|
||||||
return;
|
if (!separator.separate(element))
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (!clipper.clip(element))
|
||||||
|
return;
|
||||||
|
}
|
||||||
element.scale(scale, scale);
|
element.scale(scale, scale);
|
||||||
element.translate(-dx, -dy);
|
element.translate(-dx, -dy);
|
||||||
sink.process(element);
|
sink.process(element);
|
||||||
|
@ -37,6 +37,7 @@ import org.oscim.tiling.TileSource;
|
|||||||
import org.oscim.tiling.source.mapfile.header.SubFileParameter;
|
import org.oscim.tiling.source.mapfile.header.SubFileParameter;
|
||||||
import org.oscim.utils.Parameters;
|
import org.oscim.utils.Parameters;
|
||||||
import org.oscim.utils.geom.TileClipper;
|
import org.oscim.utils.geom.TileClipper;
|
||||||
|
import org.oscim.utils.geom.TileSeparator;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -206,6 +207,7 @@ public class MapDatabase implements ITileDataSource {
|
|||||||
|
|
||||||
private final TileProjection mTileProjection;
|
private final TileProjection mTileProjection;
|
||||||
private final TileClipper mTileClipper;
|
private final TileClipper mTileClipper;
|
||||||
|
private final TileSeparator mTileSeparator;
|
||||||
|
|
||||||
private final MapFileTileSource mTileSource;
|
private final MapFileTileSource mTileSource;
|
||||||
|
|
||||||
@ -229,6 +231,7 @@ public class MapDatabase implements ITileDataSource {
|
|||||||
|
|
||||||
mTileProjection = new TileProjection();
|
mTileProjection = new TileProjection();
|
||||||
mTileClipper = new TileClipper(0, 0, 0, 0);
|
mTileClipper = new TileClipper(0, 0, 0, 0);
|
||||||
|
mTileSeparator = new TileSeparator(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapFileTileSource getTileSource() {
|
public MapFileTileSource getTileSource() {
|
||||||
@ -406,9 +409,9 @@ public class MapDatabase implements ITileDataSource {
|
|||||||
// private long mCurrentRow;
|
// private long mCurrentRow;
|
||||||
// private long mCurrentCol;
|
// 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 numRows = queryParameters.toBlockY - queryParameters.fromBlockY;
|
||||||
long numCols = queryParameters.toBlockX - queryParameters.fromBlockX;
|
long numCols = queryParameters.toBlockX - queryParameters.fromBlockX;
|
||||||
|
|
||||||
@ -421,28 +424,29 @@ public class MapDatabase implements ITileDataSource {
|
|||||||
else
|
else
|
||||||
buffer = (int) (16 * CanvasAdapter.getScale() + 0.5f);
|
buffer = (int) (16 * CanvasAdapter.getScale() + 0.5f);
|
||||||
|
|
||||||
xmin = -buffer;
|
xmin = ymin = -buffer;
|
||||||
ymin = -buffer;
|
xmax = ymax = Tile.SIZE + buffer;
|
||||||
xmax = Tile.SIZE + buffer;
|
xSmin = ySmin = 0;
|
||||||
ymax = Tile.SIZE + buffer;
|
xSmax = ySmax = Tile.SIZE;
|
||||||
|
|
||||||
if (numRows > 0) {
|
if (numRows > 0) {
|
||||||
int w = (int) (Tile.SIZE / (numCols + 1));
|
int w = (int) (Tile.SIZE / (numCols + 1));
|
||||||
int h = (int) (Tile.SIZE / (numRows + 1));
|
int h = (int) (Tile.SIZE / (numRows + 1));
|
||||||
|
|
||||||
if (mCurrentCol > 0)
|
if (mCurrentCol > 0)
|
||||||
xmin = (int) (mCurrentCol * w);
|
xSmin = xmin = (int) (mCurrentCol * w);
|
||||||
|
|
||||||
if (mCurrentCol < numCols)
|
if (mCurrentCol < numCols)
|
||||||
xmax = (int) (mCurrentCol * w + w);
|
xSmax = xmax = (int) (mCurrentCol * w + w);
|
||||||
|
|
||||||
if (mCurrentRow > 0)
|
if (mCurrentRow > 0)
|
||||||
ymin = (int) (mCurrentRow * h);
|
ySmin = ymin = (int) (mCurrentRow * h);
|
||||||
|
|
||||||
if (mCurrentRow < numRows)
|
if (mCurrentRow < numRows)
|
||||||
ymax = (int) (mCurrentRow * h + h);
|
ySmax = ymax = (int) (mCurrentRow * h + h);
|
||||||
}
|
}
|
||||||
mTileClipper.setRect(xmin, ymin, xmax, ymax);
|
mTileClipper.setRect(xmin, ymin, xmax, ymax);
|
||||||
|
mTileSeparator.setRect(xSmin, ySmin, xSmax, ySmax);
|
||||||
}
|
}
|
||||||
|
|
||||||
//private final static Tag mWaterTag = new Tag("natural", "water");
|
//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.
|
// Avoid clipping for buildings, which slows rendering.
|
||||||
// But clip everything if buildings are displayed.
|
// But clip everything if buildings are displayed.
|
||||||
if ((!e.tags.containsKey(Tag.KEY_BUILDING)
|
if (!e.tags.containsKey(Tag.KEY_BUILDING)
|
||||||
&& !e.tags.containsKey(Tag.KEY_BUILDING_PART))
|
&& !e.tags.containsKey(Tag.KEY_BUILDING_PART)) {
|
||||||
|| queryParameters.queryZoomLevel >= BuildingLayer.MIN_ZOOM) {
|
if (!mTileClipper.clip(e))
|
||||||
if (!mTileClipper.clip(e)) {
|
continue;
|
||||||
|
} else if (queryParameters.queryZoomLevel >= BuildingLayer.MIN_ZOOM) {
|
||||||
|
if (!mTileSeparator.separate(e))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
e.simplify(1, true);
|
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