Fix basemap rendering

This commit is contained in:
Victor Shcherb 2012-04-10 00:40:09 +02:00
parent 3867c3ef57
commit 4367dda5a4
7 changed files with 245 additions and 153 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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>

View file

@ -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);
}