Fix basemap rendering
This commit is contained in:
parent
3867c3ef57
commit
4367dda5a4
7 changed files with 245 additions and 153 deletions
|
@ -46,7 +46,7 @@ public class BinaryInspector {
|
|||
public static void main(String[] args) throws IOException {
|
||||
inspector(args);
|
||||
// test cases show info
|
||||
inspector(new String[]{"/home/victor/projects/OsmAnd/data/osm-gen/basemap_coastlines.obf"});
|
||||
inspector(new String[]{"-vmap", "-zoom=3","/home/victor/projects/OsmAnd/data/osm-gen/basemap_all.obf"});
|
||||
|
||||
|
||||
// test case extract parts
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -15,6 +16,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
|
||||
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.binary.OsmandOdb.MapData;
|
||||
import net.osmand.binary.OsmandOdb.MapDataBlock;
|
||||
|
@ -26,7 +28,7 @@ import net.osmand.osm.MapUtils;
|
|||
import net.osmand.osm.Node;
|
||||
import net.osmand.osm.Way;
|
||||
import net.osmand.osm.WayChain;
|
||||
import net.osmand.osm.OSMSettings.OSMTagKey;
|
||||
import net.osmand.osm.MapRenderingTypes.MapRulType;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.tools.bzip2.CBZip2InputStream;
|
||||
|
@ -46,6 +48,10 @@ public class BasemapProcessor {
|
|||
private static final int BITS_COUNT = (1 << TILE_ZOOMLEVEL) * (1 << TILE_ZOOMLEVEL);
|
||||
private BitSet seaTileInfo = new BitSet(BITS_COUNT);
|
||||
private BitSet landTileInfo = new BitSet(BITS_COUNT);
|
||||
private TIntArrayList typeUse = new TIntArrayList();
|
||||
List<MapRulType> tempNameUse = new ArrayList<MapRenderingTypes.MapRulType>();
|
||||
TIntArrayList addtypeUse = new TIntArrayList(8);
|
||||
Map<MapRulType, String> namesUse = new LinkedHashMap<MapRenderingTypes.MapRulType, String>();
|
||||
|
||||
private final int zoomWaySmothness;
|
||||
private final MapRenderingTypes renderingTypes;
|
||||
|
@ -67,7 +73,7 @@ public class BasemapProcessor {
|
|||
}
|
||||
|
||||
SimplisticQuadTree[] children = null;
|
||||
Map<MapZoomPair,List<Way>> coastlines = null;
|
||||
Map<MapZoomPair,List<SimplisticBinaryData>> dataObjects = null;
|
||||
|
||||
|
||||
public SimplisticQuadTree[] getAllChildren(){
|
||||
|
@ -79,23 +85,23 @@ public class BasemapProcessor {
|
|||
return children != null;
|
||||
}
|
||||
|
||||
public void addCoastline(MapZoomPair p, Way w){
|
||||
public void addQuadData(MapZoomPair p, SimplisticBinaryData w){
|
||||
|
||||
if(coastlines == null) {
|
||||
coastlines = new LinkedHashMap<MapZooms.MapZoomPair, List<Way>>();
|
||||
if(dataObjects == null) {
|
||||
dataObjects = new LinkedHashMap<MapZooms.MapZoomPair, List<SimplisticBinaryData>>();
|
||||
}
|
||||
if(!coastlines.containsKey(p)){
|
||||
coastlines.put(p, new ArrayList<Way>());
|
||||
if(!dataObjects.containsKey(p)){
|
||||
dataObjects.put(p, new ArrayList<SimplisticBinaryData>());
|
||||
}
|
||||
coastlines.get(p).add(w);
|
||||
dataObjects.get(p).add(w);
|
||||
}
|
||||
|
||||
public boolean coastlinesDefined(MapZoomPair p){
|
||||
return coastlines != null && coastlines.get(p) != null;
|
||||
public boolean dataIsDefined(MapZoomPair p){
|
||||
return dataObjects != null && dataObjects.get(p) != null;
|
||||
}
|
||||
|
||||
public List<Way> getCoastlines(MapZoomPair p) {
|
||||
return coastlines.get(p);
|
||||
public List<SimplisticBinaryData> getData(MapZoomPair p) {
|
||||
return dataObjects.get(p);
|
||||
}
|
||||
|
||||
public SimplisticQuadTree getOrCreateSubTree(int x, int y, int zm) {
|
||||
|
@ -122,7 +128,15 @@ public class BasemapProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SimplisticBinaryData {
|
||||
// consequent 31 coordinates
|
||||
public byte[] coordinates;
|
||||
public int[] types;
|
||||
public int[] addTypes;
|
||||
public long id = -500;
|
||||
public Map<MapRulType, String> names;
|
||||
}
|
||||
|
||||
|
||||
|
@ -265,7 +279,7 @@ public class BasemapProcessor {
|
|||
|
||||
|
||||
|
||||
public void writeCoastlinesFile(BinaryMapIndexWriter writer, String regionName) throws IOException {
|
||||
public void writeBasemapFile(BinaryMapIndexWriter writer, String regionName) throws IOException {
|
||||
writer.startWriteMapIndex(regionName);
|
||||
// write map encoding rules
|
||||
writer.writeMapEncodingRules(renderingTypes.getEncodingRuleTypes());
|
||||
|
@ -292,36 +306,37 @@ public class BasemapProcessor {
|
|||
private void writeBinaryMapBlock(SimplisticQuadTree simplisticQuadTree, BinaryMapIndexWriter writer,
|
||||
Map<SimplisticQuadTree, BinaryFileReference> refs, MapZoomPair p) throws IOException {
|
||||
Iterator<Entry<SimplisticQuadTree, BinaryFileReference>> it = refs.entrySet().iterator();
|
||||
TIntArrayList type = new TIntArrayList();
|
||||
type.add(renderingTypes.getCoastlineRuleType().getTargetId());
|
||||
|
||||
while(it.hasNext()) {
|
||||
Entry<SimplisticQuadTree, BinaryFileReference> e = it.next();
|
||||
MapDataBlock.Builder dataBlock = MapDataBlock.newBuilder();
|
||||
SimplisticQuadTree quad = e.getKey();
|
||||
|
||||
for (Way w : quad.getCoastlines(p)) {
|
||||
dataBlock.setBaseId(w.getId());
|
||||
List<Node> res = new ArrayList<Node>();
|
||||
MapAlgorithms.simplifyDouglasPeucker(w.getNodes(), p.getMaxZoom() - 1 + 8 + zoomWaySmothness, 3, res);
|
||||
ByteArrayOutputStream bcoordinates = new ByteArrayOutputStream();
|
||||
for (Node n : res) {
|
||||
if (n != null) {
|
||||
int y = MapUtils.get31TileNumberY(n.getLatitude());
|
||||
int x = MapUtils.get31TileNumberX(n.getLongitude());
|
||||
Algoritms.writeInt(bcoordinates, x);
|
||||
Algoritms.writeInt(bcoordinates, y);
|
||||
Map<String, Integer> stringTable = new LinkedHashMap<String, Integer> ();
|
||||
for (SimplisticBinaryData w : quad.getData(p)) {
|
||||
dataBlock.setBaseId(w.id);
|
||||
int[] wts = null;
|
||||
int[] wats = null;
|
||||
if(w.types != null ){
|
||||
wts = new int[w.types.length];
|
||||
for (int j = 0; j < w.types.length; j ++) {
|
||||
wts[j] = renderingTypes.getTypeByInternalId(w.types[j]).getTargetId();
|
||||
}
|
||||
}
|
||||
if(w.addTypes != null){
|
||||
wats = new int[w.addTypes.length];
|
||||
for (int j = 0; j < w.addTypes.length; j ++) {
|
||||
wats[j] = renderingTypes.getTypeByInternalId(w.addTypes[j]).getTargetId();
|
||||
}
|
||||
}
|
||||
MapData mapData = writer.writeMapData(0,
|
||||
quad.x << (31 - quad.zoom), quad.y << (31 - quad.zoom), false,
|
||||
bcoordinates.toByteArray(), null, type, null, null, null, dataBlock);
|
||||
w.coordinates, null, wts, wats, w.names, stringTable, dataBlock);
|
||||
if (mapData != null) {
|
||||
dataBlock.addDataObjects(mapData);
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeMapDataBlock(dataBlock, null, e.getValue());
|
||||
writer.writeMapDataBlock(dataBlock, stringTable, e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,7 +346,7 @@ public class BasemapProcessor {
|
|||
int xR = ((quadTree.x + 1) << (31 - quadTree.zoom)) - 1;
|
||||
int yT = (quadTree.y) << (31 - quadTree.zoom);
|
||||
int yB = ((quadTree.y + 1) << (31 - quadTree.zoom)) - 1;
|
||||
boolean defined = quadTree.coastlinesDefined(p);
|
||||
boolean defined = quadTree.dataIsDefined(p);
|
||||
boolean ocean = false;
|
||||
boolean land = false;
|
||||
if (!defined) {
|
||||
|
@ -355,88 +370,158 @@ public class BasemapProcessor {
|
|||
}
|
||||
|
||||
public void processEntity(Entity e) {
|
||||
if(e instanceof Way && "coastline".equals(e.getTag(OSMTagKey.NATURAL))) {
|
||||
processCoastline((Way) e);
|
||||
if (e instanceof Way || e instanceof Node) {
|
||||
for (int level = 0; level < mapZooms.getLevels().size(); level++) {
|
||||
renderingTypes.encodeEntityWithType(e, mapZooms.getLevel(level).getMaxZoom(), typeUse, addtypeUse, namesUse, tempNameUse);
|
||||
if (typeUse.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
MapZoomPair zoomPair = mapZooms.getLevel(level);
|
||||
if (e instanceof Way) {
|
||||
if(((Way) e).getNodes().size() < 2){
|
||||
continue;
|
||||
}
|
||||
if ("coastline".equals(e.getTag("natural")) || !Algoritms.isEmpty(e.getTag("admin_level"))) {
|
||||
splitContinuousWay(((Way) e).getNodes(), typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null,
|
||||
zoomPair, quadTrees[level]);
|
||||
} else {
|
||||
List<Node> ns = ((Way) e).getNodes();
|
||||
int z = getViewZoom(zoomPair);
|
||||
int tilex = 0;
|
||||
int tiley = 0;
|
||||
boolean sameTile = false;
|
||||
while (!sameTile) {
|
||||
tilex = (int) MapUtils.getTileNumberX(z, ns.get(0).getLongitude());
|
||||
tiley = (int) MapUtils.getTileNumberY(z, ns.get(0).getLatitude());
|
||||
sameTile = true;
|
||||
for (int i = 1; i < ns.size(); i++) {
|
||||
int tx = (int) MapUtils.getTileNumberX(z, ns.get(i).getLongitude());
|
||||
int ty = (int) MapUtils.getTileNumberY(z, ns.get(i).getLatitude());
|
||||
if (tx != tilex || ty != tiley) {
|
||||
sameTile = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sameTile) {
|
||||
z--;
|
||||
}
|
||||
}
|
||||
List<Node> res = new ArrayList<Node>();
|
||||
MapAlgorithms.simplifyDouglasPeucker(ns, zoomPair.getMaxZoom() - 1 + 8 + zoomWaySmothness, 3, res);
|
||||
addSimplisticData(res, typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null, zoomPair,
|
||||
quadTrees[level], z, tilex, tiley, namesUse.isEmpty() ? null : new LinkedHashMap<MapRenderingTypes.MapRulType, String>(namesUse));
|
||||
}
|
||||
} else {
|
||||
int z = getViewZoom(zoomPair);
|
||||
int tilex = (int) MapUtils.getTileNumberX(z, ((Node) e).getLongitude());
|
||||
int tiley = (int) MapUtils.getTileNumberY(z, ((Node) e).getLatitude());
|
||||
addSimplisticData(Collections.singletonList((Node)e), typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null, zoomPair,
|
||||
quadTrees[level], z, tilex, tiley, namesUse.isEmpty() ? null : new LinkedHashMap<MapRenderingTypes.MapRulType, String>(namesUse));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processCoastline(Way e) {
|
||||
renderingTypes.getCoastlineRuleType().updateFreq();
|
||||
int ij = 0;
|
||||
for(MapZoomPair zoomPair : mapZooms.getLevels()) {
|
||||
SimplisticQuadTree quadTree = quadTrees[ij++];
|
||||
int z = Math.min((zoomPair.getMinZoom() + zoomPair.getMaxZoom()) / 2 - 1, zoomPair.getMinZoom() + 1);
|
||||
List<Node> ns = e.getNodes();
|
||||
if(ns.size() < 2) {
|
||||
return;
|
||||
}
|
||||
int i = 1;
|
||||
Node prevNode = ns.get(0);
|
||||
int px31 = MapUtils.get31TileNumberX(prevNode.getLongitude());
|
||||
int py31 = MapUtils.get31TileNumberY(prevNode.getLatitude());
|
||||
while(i<ns.size()) {
|
||||
Way w = new Way(-1000);
|
||||
w.addNode(prevNode);
|
||||
int tilex = px31 >> (31 - z);
|
||||
int tiley = py31 >> (31 - z);
|
||||
boolean sameTile = true;
|
||||
wayConstruct : while(sameTile && i<ns.size()) {
|
||||
Node next = ns.get(i);
|
||||
int ntilex = (int) MapUtils.getTileNumberX(z, next.getLongitude());
|
||||
int ntiley = (int) MapUtils.getTileNumberY(z, next.getLatitude());
|
||||
if(ntilex == tilex && tiley == ntiley) {
|
||||
sameTile = true;
|
||||
w.addNode(next);
|
||||
prevNode = next;
|
||||
px31 = MapUtils.get31TileNumberX(prevNode.getLongitude());
|
||||
py31 = MapUtils.get31TileNumberY(prevNode.getLatitude());
|
||||
public void splitContinuousWay(List<Node> ns, int[] types, int[] addTypes, MapZoomPair zoomPair, SimplisticQuadTree quadTree) {
|
||||
int z = getViewZoom(zoomPair);
|
||||
int i = 1;
|
||||
Node prevNode = ns.get(0);
|
||||
int px31 = MapUtils.get31TileNumberX(prevNode.getLongitude());
|
||||
int py31 = MapUtils.get31TileNumberY(prevNode.getLatitude());
|
||||
while (i < ns.size()) {
|
||||
List<Node> w = new ArrayList<Node>();
|
||||
w.add(prevNode);
|
||||
int tilex = px31 >> (31 - z);
|
||||
int tiley = py31 >> (31 - z);
|
||||
boolean sameTile = true;
|
||||
wayConstruct: while (sameTile && i < ns.size()) {
|
||||
Node next = ns.get(i);
|
||||
int ntilex = (int) MapUtils.getTileNumberX(z, next.getLongitude());
|
||||
int ntiley = (int) MapUtils.getTileNumberY(z, next.getLatitude());
|
||||
if (ntilex == tilex && tiley == ntiley) {
|
||||
sameTile = true;
|
||||
w.add(next);
|
||||
prevNode = next;
|
||||
px31 = MapUtils.get31TileNumberX(prevNode.getLongitude());
|
||||
py31 = MapUtils.get31TileNumberY(prevNode.getLatitude());
|
||||
i++;
|
||||
} else {
|
||||
int nx31 = MapUtils.get31TileNumberX(next.getLongitude());
|
||||
int ny31 = MapUtils.get31TileNumberY(next.getLatitude());
|
||||
// increase boundaries to drop into another tile
|
||||
int leftX = (tilex << (31 - z)) - 1;
|
||||
int rightX = (tilex + 1) << (31 - z);
|
||||
if (rightX < 0) {
|
||||
rightX = Integer.MAX_VALUE;
|
||||
}
|
||||
int topY = (tiley << (31 - z)) - 1;
|
||||
int bottomY = (tiley + 1) << (31 - z);
|
||||
if (bottomY < 0) {
|
||||
bottomY = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
long inter = MapAlgorithms.calculateIntersection(px31, py31, nx31, ny31, leftX, rightX, bottomY, topY);
|
||||
int cy31 = (int) inter;
|
||||
int cx31 = (int) (inter >> 32l);
|
||||
if (inter == -1) {
|
||||
cx31 = nx31;
|
||||
cy31 = ny31;
|
||||
i++;
|
||||
} else {
|
||||
int nx31 = MapUtils.get31TileNumberX(next.getLongitude());
|
||||
int ny31 = MapUtils.get31TileNumberY(next.getLatitude());
|
||||
// increase boundaries to drop into another tile
|
||||
int leftX = (tilex << (31 - z)) - 1;
|
||||
int rightX = (tilex + 1) << (31 - z);
|
||||
if (rightX < 0) {
|
||||
rightX = Integer.MAX_VALUE;
|
||||
}
|
||||
int topY = (tiley << (31 - z)) - 1;
|
||||
int bottomY = (tiley + 1) << (31 - z);
|
||||
if (bottomY < 0) {
|
||||
bottomY = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
long inter = MapAlgorithms.calculateIntersection(px31, py31, nx31, ny31, leftX, rightX, bottomY, topY);
|
||||
int cy31 = (int) inter;
|
||||
int cx31 = (int) (inter >> 32l);
|
||||
if (inter == -1) {
|
||||
cx31 = nx31;
|
||||
cy31 = ny31;
|
||||
i++;
|
||||
logMapDataWarn.warn("Can't find intersection for " + MapUtils.get31LongitudeX(px31) + ","
|
||||
+ MapUtils.get31LatitudeY(py31) + " - " + +MapUtils.get31LongitudeX(nx31) + ","
|
||||
+ MapUtils.get31LatitudeY(ny31));
|
||||
}
|
||||
|
||||
prevNode = new Node(MapUtils.get31LatitudeY(cy31), MapUtils.get31LongitudeX(cx31), -1000);
|
||||
px31 = cx31;
|
||||
py31 = cy31;
|
||||
w.addNode(prevNode);
|
||||
break wayConstruct;
|
||||
logMapDataWarn.warn("Can't find intersection for " + MapUtils.get31LongitudeX(px31) + ","
|
||||
+ MapUtils.get31LatitudeY(py31) + " - " + MapUtils.get31LongitudeX(nx31) + ","
|
||||
+ MapUtils.get31LatitudeY(ny31));
|
||||
}
|
||||
|
||||
prevNode = new Node(MapUtils.get31LatitudeY(cy31), MapUtils.get31LongitudeX(cx31), -1000);
|
||||
px31 = cx31;
|
||||
py31 = cy31;
|
||||
w.add(prevNode);
|
||||
break wayConstruct;
|
||||
}
|
||||
SimplisticQuadTree quad = quadTree.getOrCreateSubTree(tilex, tiley, z);
|
||||
if (quad == null) {
|
||||
if (logMapDataWarn != null) {
|
||||
logMapDataWarn.error("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
|
||||
} else {
|
||||
System.err.println("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
|
||||
}
|
||||
}
|
||||
quad.addCoastline(zoomPair, w);
|
||||
|
||||
}
|
||||
List<Node> res = new ArrayList<Node>();
|
||||
MapAlgorithms.simplifyDouglasPeucker(w, zoomPair.getMaxZoom() - 1 + 8 + zoomWaySmothness, 3, res);
|
||||
addSimplisticData(res, types, addTypes, zoomPair, quadTree, z, tilex, tiley, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSimplisticData(List<Node> res, int[] types, int[] addTypes, MapZoomPair zoomPair, SimplisticQuadTree quadTree, int z, int tilex,
|
||||
int tiley, Map<MapRulType, String> names) {
|
||||
SimplisticQuadTree quad = quadTree.getOrCreateSubTree(tilex, tiley, z);
|
||||
if (quad == null) {
|
||||
if (logMapDataWarn != null) {
|
||||
logMapDataWarn.error("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
|
||||
} else {
|
||||
System.err.println("Tile " + tilex + " / " + tiley + " at " + z + " can not be found");
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream bcoordinates = new ByteArrayOutputStream();
|
||||
for (Node n : res) {
|
||||
if (n != null) {
|
||||
int y = MapUtils.get31TileNumberY(n.getLatitude());
|
||||
int x = MapUtils.get31TileNumberX(n.getLongitude());
|
||||
try {
|
||||
Algoritms.writeInt(bcoordinates, x);
|
||||
Algoritms.writeInt(bcoordinates, y);
|
||||
} catch (IOException e1) {
|
||||
throw new IllegalStateException(e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
SimplisticBinaryData data = new SimplisticBinaryData();
|
||||
// not needed
|
||||
// data.id = w.getId();
|
||||
data.coordinates = bcoordinates.toByteArray();
|
||||
data.types = types;
|
||||
data.addTypes = addTypes;
|
||||
data.names = names;
|
||||
quad.addQuadData(zoomPair, data);
|
||||
}
|
||||
|
||||
private int getViewZoom(MapZoomPair zoomPair) {
|
||||
return Math.min((zoomPair.getMinZoom() + zoomPair.getMaxZoom()) / 2 - 1, zoomPair.getMinZoom() + 1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -352,8 +352,8 @@ public class BinaryMapIndexWriter {
|
|||
|
||||
private TByteArrayList mapDataBuf = new TByteArrayList();
|
||||
|
||||
public MapData writeMapData(long diffId, int pleft, int ptop, boolean area, byte[] coordinates, byte[] innerPolygonTypes, TIntArrayList typeUse,
|
||||
TIntArrayList addtypeUse, Map<MapRulType, String> names, Map<String, Integer> stringTable, MapDataBlock.Builder dataBlock)
|
||||
public MapData writeMapData(long diffId, int pleft, int ptop, boolean area, byte[] coordinates, byte[] innerPolygonTypes, int[] typeUse,
|
||||
int[] addtypeUse, Map<MapRulType, String> names, Map<String, Integer> stringTable, MapDataBlock.Builder dataBlock)
|
||||
throws IOException {
|
||||
|
||||
MapData.Builder data = MapData.newBuilder();
|
||||
|
@ -409,16 +409,16 @@ public class BinaryMapIndexWriter {
|
|||
}
|
||||
|
||||
mapDataBuf.clear();
|
||||
for (int i = 0; i < typeUse.size() ; i++) {
|
||||
writeRawVarint32(mapDataBuf, typeUse.get(i));;
|
||||
for (int i = 0; i < typeUse.length ; i++) {
|
||||
writeRawVarint32(mapDataBuf, typeUse[i]);
|
||||
}
|
||||
data.setTypes(ByteString.copyFrom(mapDataBuf.toArray()));
|
||||
TYPES_SIZE += CodedOutputStream.computeTagSize(OsmandOdb.MapData.TYPES_FIELD_NUMBER)
|
||||
+ CodedOutputStream.computeRawVarint32Size(mapDataBuf.size()) + mapDataBuf.size();
|
||||
if (addtypeUse != null && addtypeUse.size() > 0) {
|
||||
if (addtypeUse != null && addtypeUse.length > 0) {
|
||||
mapDataBuf.clear();
|
||||
for (int i = 0; i < addtypeUse.size() ; i++) {
|
||||
writeRawVarint32(mapDataBuf, addtypeUse.get(i));;
|
||||
for (int i = 0; i < addtypeUse.length ; i++) {
|
||||
writeRawVarint32(mapDataBuf, addtypeUse[i]);
|
||||
}
|
||||
data.setAdditionalTypes(ByteString.copyFrom(mapDataBuf.toArray()));
|
||||
TYPES_SIZE += CodedOutputStream.computeTagSize(OsmandOdb.MapData.ADDITIONALTYPES_FIELD_NUMBER);
|
||||
|
|
|
@ -241,7 +241,9 @@ public class IndexCreator {
|
|||
|
||||
@Override
|
||||
public boolean acceptEntityToLoad(OsmBaseStorage storage, EntityId entityId, Entity entity) {
|
||||
indexAddressCreator.registerCityIfNeeded(entity);
|
||||
if(indexAddressCreator != null) {
|
||||
indexAddressCreator.registerCityIfNeeded(entity);
|
||||
}
|
||||
// accept to allow db creator parse it
|
||||
return true;
|
||||
}
|
||||
|
@ -275,11 +277,11 @@ public class IndexCreator {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean createPlainOsmDb(IProgress progress, File readFile, IOsmStorageFilter addFilter) throws SQLException, FileNotFoundException, IOException, SAXException{
|
||||
private boolean createPlainOsmDb(IProgress progress, File readFile, IOsmStorageFilter addFilter, boolean deletePrevious) throws SQLException, FileNotFoundException, IOException, SAXException{
|
||||
// dbFile = new File(workingDir, TEMP_NODES_DB);
|
||||
// initialize db file
|
||||
boolean loadFromExistingFile = dbFile != null && dialect.databaseFileExists(dbFile);
|
||||
if (dbFile == null) {
|
||||
boolean loadFromExistingFile = dbFile != null && dialect.databaseFileExists(dbFile) && !deletePrevious;
|
||||
if (dbFile == null || deletePrevious) {
|
||||
dbFile = new File(workingDir, TEMP_NODES_DB);
|
||||
// to save space
|
||||
if (dialect.databaseFileExists(dbFile)) {
|
||||
|
@ -362,7 +364,7 @@ public class IndexCreator {
|
|||
|
||||
for (File readFile : readFiles) {
|
||||
this.accessor = new OsmDbAccessor();
|
||||
createPlainOsmDb(progress, readFile, addFilter);
|
||||
createPlainOsmDb(progress, readFile, addFilter, true);
|
||||
// 2. Create index connections and index structure
|
||||
|
||||
progress.setGeneralProgress("[50 / 100]");
|
||||
|
@ -398,7 +400,7 @@ public class IndexCreator {
|
|||
|
||||
progress.setGeneralProgress("[95 of 100]");
|
||||
progress.startTask("Writing map index to binary file...", -1);
|
||||
processor.writeCoastlinesFile(writer, regionName);
|
||||
processor.writeBasemapFile(writer, regionName);
|
||||
progress.finishTask();
|
||||
writer.close();
|
||||
mapRAFile.close();
|
||||
|
@ -460,7 +462,7 @@ public class IndexCreator {
|
|||
try {
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// 1. creating nodes db to fast access for all nodes and simply import all relations, ways, nodes to it
|
||||
boolean loadFromExistingFile = createPlainOsmDb(progress, readFile, addFilter);
|
||||
boolean loadFromExistingFile = createPlainOsmDb(progress, readFile, addFilter, false);
|
||||
|
||||
// do not create temp map file and rtree files
|
||||
if (recreateOnlyBinaryFile) {
|
||||
|
@ -715,18 +717,24 @@ public class IndexCreator {
|
|||
creator.setZoomWaySmothness(2);
|
||||
MapRenderingTypes rt = MapRenderingTypes.getDefault();// new MapRenderingTypes("/home/victor/projects/OsmAnd/data/testdata/roads_rendering_types.xml");
|
||||
MapZooms zooms = MapZooms.getDefault(); // MapZooms.parseZooms("15-");
|
||||
creator.setNodesDBFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/nodes.tmp.odb"));
|
||||
// creator.setNodesDBFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/nodes.tmp.odb"));
|
||||
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/luxembourg.osm.pbf"),
|
||||
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/cuba2.osm.bz2"),
|
||||
// new ConsoleProgressImplementation(1), null, zooms, rt, log);
|
||||
// ;6-8;9-14
|
||||
zooms = MapZooms.parseZooms("1-3;4-6;7-9;10-");
|
||||
creator.setMapFileName("basemap_coastlines.obf");
|
||||
|
||||
// zooms = MapZooms.parseZooms("1-3;4-6;7-9;10-");
|
||||
// creator.setMapFileName("basemap_coastlines.obf");
|
||||
zooms = MapZooms.parseZooms("1-3;4-5;6-7;8-9;10-");
|
||||
creator.setMapFileName("basemap_a.obf");
|
||||
|
||||
File basemapParent = new File("/home/victor/projects/OsmAnd/data/basemap");
|
||||
creator.generateBasemapIndex(new ConsoleProgressImplementation(1), null, zooms, rt, log, "basemap",
|
||||
new File("/home/victor/projects/OsmAnd/data/basemap/10m_coastline_out.osm"));
|
||||
|
||||
|
||||
|
||||
new File(basemapParent, "10m_coastline_out.osm"),
|
||||
new File(basemapParent, "10m_admin_level_out.osm"),
|
||||
new File(basemapParent, "10m_rivers.osm"),
|
||||
new File(basemapParent, "10m_lakes_out.osm"),
|
||||
new File(basemapParent, "10m_populated_places_out.osm")
|
||||
);
|
||||
// world generation
|
||||
// MapZooms mapZooms = new MapZooms();
|
||||
// MapZoomPair pair1 = new MapZooms.MapZoomPair(1, 3);
|
||||
|
|
|
@ -2,7 +2,6 @@ package net.osmand.data.preparation;
|
|||
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||
import gnu.trove.procedure.TObjectProcedure;
|
||||
import gnu.trove.set.hash.TLongHashSet;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -27,7 +26,6 @@ import net.osmand.binary.OsmandOdb.MapData;
|
|||
import net.osmand.binary.OsmandOdb.MapDataBlock;
|
||||
import net.osmand.data.Boundary;
|
||||
import net.osmand.data.MapAlgorithms;
|
||||
import net.osmand.data.WayBoundary;
|
||||
import net.osmand.osm.Entity;
|
||||
import net.osmand.osm.Entity.EntityId;
|
||||
import net.osmand.osm.Entity.EntityType;
|
||||
|
@ -35,7 +33,6 @@ import net.osmand.osm.MapRenderingTypes;
|
|||
import net.osmand.osm.MapRenderingTypes.MapRulType;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.osmand.osm.Node;
|
||||
import net.osmand.osm.WayChain;
|
||||
import net.osmand.osm.OSMSettings.OSMTagKey;
|
||||
import net.osmand.osm.Relation;
|
||||
import net.osmand.osm.Way;
|
||||
|
@ -72,9 +69,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
List<MapRulType> tempNameUse = new ArrayList<MapRenderingTypes.MapRulType>();
|
||||
Map<MapRulType, String> namesUse = new LinkedHashMap<MapRenderingTypes.MapRulType, String>();
|
||||
TIntArrayList addtypeUse = new TIntArrayList(8);
|
||||
List<Long> restrictionsUse = new ArrayList<Long>(8);
|
||||
|
||||
private BasemapProcessor basemapProcessor;
|
||||
private PreparedStatement mapBinaryStat;
|
||||
private PreparedStatement mapLowLevelBinaryStat;
|
||||
private int lowLevelWays = -1;
|
||||
|
@ -91,7 +86,6 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
this.mapZooms = mapZooms;
|
||||
this.zoomWaySmothness = zoomWaySmothness;
|
||||
this.renderingTypes = renderingTypes;
|
||||
this.basemapProcessor = new BasemapProcessor(logMapDataWarn, mapZooms, renderingTypes, zoomWaySmothness);
|
||||
lowLevelWays = -1;
|
||||
}
|
||||
|
||||
|
@ -208,13 +202,13 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
List<Node> outerWay = outerWaySrc;
|
||||
int zoomToSimplify = mapZooms.getLevel(level).getMaxZoom() - 1;
|
||||
if (zoomToSimplify < 15) {
|
||||
outerWay = simplifyCycleWay(outerWay, zoomToSimplify);
|
||||
outerWay = simplifyCycleWay(outerWay, zoomToSimplify, zoomWaySmothness);
|
||||
if (outerWay == null) {
|
||||
continue nextZoom;
|
||||
}
|
||||
List<List<Node>> newinnerWays = new ArrayList<List<Node>>();
|
||||
for (List<Node> ls : innerWays) {
|
||||
ls = simplifyCycleWay(ls, zoomToSimplify);
|
||||
ls = simplifyCycleWay(ls, zoomToSimplify, zoomWaySmothness);
|
||||
if (ls != null) {
|
||||
newinnerWays.add(ls);
|
||||
}
|
||||
|
@ -299,7 +293,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
}
|
||||
}
|
||||
|
||||
protected List<Node> simplifyCycleWay(List<Node> ns, int zoom) throws SQLException {
|
||||
public static List<Node> simplifyCycleWay(List<Node> ns, int zoom, int zoomWaySmothness) throws SQLException {
|
||||
if (checkForSmallAreas(ns, zoom + Math.min(zoomWaySmothness / 2, 3), 2, 4)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -339,7 +333,6 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
}
|
||||
|
||||
public void processingLowLevelWays(IProgress progress) throws SQLException {
|
||||
restrictionsUse.clear();
|
||||
mapLowLevelBinaryStat.executeBatch();
|
||||
mapLowLevelBinaryStat.close();
|
||||
pStatements.remove(mapLowLevelBinaryStat);
|
||||
|
@ -473,7 +466,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
|
||||
}
|
||||
|
||||
private boolean checkForSmallAreas(List<Node> nodes, int zoom, int minz, int maxz) {
|
||||
private static boolean checkForSmallAreas(List<Node> nodes, int zoom, int minz, int maxz) {
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
|
@ -529,7 +522,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
if (zoomToSimplify < 15) {
|
||||
boolean cycle = ((Way) e).getFirstNodeId() == ((Way) e).getLastNodeId();
|
||||
if (cycle) {
|
||||
res = simplifyCycleWay(((Way) e).getNodes(), zoomToSimplify);
|
||||
res = simplifyCycleWay(((Way) e).getNodes(), zoomToSimplify, zoomWaySmothness);
|
||||
} else {
|
||||
String ename = namesUse.get(renderingTypes.getNameRuleType());
|
||||
insertLowLevelMapBinaryObject(level, zoomToSimplify, typeUse, addtypeUse, id, ((Way) e).getNodes(), ename);
|
||||
|
@ -652,17 +645,17 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
|
|||
tempNames.clear();
|
||||
decodeNames(rs.getString(6), tempNames);
|
||||
byte[] types = rs.getBytes(4);
|
||||
typeUse.clear();
|
||||
int[] typeUse = new int[types.length / 2];
|
||||
for (int j = 0; j < types.length; j += 2) {
|
||||
int ids = Algoritms.parseSmallIntFromBytes(types, j);
|
||||
typeUse.add(renderingTypes.getTypeByInternalId(ids).getTargetId());
|
||||
typeUse[j / 2] = renderingTypes.getTypeByInternalId(ids).getTargetId();
|
||||
}
|
||||
byte[] addTypes = rs.getBytes(5);
|
||||
addtypeUse.clear();
|
||||
int[] addtypeUse = new int[addTypes.length / 2];
|
||||
if (addTypes != null) {
|
||||
for (int j = 0; j < addTypes.length; j += 2) {
|
||||
int ids = Algoritms.parseSmallIntFromBytes(addTypes, j);
|
||||
addtypeUse.add(renderingTypes.getTypeByInternalId(ids).getTargetId());
|
||||
addtypeUse[j / 2] = renderingTypes.getTypeByInternalId(ids).getTargetId();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,8 @@
|
|||
<!-- point has order 128 -->
|
||||
<filter tag="" value="" point="true" order="128" objectType="1"/>
|
||||
<!-- default polygon -->
|
||||
<filter cycle="true" layer="-1" tag="" value="" order="1" objectType="3"/>
|
||||
<filter area="true" layer="-1" tag="" value="" order="1" objectType="3"/>
|
||||
<filter cycle="true" layer="-1" tag="" value="" order="3" objectType="3"/>
|
||||
<filter area="true" layer="-1" tag="" value="" order="3" objectType="3"/>
|
||||
<!-- default line -->
|
||||
<filter layer="-1" tag="" value="" order="10" objectType="2"/>
|
||||
<filter tag="" value="" order="11" objectType="2"/>
|
||||
|
@ -229,13 +229,13 @@
|
|||
|
||||
<filter tag="landuse" value="reservoir" order="5"/>
|
||||
<filter tag="landuse" value="water" order="5"/>
|
||||
<filter tag="landuse" value="" order="1"/>
|
||||
<filter tag="landuse" value="" order="3"/>
|
||||
|
||||
<filter tag="natural" value="water" order="5"/>
|
||||
<filter tag="natural" value="bay" order="5"/>
|
||||
<filter tag="natural" value="land" order="6"/>
|
||||
<filter tag="natural" value="land" order="2"/>
|
||||
<filter tag="natural" value="coastline" order="1"/>
|
||||
<filter tag="natural" value="" order="1"/>
|
||||
<filter tag="natural" value="" order="3"/>
|
||||
</group>
|
||||
|
||||
|
||||
|
|
|
@ -374,14 +374,14 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
String coastlineTime = "";
|
||||
boolean addBasemapCoastlines = zoom <= BASEMAP_ZOOM;
|
||||
boolean addBasemapCoastlines = true;
|
||||
boolean emptyData = zoom > BASEMAP_ZOOM && tempResult.isEmpty() && coastLines.isEmpty() ;
|
||||
|
||||
if(!coastLines.isEmpty()) {
|
||||
long ms = System.currentTimeMillis();
|
||||
List<BinaryMapDataObject> pcoastlines = processCoastlines(coastLines, leftX, rightX, bottomY, topY, zoom,
|
||||
basemapCoastLines.isEmpty());
|
||||
addBasemapCoastlines = pcoastlines.isEmpty() || addBasemapCoastlines;
|
||||
addBasemapCoastlines = pcoastlines.isEmpty() || zoom <= BASEMAP_ZOOM;
|
||||
tempResult.addAll(pcoastlines);
|
||||
coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )";
|
||||
} else if(basemapCoastLines.isEmpty() && mi != null){
|
||||
|
@ -397,10 +397,16 @@ public class MapRenderRepositories {
|
|||
coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )";
|
||||
}
|
||||
if(emptyData && tempResult.size() > 0){
|
||||
BinaryMapDataObject o = tempResult.get(0);
|
||||
// message
|
||||
BinaryMapDataObject p = tempResult.get(0);
|
||||
// avoid overflow int errors
|
||||
BinaryMapDataObject o = new BinaryMapDataObject(new int[] { leftX + (rightX - leftX) / 2, topY + (bottomY - topY) / 2 },
|
||||
new int[] { p.getMapIndex().coastlineEncodingType }, null, -1);
|
||||
o.setMapIndex(p.getMapIndex());
|
||||
o.putObjectName(o.getMapIndex().nameEncodingType, context.getString(R.string.switch_to_raster_map_to_see));
|
||||
tempResult.add(o);
|
||||
}
|
||||
if(zoom <= BASEMAP_ZOOM || tempResult.isEmpty()) {
|
||||
if(zoom <= BASEMAP_ZOOM || emptyData) {
|
||||
tempResult.addAll(basemapResult);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue