Mapsforge: Move tileprojection to convert E6 int directly to tile coordinates (#752)

This commit is contained in:
Justus Schmidt
2019-11-22 11:50:56 +01:00
committed by Emux
parent a13c4a3793
commit cdcae29ae1

View File

@@ -7,6 +7,7 @@
* Copyright 2017-2018 Gustl22 * Copyright 2017-2018 Gustl22
* Copyright 2018 Bezzu * Copyright 2018 Bezzu
* Copyright 2019 marq24 * Copyright 2019 marq24
* Copyright 2019 Justus Schmidt
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
* *
@@ -692,7 +693,7 @@ public class MapDatabase implements ITileDataSource {
return true; return true;
} }
private boolean processWayDataBlock(MapElement e, boolean doubleDeltaEncoding, boolean isLine, List<GeoPoint[]> wayCoordinates) { private boolean processWayDataBlock(MapElement e, boolean doubleDeltaEncoding, boolean isLine, List<GeoPoint[]> wayCoordinates, int[] labelPosition) {
/* get and check the number of way coordinate blocks (VBE-U) */ /* get and check the number of way coordinate blocks (VBE-U) */
int numBlocks = mReadBuffer.readUnsignedInt(); int numBlocks = mReadBuffer.readUnsignedInt();
if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) { if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) {
@@ -717,37 +718,50 @@ public class MapDatabase implements ITileDataSource {
/* each way node consists of latitude and longitude */ /* each way node consists of latitude and longitude */
int len = numWayNodes * 2; int len = numWayNodes * 2;
wayLengths[coordinateBlock] = decodeWayNodes(doubleDeltaEncoding, // create the array which will store the current way segment
e, len, isLine); GeoPoint[] waySegment = null;
if (wayCoordinates != null)
waySegment = new GeoPoint[numWayNodes];
if (wayCoordinates != null) { // label position must be set on first coordinate block
// create the array which will store the current way segment wayLengths[coordinateBlock] = decodeWayNodes(doubleDeltaEncoding, e, len, isLine,
GeoPoint[] waySegment = new GeoPoint[e.getNumPoints()]; coordinateBlock == 0 ? labelPosition : null, waySegment);
for (int i = 0; i < e.getNumPoints(); i++)
waySegment[i] = new GeoPoint(e.getPointY(i) / 1E6, e.getPointX(i) / 1E6); if (wayCoordinates != null)
wayCoordinates.add(waySegment); wayCoordinates.add(waySegment);
}
} }
return true; return true;
} }
private int decodeWayNodes(boolean doubleDelta, MapElement e, int length, boolean isLine) { private int decodeWayNodes(boolean doubleDelta, MapElement e, int length, boolean isLine, int[] labelPosition, GeoPoint[] waySegment) {
int[] buffer = mIntBuffer; int[] buffer = mIntBuffer;
mReadBuffer.readSignedInt(buffer, length); mReadBuffer.readSignedInt(buffer, length);
float[] outBuffer = e.ensurePointSize(e.pointNextPos + length, true); float[] outBuffer = e.ensurePointSize(e.pointNextPos + length, true);
int outPos = e.pointNextPos; int outPos = e.pointNextPos;
int lat, lon; float pLat, pLon;
/* first node latitude single-delta offset */ /* first node latitude single-delta offset */
int firstLat = lat = mTileLatitude + buffer[0]; int rawLat = mTileLatitude + buffer[0];
int firstLon = lon = mTileLongitude + buffer[1]; int rawLon = mTileLongitude + buffer[1];
outBuffer[outPos++] = lon; float firstLat = pLat = mTileProjection.projectLat(rawLat);
outBuffer[outPos++] = lat; float firstLon = pLon = mTileProjection.projectLon(rawLon);
outBuffer[outPos++] = pLon;
outBuffer[outPos++] = pLat;
int cnt = 2; int cnt = 2;
/* reset label position single-delta to first way node */
if (labelPosition != null) {
labelPosition[1] = rawLat + labelPosition[1];
labelPosition[0] = rawLon + labelPosition[0];
}
if (waySegment != null)
waySegment[0] = new GeoPoint(rawLat / 1E6, rawLon / 1E6);
int deltaLat = 0; int deltaLat = 0;
int deltaLon = 0; int deltaLon = 0;
@@ -759,8 +773,14 @@ public class MapDatabase implements ITileDataSource {
deltaLat = buffer[pos]; deltaLat = buffer[pos];
deltaLon = buffer[pos + 1]; deltaLon = buffer[pos + 1];
} }
lat += deltaLat; rawLat += deltaLat;
lon += deltaLon; rawLon += deltaLon;
if (waySegment != null)
waySegment[pos / 2] = new GeoPoint(rawLat / 1E6, rawLon / 1E6);
float lat = mTileProjection.projectLat(rawLat);
float lon = mTileProjection.projectLon(rawLon);
if (pos == length - 2) { if (pos == length - 2) {
boolean line = isLine || (lon != firstLon || lat != firstLat); boolean line = isLine || (lon != firstLon || lat != firstLat);
@@ -774,13 +794,16 @@ public class MapDatabase implements ITileDataSource {
if (e.type == GeometryType.NONE) if (e.type == GeometryType.NONE)
e.type = line ? LINE : POLY; e.type = line ? LINE : POLY;
} else if (lat == pLat && lon == pLon) {
/* drop small distance intermediate nodes */
//log.debug("drop zero delta ");
} else /*if ((deltaLon > minDeltaLon || deltaLon < -minDeltaLon } else /*if ((deltaLon > minDeltaLon || deltaLon < -minDeltaLon
|| deltaLat > minDeltaLat || deltaLat < -minDeltaLat) || deltaLat > minDeltaLat || deltaLat < -minDeltaLat)
|| e.tags.contains("natural", "nosea"))*/ { || e.tags.contains("natural", "nosea"))*/ {
// Avoid additional simplification // Avoid additional simplification
// https://github.com/mapsforge/vtm/issues/39 // https://github.com/mapsforge/vtm/issues/39
outBuffer[outPos++] = lon; outBuffer[outPos++] = pLon = lon;
outBuffer[outPos++] = lat; outBuffer[outPos++] = pLat = lat;
cnt += 2; cnt += 2;
} }
} }
@@ -954,7 +977,7 @@ public class MapDatabase implements ITileDataSource {
if (ways != null) if (ways != null)
wayNodes = new ArrayList<>(); wayNodes = new ArrayList<>();
if (!processWayDataBlock(e, featureWayDoubleDeltaEncoding, linearFeature, wayNodes)) if (!processWayDataBlock(e, featureWayDoubleDeltaEncoding, linearFeature, wayNodes, labelPosition))
return false; return false;
/* drop invalid outer ring */ /* drop invalid outer ring */
@@ -963,12 +986,10 @@ public class MapDatabase implements ITileDataSource {
} }
if (labelPosition != null && wayDataBlock == 0) if (labelPosition != null && wayDataBlock == 0)
e.setLabelPosition(e.points[0] + labelPosition[0], e.points[1] + labelPosition[1]); e.setLabelPosition(mTileProjection.projectLon(labelPosition[0]), mTileProjection.projectLat(labelPosition[1]));
else else
e.labelPosition = null; e.labelPosition = null;
mTileProjection.project(e);
// When a way will be rendered then typically a label / symbol will be applied // When a way will be rendered then typically a label / symbol will be applied
// by the render theme. If the way does not come with a defined labelPosition // by the render theme. If the way does not come with a defined labelPosition
// we should calculate a position, that is based on all points of the given way. // we should calculate a position, that is based on all points of the given way.
@@ -1011,7 +1032,7 @@ public class MapDatabase implements ITileDataSource {
for (int i = 0; i < e.tags.size(); i++) for (int i = 0; i < e.tags.size(); i++)
tags.add(e.tags.get(i)); tags.add(e.tags.get(i));
if (Selector.ALL == selector || hasName || hasHouseNr || hasRef || wayAsLabelTagFilter(tags)) { if (Selector.ALL == selector || hasName || hasHouseNr || hasRef || wayAsLabelTagFilter(tags)) {
GeoPoint labelPos = e.labelPosition != null ? new GeoPoint(e.labelPosition.y / 1E6, e.labelPosition.x / 1E6) : null; GeoPoint labelPos = labelPosition != null ? new GeoPoint(labelPosition[1] / 1E6, labelPosition[0] / 1E6) : null;
ways.add(new Way(layer, tags, wayNodesArray, labelPos, e.type)); ways.add(new Way(layer, tags, wayNodesArray, labelPos, e.type));
} }
} }