Routing update

This commit is contained in:
Victor Shcherb 2012-06-13 12:00:12 +02:00
parent eae0274b0b
commit 64605e8561
12 changed files with 321 additions and 531 deletions

View file

@ -82,6 +82,7 @@ public class IndexBatchCreator {
boolean indexTransport = false;
boolean indexAddress = false;
boolean indexMap = false;
boolean indexRouting = false;
private String wget;
@ -147,6 +148,8 @@ public class IndexBatchCreator {
indexPOI = Boolean.parseBoolean(process.getAttribute("indexPOI"));
indexMap = Boolean.parseBoolean(process.getAttribute("indexMap"));
indexRouting = process.getAttribute("indexRouting") == null ||
process.getAttribute("indexRouting").equalsIgnoreCase("true");
indexTransport = Boolean.parseBoolean(process.getAttribute("indexTransport"));
indexAddress = Boolean.parseBoolean(process.getAttribute("indexAddress"));
parseProcessAttributes(process);
@ -432,6 +435,7 @@ public class IndexBatchCreator {
indexCreator.setIndexPOI(indexPOI);
indexCreator.setIndexTransport(indexTransport);
indexCreator.setIndexMap(indexMap);
indexCreator.setIndexRouting(indexRouting);
indexCreator.setLastModifiedDate(f.lastModified());
indexCreator.setNormalizeStreets(true);
indexCreator.setRegionName(rName);

View file

@ -130,6 +130,7 @@ public class WikiIndexer {
IndexCreator ic = new IndexCreator(workPath);
ic.setIndexPOI(true);
ic.setIndexMap(false);
ic.setIndexRouting(false);
ic.setIndexTransport(false);
ic.setIndexAddress(false);
ic.generateIndexes(outFile, new ConsoleProgressImplementation(3), null, null, null, log);

View file

@ -13,7 +13,7 @@
-->
<!-- zoomWaySmoothness - 1-4, typical mapZooms - 8-10;11-12;13-14;15 -->
<process directory_for_osm_files="/home/..." directory_for_index_files="/home/..." directory_for_generation="/home/..."
skipExistingIndexesAt="/home/..." indexPOI="true" indexMap="true" indexTransport="true" indexAddress="true">
skipExistingIndexesAt="/home/..." indexPOI="true" indexRouting="true" indexMap="true" indexTransport="true" indexAddress="true">
<!-- Add wget="C:/Program Files/GNUWin32/bin/wget.exe" to process, to use wget for download.
On linux systems if wget is in your path it can be wget="wget" or you can make own script with wget command:
wget="/path/to/script/wget.sh"

View file

@ -730,22 +730,22 @@ public class IndexCreator {
public static void main(String[] args) throws IOException, SAXException, SQLException, InterruptedException {
long time = System.currentTimeMillis();
IndexCreator creator = new IndexCreator(new File("/home/victor/projects/OsmAnd/data/osm-gen/")); //$NON-NLS-1$
creator.setIndexMap(false);
creator.setIndexAddress(false);
creator.setIndexPOI(false);
creator.setIndexTransport(false);
creator.setIndexMap(true);
creator.setIndexAddress(true);
creator.setIndexPOI(true);
creator.setIndexTransport(true);
creator.setIndexRouting(true);
// creator.deleteDatabaseIndexes = false;
// creator.recreateOnlyBinaryFile = true;
// creator.deleteOsmDB = false;
creator.setZoomWaySmothness(2);
MapRenderingTypes rt = MapRenderingTypes.getDefault();
MapZooms zooms = MapZooms.getDefault(); // MapZooms.parseZooms("15-");
creator.setNodesDBFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/nodes.tmp.odb"));
creator.generateIndexes(new File("/home/victor/projects/OsmAnd/temp/map.osm"),
// creator.setNodesDBFile(new File("/home/victor/projects/OsmAnd/data/osm-gen/nodes.tmp.odb"));
// creator.generateIndexes(new File("/home/victor/projects/OsmAnd/temp/map.osm"),
creator.generateIndexes(new File("/home/victor/projects/OsmAnd/data/osm-maps/RU-SPE.osm.bz2"),
new ConsoleProgressImplementation(1), null, zooms, rt, log);

View file

@ -1,15 +1,16 @@
package net.osmand.data.preparation;
import gnu.trove.list.TLongList;
import gnu.trove.list.array.TLongArrayList;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@ -19,47 +20,28 @@ import net.osmand.osm.Entity;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import com.anvisics.jleveldb.ArraySerializer;
import com.anvisics.jleveldb.ArraySerializer.EntityValueTokenizer;
import com.anvisics.jleveldb.ext.DBAccessor;
import com.anvisics.jleveldb.ext.DBIterator;
import com.anvisics.jleveldb.ext.ReadOptions;
public class OsmDbAccessor implements OsmDbAccessorContext {
private static final Log log = LogFactory.getLog(OsmDbAccessor.class);
//private static final Log log = LogFactory.getLog(OsmDbAccessor.class);
private PreparedStatement pselectNode;
private PreparedStatement pselectWay;
private PreparedStatement pselectRelation;
private PreparedStatement pselectTags;
private int allRelations;
private int allBoundaries;
private int allWays;
private int allNodes;
private int allBoundaries;
private boolean realCounts = false;
private Connection dbConn;
private DBDialect dialect;
// leveldb
private ReadOptions randomAccessOptions;
private DBAccessor accessor;
private PreparedStatement iterateNodes;
private PreparedStatement iterateWays;
private PreparedStatement iterateRelations;
private PreparedStatement iterateWayBoundaries;
public interface OsmDbVisitor {
@ -76,26 +58,22 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
this.allWays = allWays;
this.allRelations = allRelations;
if(this.dialect == DBDialect.NOSQL){
accessor = (DBAccessor) dbConnection;
randomAccessOptions = new ReadOptions();
throw new UnsupportedOperationException();
} else {
this.dbConn = (Connection) dbConnection;
pselectNode = dbConn.prepareStatement("select n.latitude, n.longitude, t.skeys, t.value from node n left join tags t on n.id = t.id and t.type = 0 where n.id = ?"); //$NON-NLS-1$
pselectWay = dbConn.prepareStatement("select w.node, w.ord, t.skeys, t.value, n.latitude, n.longitude " + //$NON-NLS-1$
"from ways w left join tags t on w.id = t.id and t.type = 1 and w.ord = 0 left join node n on w.node = n.id " + //$NON-NLS-1$
"where w.id = ? order by w.ord"); //$NON-NLS-1$
pselectRelation = dbConn.prepareStatement("select r.member, r.type, r.role, r.ord, t.skeys, t.value " + //$NON-NLS-1$
"from relations r left join tags t on r.id = t.id and t.type = 2 and r.ord = 0 " + //$NON-NLS-1$
"where r.id = ? order by r.ord"); //$NON-NLS-1$
pselectTags = dbConn.prepareStatement("select skeys, value from tags where id = ? and type = ?"); //$NON-NLS-1$
pselectNode = dbConn.prepareStatement("select n.latitude, n.longitude, n.tags from node n where n.id = ?"); //$NON-NLS-1$
pselectWay = dbConn.prepareStatement("select w.node, w.ord, w.tags, n.latitude, n.longitude, n.tags " + //$NON-NLS-1$
"from ways w left join node n on w.node = n.id where w.id = ? order by w.ord"); //$NON-NLS-1$
pselectRelation = dbConn.prepareStatement("select r.member, r.type, r.role, r.ord, r.tags " + //$NON-NLS-1$
"from relations r where r.id = ? order by r.ord"); //$NON-NLS-1$
iterateNodes = dbConn.prepareStatement("select n.id, n.latitude, n.longitude, t.skeys, t.value from node n inner join tags t on n.id = t.id and t.type = 0 order by n.id"); //$NON-NLS-1$
iterateWays = dbConn.prepareStatement("select w.id, w.node, w.ord, t.skeys, t.value, n.latitude, n.longitude " + //$NON-NLS-1$
"from ways w left join tags t on w.id = t.id and t.type = 1 and w.ord = 0 left join node n on w.node = n.id " + //$NON-NLS-1$
"order by w.id, w.ord"); //$NON-NLS-1$
iterateWayBoundaries = dbConn.prepareStatement("select t.id from tags t where t.skeys = \"" + OSMTagKey.BOUNDARY.getValue() + "\""); //$NON-NLS-1$
iterateRelations = dbConn.prepareStatement("select r.id, t.skeys, t.value from relations r inner join tags t on t.id = r.id and t.type = 2 and r.ord = 0"); //$NON-NLS-1$
iterateNodes = dbConn.prepareStatement("select n.id, n.latitude, n.longitude, n.tags from node n where length(n.tags) > 0"); //$NON-NLS-1$
iterateWays = dbConn.prepareStatement("select w.id, w.node, w.ord, w.tags, n.latitude, n.longitude, n.tags " + //$NON-NLS-1$
"from ways w left join node n on w.node = n.id order by w.id, w.ord"); //$NON-NLS-1$
iterateWayBoundaries = dbConn.prepareStatement("select w.id, w.node, w.ord, w.tags, n.latitude, n.longitude, n.tags " + //$NON-NLS-1$
"from ways w left join node n on w.node = n.id where w.boundary > 0 order by w.id, w.ord"); //$NON-NLS-1$
iterateRelations = dbConn.prepareStatement("select r.id, r.tags from relations r where length(r.tags) > 0"); //$NON-NLS-1$
}
}
@ -111,171 +89,134 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
return allWays;
}
@Override
public void loadEntityRelation(Relation e) throws SQLException {
loadEntityData(e);
}
@Override
public void loadEntityWay(Way e) throws SQLException {
loadEntityData(e);
}
public void loadEntityData(Entity e) throws SQLException {
if (e.isDataLoaded()) { //data was already loaded, nothing to do
return;
}
if(dialect == DBDialect.NOSQL){
loadEntityDataNoSQL(e);
e.entityDataLoaded();
return;
}
Map<EntityId, Entity> map = new LinkedHashMap<EntityId, Entity>();
if (e instanceof Relation && ((Relation) e).getMemberIds().isEmpty()) {
pselectRelation.setLong(1, e.getId());
if (pselectRelation.execute()) {
ResultSet rs = pselectRelation.getResultSet();
boolean first = true;
while (rs.next()) {
int ord = rs.getInt(4);
if (ord > 0 || first) {
first = false;
((Relation) e).addMember(rs.getLong(1), EntityType.values()[rs.getInt(2)], rs.getString(3));
}
}
rs.close();
}
} else if (e instanceof Way && ((Way) e).getEntityIds().isEmpty()) {
if (e.getEntityIds().isEmpty()) {
pselectWay.setLong(1, e.getId());
if (pselectWay.execute()) {
ResultSet rs = pselectWay.getResultSet();
boolean first = true;
while (rs.next()) {
int ord = rs.getInt(2);
if (ord > 0 || first) {
first = false;
if(rs.getObject(5) != null) {
((Way) e).addNode(new Node(rs.getDouble(5), rs.getDouble(6), rs.getLong(1)));
} else {
((Way) e).addNode(rs.getLong(1));
}
if (ord == 0) {
readTags(e, rs.getBytes(3));
}
if (rs.getObject(5) != null) {
Node n = new Node(rs.getDouble(4), rs.getDouble(5), rs.getLong(1));
((Way) e).addNode(n);
readTags(n, rs.getBytes(6));
} else {
((Way) e).addNode(rs.getLong(1));
}
}
rs.close();
}
}
Collection<EntityId> ids = e instanceof Relation ? ((Relation) e).getMemberIds() : ((Way) e).getEntityIds();
for (EntityId i : ids) {
// pselectNode = dbConn.prepareStatement("select n.latitude, n.longitude, t.skeys, t.value from node n left join tags t on n.id = t.id and t.type = 0 where n.id = ?");
if (i.getType() == EntityType.NODE) {
pselectNode.setLong(1, i.getId());
if (pselectNode.execute()) {
ResultSet rs = pselectNode.getResultSet();
Node n = null;
while (rs.next()) {
if (n == null) {
n = new Node(rs.getDouble(1), rs.getDouble(2), i.getId());
}
if (rs.getObject(3) != null) {
n.putTag(rs.getString(3), rs.getString(4));
}
}
@Override
public void loadEntityRelation(Relation e) throws SQLException {
loadEntityRelation(e, 1);
}
public void loadEntityRelation(Relation e, int level) throws SQLException {
if (e.isDataLoaded()) { //data was already loaded, nothing to do
return;
}
Map<EntityId, Entity> map = new LinkedHashMap<EntityId, Entity>();
if (e.getMemberIds().isEmpty()) {
pselectRelation.setLong(1, e.getId());
if (pselectRelation.execute()) {
ResultSet rs = pselectRelation.getResultSet();
while (rs.next()) {
int ord = rs.getInt(4);
if (ord == 0 ) {
readTags(e, rs.getBytes(5));
}
map.put(i, n);
rs.close();
}
} else if (i.getType() == EntityType.WAY) {
// pselectWay = dbConn.prepareStatement("select w.node, w.ord, t.skeys, t.value, n.latitude, n.longitude " +
// "from ways w left join tags t on w.id = t.id and t.type = 1 and w.ord = 0 inner join node n on w.node = n.id " +
// "where w.id = ? order by w.ord");
pselectWay.setLong(1, i.getId());
if (pselectWay.execute()) {
ResultSet rs = pselectWay.getResultSet();
Way way = new Way(i.getId());
map.put(i, way);
boolean first = true;
while (rs.next()) {
int ord = rs.getInt(2);
if (ord > 0 || first) {
first = false;
if(rs.getObject(5) != null) {
way.addNode(new Node(rs.getDouble(5), rs.getDouble(6), rs.getLong(1)));
} else {
way.addNode(rs.getLong(1));
}
}
if (ord == 0 && rs.getObject(3) != null) {
way.putTag(rs.getString(3), rs.getString(4));
}
}
rs.close();
}
} else if (i.getType() == EntityType.RELATION) {
pselectRelation.setLong(1, i.getId());
// pselectRelation = dbConn.prepareStatement("select r.member, r.type, r.role, r.ord, t.skeys, t.value" +
// "from relations r left join tags t on r.id = t.id and t.type = 2 and r.ord = 0 " +
// "where r.id = ? order by r.ord");
if (pselectRelation.execute()) {
ResultSet rs = pselectRelation.getResultSet();
Relation rel = new Relation(i.getId());
map.put(i, rel);
boolean first = true;
while (rs.next()) {
int ord = rs.getInt(4);
if (ord > 0 || first) {
first = false;
rel.addMember(rs.getLong(1), EntityType.values()[rs.getInt(2)], rs.getString(3));
}
if (ord == 0 && rs.getObject(5) != null) {
rel.putTag(rs.getString(5), rs.getString(6));
}
}
// do not load relation members recursively ? It is not needed for transport, address, poi before
rs.close();
e.addMember(rs.getLong(1), EntityType.values()[rs.getInt(2)], rs.getString(3));
}
rs.close();
}
}
Collection<EntityId> ids = e.getMemberIds() ;
if (level > 0) {
for (EntityId i : ids) {
if (i.getType() == EntityType.NODE) {
pselectNode.setLong(1, i.getId());
if (pselectNode.execute()) {
ResultSet rs = pselectNode.getResultSet();
Node n = null;
while (rs.next()) {
if (n == null) {
n = new Node(rs.getDouble(1), rs.getDouble(2), i.getId());
readTags(n, rs.getBytes(3));
}
}
map.put(i, n);
rs.close();
}
} else if (i.getType() == EntityType.WAY) {
Way way = new Way(i.getId());
loadEntityWay(way);
map.put(i, way);
} else if (i.getType() == EntityType.RELATION) {
Relation rel = new Relation(i.getId());
loadEntityRelation(rel, level - 1);
map.put(i, rel);
}
}
e.initializeLinks(map);
e.entityDataLoaded();
e.initializeLinks(map);
e.entityDataLoaded();
}
}
public void readTags(Entity e, byte[] tags){
if (tags != null) {
try {
int prev = 0;
List<String> vs = new ArrayList<String>();
for (int i = 0; i < tags.length; i++) {
if (tags[i] == 0) {
vs.add(new String(tags, prev, i - prev, "UTF-8"));
prev = i + 1;
}
}
for(int i=0; i<vs.size(); i+=2) {
e.putTag(vs.get(i), vs.get(i+1));
}
} catch (UnsupportedEncodingException e1) {
throw new RuntimeException(e1);
}
}
}
public int iterateOverEntities(IProgress progress, EntityType type, OsmDbVisitor visitor) throws SQLException, InterruptedException {
if(dialect == DBDialect.NOSQL){
return iterateOverEntitiesNoSQL(progress, type, visitor);
}
Statement statement = dbConn.createStatement();
PreparedStatement select;
int count = 0;
// stat.executeUpdate("create table tags (id "+longType+", type smallint, skeys varchar(1024), value varchar(1024))");
// stat.executeUpdate("create table ways (id "+longType+", node "+longType+", ord smallint)");
// stat.executeUpdate("create table relations (id "+longType+", member "+longType+", type smallint, role varchar(1024), ord smallint)");
computeRealCounts(statement);
statement.close();
BlockingQueue<Entity> toProcess = new ArrayBlockingQueue<Entity>(100000);
AbstractProducer entityProducer = null;
if (type == EntityType.WAY_BOUNDARY) {
if (type == EntityType.NODE) {
// filter out all nodes without tags
select = iterateNodes;
count = allNodes;
} else if (type == EntityType.WAY) {
select = iterateWays;
count = allWays;
} else if (type == EntityType.WAY_BOUNDARY) {
select = iterateWayBoundaries;
count = allBoundaries;
entityProducer = new BoundaryProducer(toProcess, select);
} else {
if (type == EntityType.NODE) {
// filter out all nodes without tags
select = iterateNodes;
count = allNodes;
} else if (type == EntityType.WAY) {
select = iterateWays;
count = allWays;
} else {
select = iterateRelations;
count = allRelations;
}
entityProducer = new EntityProducer(toProcess, type, select);
select = iterateRelations;
count = allRelations;
}
entityProducer = new EntityProducer(toProcess, type, select);
progress.startWork(count);
//produce
@ -297,168 +238,15 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
if (!realCounts) {
realCounts = true;
// filter out all nodes without tags
allNodes = statement.executeQuery("select count(distinct n.id) from node n inner join tags t on n.id = t.id and t.type = 0").getInt(1); //$NON-NLS-1$
allNodes = statement.executeQuery("select count(distinct n.id) from node n where length(n.tags) > 0").getInt(1); //$NON-NLS-1$
allWays = statement.executeQuery("select count(*) from ways w where w.ord = 0").getInt(1); //$NON-NLS-1$
allRelations = statement.executeQuery("select count(distinct r.id) from relations r inner join tags t on t.id = r.id and t.type = 2 and r.ord = 0").getInt(1); //$NON-NLS-1$
allBoundaries = statement.executeQuery("select count(distinct t.id) from tags t where t.skeys = \"" + OSMTagKey.BOUNDARY.getValue() + "\"").getInt(1); //$NON-NLS-1$
allRelations = statement.executeQuery("select count(distinct r.id) from relations r").getInt(1); //$NON-NLS-1$
allBoundaries = statement.executeQuery("select count(*) from ways w where w.ord = 0 and w.boundary > 0").getInt(1); //$NON-NLS-1$
}
}
private void loadEntityDataNoSQL(Entity e) {
Collection<EntityId> ids = e instanceof Relation ? ((Relation) e).getMemberIds() : ((Way) e).getEntityIds();
Map<EntityId, Entity> map = new LinkedHashMap<EntityId, Entity>();
for (EntityId i : ids) {
char pr = i.getType() == EntityType.NODE ? '0' : (i.getType() == EntityType.WAY ? '1' : '2');
String key = pr + "" + i.getId();
String value = accessor.get(randomAccessOptions, key);
if (value != null && value.length() > 0) {
try {
Entity es = loadEntityNoSqlFromValue(randomAccessOptions, key, value, false);
map.put(i, es);
} catch (JSONException e1) {
log.warn(key + " - " + e1.getMessage() + " " + value + "("+value.length()+"]", e1);
}
}
}
e.initializeLinks(map);
}
private void assertToken(int expected, int actual, String value){
if(expected != actual){
System.err.println("Expected token " + expected + " != " + actual +" actual for : " + value);
}
}
private Entity loadEntityNoSqlFromValue(ReadOptions opts,
String key, String value, boolean skipIfEmptyTags) throws JSONException{
if(value == null){
return null;
}
Entity e = null;
long id = Long.parseLong(key.substring(1));
ArraySerializer.EntityValueTokenizer tokenizer = new EntityValueTokenizer();
tokenizer.tokenize(value);
assertToken(ArraySerializer.START_ARRAY, tokenizer.next(), value);
int next = tokenizer.next();
if(next == ArraySerializer.ELEMENT && skipIfEmptyTags){
return null;
}
// create e
if (key.charAt(0) == '0') {
e = new Node(0, 0, id);
} else if (key.charAt(0) == '1') {
e = new Way(id);
} else if (key.charAt(0) == '2') {
e = new Relation(id);
}
// let's read tags
if(next == ArraySerializer.START_ARRAY){
int n = tokenizer.next();
while(n == ArraySerializer.ELEMENT){
String tagKey = tokenizer.value();
assertToken(ArraySerializer.ELEMENT, tokenizer.next(), value);
String tagValue = tokenizer.value();
e.putTag(tagKey, tagValue);
n = tokenizer.next();
}
}
if (key.charAt(0) == '0') {
try {
assertToken(ArraySerializer.ELEMENT, tokenizer.next(), value);
double lat = Double.parseDouble(tokenizer.value());
assertToken(ArraySerializer.ELEMENT, tokenizer.next(), value);
double lon = Double.parseDouble(tokenizer.value());
((Node)e).setLatitude(lat);
((Node)e).setLongitude(lon);
} catch (java.lang.NumberFormatException ex) {
log.warn("Cannot parse lat/log for Node with key:" + key + " value:" + value);
e = null;
}
} else if (key.charAt(0) == '1') {
assertToken(ArraySerializer.START_ARRAY, tokenizer.next(), value);
int n = tokenizer.next();
while(n == ArraySerializer.ELEMENT){
String pointId = "0"+ tokenizer.value();
String pointVal = this.accessor.get(opts, pointId);
Node node = (Node) loadEntityNoSqlFromValue(opts, pointId, pointVal, false);
if(node != null){
((Way) e).addNode(node);
}
n = tokenizer.next();
}
} else if (key.charAt(0) == '2') {
assertToken(ArraySerializer.START_ARRAY, tokenizer.next(), value);
int n = tokenizer.next();
while(n == ArraySerializer.ELEMENT){
String mkey = tokenizer.value();
EntityType t = null;
long mid = Long.parseLong(mkey.substring(1));
if(mkey.charAt(0) == '0'){
t = EntityType.NODE;
} else if(mkey.charAt(0) == '1'){
t = EntityType.WAY;
} else if(mkey.charAt(0) == '2'){
t = EntityType.RELATION;
}
assertToken(ArraySerializer.ELEMENT, tokenizer.next(), value);
String role = tokenizer.value();
((Relation) e).addMember(mid, t, role);
n = tokenizer.next();
}
}
return e;
}
private int iterateOverEntitiesNoSQL(IProgress progress, EntityType type, OsmDbVisitor visitor) throws SQLException {
ReadOptions opts = new ReadOptions();
DBIterator iterator = accessor.newIterator(opts);
String prefix = "0";
int count = 0;
if (type == EntityType.WAY) {
prefix = "1";
} else if (type == EntityType.RELATION) {
prefix = "2";
}
iterator.seek(prefix);
while(iterator.valid()){
String key = iterator.key();
if(!key.startsWith(prefix)){
break;
}
String value = iterator.value();
try {
Entity e = null;
if (type == EntityType.NODE) {
e = loadEntityNoSqlFromValue(opts, key, value, true);
} else if (type == EntityType.WAY) {
e = loadEntityNoSqlFromValue(opts, key, value, false);
} else {
e = loadEntityNoSqlFromValue(opts, key, value, false);
}
if(e != null){
count++;
if (progress != null) {
progress.progress(1);
}
visitor.iterateEntity(e, this);
}
} catch (JSONException e) {
log.warn(key + " - " + e.getMessage() + " " + value + "("+value.length()+"]", e);
}
iterator.next();
}
iterator.delete();
return count;
}
public void closeReadingConnection() throws SQLException {
if (dialect != DBDialect.NOSQL) {
if (pselectNode != null) {
@ -470,9 +258,6 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
if (pselectRelation != null) {
pselectRelation.close();
}
if (pselectTags != null) {
pselectTags.close();
}
if (iterateNodes != null) {
iterateNodes.close();
}
@ -497,67 +282,6 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
}
}
public class BoundaryProducer extends AbstractProducer {
private final BlockingQueue<Entity> toProcess;
private final PreparedStatement select;
public BoundaryProducer(BlockingQueue<Entity> toProcess, PreparedStatement selectIds) {
this.toProcess = toProcess;
this.select = selectIds;
setDaemon(true);
setName("BoundaryProducer");
}
@Override
public void run() {
ResultSet rs;
try {
select.execute();
rs = select.getResultSet();
TLongArrayList boundariesToLoad = new TLongArrayList();
while (rs.next()) {
boundariesToLoad.add(rs.getLong(1));
}
rs.close();
PreparedStatement iterateWaysByIds = null;
int idsSize = 0;
while (!boundariesToLoad.isEmpty()) {
int chunk = Math.min(100, boundariesToLoad.size());
if (chunk != idsSize) {
if (iterateWaysByIds != null) {
iterateWaysByIds.close();
}
StringBuilder b = new StringBuilder();
for (int i = 0; i <= chunk; i++) {
b.append('?').append(',');
}
b.deleteCharAt(b.length()-1);
iterateWaysByIds = dbConn.prepareStatement("select w.id, w.node, w.ord, t.skeys, t.value, n.latitude, n.longitude " + //$NON-NLS-1$
"from ways w left join tags t on w.id = t.id and t.type = 1 and w.ord = 0 inner join node n on w.node = n.id where w.id in (" + b.toString() + //$NON-NLS-1$
") order by w.id, w.ord"); //$NON-NLS-1$
idsSize = chunk;
}
TLongList subList = boundariesToLoad.subList(0, chunk);
for (int i = 0; i < chunk; i++) {
iterateWaysByIds.setLong(i+1, subList.get(i));
}
boundariesToLoad.remove(0, chunk);
//load the ways
new EntityProducer(toProcess, EntityType.WAY, iterateWaysByIds,false).run();
}
} catch (SQLException e1) {
e1.printStackTrace();
} finally {
try {
toProcess.put(getEndingEntity());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class EntityProducer extends AbstractProducer {
@ -571,12 +295,12 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
}
public EntityProducer(BlockingQueue<Entity> toProcess, EntityType type, PreparedStatement select, boolean putEndingEntity) {
this.toProcess = toProcess;
this.type = type;
this.select = select;
this.putEndingEntity = putEndingEntity;
setDaemon(true);
setName("EntityProducer");
this.toProcess = toProcess;
this.type = type;
this.select = select;
this.putEndingEntity = putEndingEntity;
setDaemon(true);
setName("EntityProducer");
}
@Override
@ -585,41 +309,34 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
try {
select.execute();
rs = select.getResultSet();
// rs.setFetchSize(1000); !! not working for SQLite would case troubles probably
// rs.setFetchSize(1000); !! not working for SQLite would case troubles probably
Entity prevEntity = null;
long prevId = Long.MIN_VALUE;
while (rs.next()) {
long curId = rs.getLong(1);
boolean newEntity = curId != prevId;
Entity e = prevEntity;
if (type == EntityType.NODE) {
if (newEntity) {
e = new Node(rs.getDouble(2), rs.getDouble(3),
curId);
}
e.putTag(rs.getString(4), rs.getString(5));
} else if (type == EntityType.WAY) {
e = new Node(rs.getDouble(2), rs.getDouble(3), curId);
readTags(e, rs.getBytes(4));
} else if (type == EntityType.WAY || type == EntityType.WAY_BOUNDARY) {
if (newEntity) {
e = new Way(curId);
}
int ord = rs.getInt(3);
if (ord == 0 && rs.getObject(4) != null) {
e.putTag(rs.getString(4), rs.getString(5));
if (ord == 0) {
readTags(e, rs.getBytes(4));
}
if (newEntity || ord > 0) {
if(rs.getObject(6) == null) {
((Way) e).addNode(rs.getLong(2));
} else {
((Way) e).addNode(new Node(rs.getDouble(6), rs
.getDouble(7), rs.getLong(2)));
}
if (rs.getObject(6) == null) {
((Way) e).addNode(rs.getLong(2));
} else {
Node n = new Node(rs.getDouble(5), rs.getDouble(6), rs.getLong(2));
readTags(n, rs.getBytes(7));
((Way) e).addNode(n);
}
} else {
if (newEntity) {
e = new Relation(curId);
}
e.putTag(rs.getString(2), rs.getString(3));
e = new Relation(curId);
readTags(e, rs.getBytes(2));
}
if (newEntity) {
if (prevEntity != null) {

View file

@ -2,6 +2,8 @@ package net.osmand.data.preparation;
import gnu.trove.list.array.TLongArrayList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@ -11,6 +13,7 @@ import java.util.Map.Entry;
import net.osmand.osm.Entity;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.osm.Relation;
import net.osmand.osm.Way;
import net.osmand.osm.Entity.EntityId;
@ -48,10 +51,8 @@ public class OsmDbCreator implements IOsmStorageFilter {
private PreparedStatement prepWays;
int allWays = 0;
int currentTagsCount = 0;
private PreparedStatement prepTags;
private Connection dbConn;
private final IndexCreator indexCreator;
protected final IndexCreator indexCreator;
private DBAccessor database;
private DBWriteBatch batch;
@ -74,23 +75,19 @@ public class OsmDbCreator implements IOsmStorageFilter {
// prepare tables
Statement stat = dbConn.createStatement();
dialect.deleteTableIfExists("node", stat);
stat.executeUpdate("create table node (id bigint primary key, latitude double, longitude double)"); //$NON-NLS-1$
stat.executeUpdate("create table node (id bigint primary key, latitude double, longitude double, tags blob)"); //$NON-NLS-1$
stat.executeUpdate("create index IdIndex ON node (id)"); //$NON-NLS-1$
dialect.deleteTableIfExists("ways", stat);
stat.executeUpdate("create table ways (id bigint, node bigint, ord smallint, primary key (id, ord))"); //$NON-NLS-1$
stat.executeUpdate("create table ways (id bigint, node bigint, ord smallint, tags blob, boundary smallint, primary key (id, ord))"); //$NON-NLS-1$
stat.executeUpdate("create index IdWIndex ON ways (id)"); //$NON-NLS-1$
dialect.deleteTableIfExists("relations", stat);
stat.executeUpdate("create table relations (id bigint, member bigint, type smallint, role varchar(1024), ord smallint, primary key (id, ord))"); //$NON-NLS-1$
stat.executeUpdate("create table relations (id bigint, member bigint, type smallint, role varchar(1024), ord smallint, tags blob, primary key (id, ord))"); //$NON-NLS-1$
stat.executeUpdate("create index IdRIndex ON relations (id)"); //$NON-NLS-1$
dialect.deleteTableIfExists("tags", stat);
stat.executeUpdate("create table tags (id bigint, type smallint, skeys varchar(1024), value varchar(1024), primary key (id, type, skeys))"); //$NON-NLS-1$
stat.executeUpdate("create index IdTIndex ON tags (id, type)"); //$NON-NLS-1$
stat.close();
prepNode = dbConn.prepareStatement("insert into node values (?, ?, ?)"); //$NON-NLS-1$
prepWays = dbConn.prepareStatement("insert into ways values (?, ?, ?)"); //$NON-NLS-1$
prepRelations = dbConn.prepareStatement("insert into relations values (?, ?, ?, ?, ?)"); //$NON-NLS-1$
prepTags = dbConn.prepareStatement("insert into tags values (?, ?, ?, ?)"); //$NON-NLS-1$
prepNode = dbConn.prepareStatement("insert into node values (?, ?, ?, ?)"); //$NON-NLS-1$
prepWays = dbConn.prepareStatement("insert into ways values (?, ?, ?, ?, ?)"); //$NON-NLS-1$
prepRelations = dbConn.prepareStatement("insert into relations values (?, ?, ?, ?, ?, ?)"); //$NON-NLS-1$
dbConn.setAutoCommit(false);
}
}
@ -109,10 +106,6 @@ public class OsmDbCreator implements IOsmStorageFilter {
prepRelations.executeBatch();
}
prepRelations.close();
if (currentTagsCount > 0) {
prepTags.executeBatch();
}
prepTags.close();
} else {
database.write(options, batch);
}
@ -193,6 +186,19 @@ public class OsmDbCreator implements IOsmStorageFilter {
}
} else {
try {
e.removeTags(tagsToIgnore);
ByteArrayOutputStream tags = new ByteArrayOutputStream();
try {
for (Entry<String, String> i : e.getTags().entrySet()) {
// UTF-8 default
tags.write(i.getKey().getBytes("UTF-8"));
tags.write(0);
tags.write(i.getValue().getBytes("UTF-8"));
tags.write(0);
}
} catch (IOException es) {
throw new RuntimeException(es);
}
if (e instanceof Node) {
currentCountNode++;
if (!e.getTags().isEmpty()) {
@ -201,6 +207,7 @@ public class OsmDbCreator implements IOsmStorageFilter {
prepNode.setLong(1, e.getId());
prepNode.setDouble(2, ((Node) e).getLatitude());
prepNode.setDouble(3, ((Node) e).getLongitude());
prepNode.setBytes(4, tags.toByteArray());
prepNode.addBatch();
if (currentCountNode >= BATCH_SIZE_OSM) {
prepNode.executeBatch();
@ -211,11 +218,16 @@ public class OsmDbCreator implements IOsmStorageFilter {
allWays++;
short ord = 0;
TLongArrayList nodeIds = ((Way) e).getNodeIds();
for (int j=0; j<nodeIds.size(); j++) {
int boundary = ((Way)e).getTag(OSMTagKey.BOUNDARY) != null ? 1 : 0;
for (int j = 0; j < nodeIds.size(); j++) {
currentWaysCount++;
if (ord == 0) {
prepWays.setBytes(4, tags.toByteArray());
}
prepWays.setLong(1, e.getId());
prepWays.setLong(2, nodeIds.get(j));
prepWays.setLong(3, ord++);
prepWays.setInt(5, boundary);
prepWays.addBatch();
}
if (currentWaysCount >= BATCH_SIZE_OSM) {
@ -228,6 +240,9 @@ public class OsmDbCreator implements IOsmStorageFilter {
short ord = 0;
for (Entry<EntityId, String> i : ((Relation) e).getMembersMap().entrySet()) {
currentRelationsCount++;
if (ord == 0) {
prepRelations.setBytes(6, tags.toByteArray());
}
prepRelations.setLong(1, e.getId());
prepRelations.setLong(2, i.getKey().getId());
prepRelations.setLong(3, i.getKey().getType().ordinal());
@ -241,20 +256,7 @@ public class OsmDbCreator implements IOsmStorageFilter {
currentRelationsCount = 0;
}
}
e.removeTags(tagsToIgnore);
for (Entry<String, String> i : e.getTags().entrySet()) {
currentTagsCount++;
prepTags.setLong(1, e.getId());
prepTags.setLong(2, EntityType.valueOf(e).ordinal());
prepTags.setString(3, i.getKey());
prepTags.setString(4, i.getValue());
prepTags.addBatch();
}
if (currentTagsCount >= BATCH_SIZE_OSM) {
prepTags.executeBatch();
dbConn.commit(); // clear memory
currentTagsCount = 0;
}
} catch (SQLException ex) {
log.error("Could not save in db", ex); //$NON-NLS-1$
}

View file

@ -1,6 +1,7 @@
package net.osmand.router;
import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import java.io.IOException;
@ -89,13 +90,31 @@ public class BinaryRoutePlanner {
public RouteSegment findRouteSegment(double lat, double lon, RoutingContext ctx) throws IOException {
int zoomAround = 15;
int coordinatesShift = (1 << (31 - zoomAround));
int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat);
List<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
RoutingTile tl = loadRoutes(ctx, px,py, dataObjects);
// put in map to avoid duplicate map loading
TIntObjectHashMap<RoutingTile> ts = new TIntObjectHashMap<RoutingContext.RoutingTile>();
// calculate box to load neighbor tiles
RoutingTile rt = ctx.getRoutingTile(px - coordinatesShift, py - coordinatesShift);
ts.put(rt.getId(), rt);
rt = ctx.getRoutingTile(px + coordinatesShift, py - coordinatesShift);
ts.put(rt.getId(), rt);
rt = ctx.getRoutingTile(px - coordinatesShift, py + coordinatesShift);
ts.put(rt.getId(), rt);
rt = ctx.getRoutingTile(px + coordinatesShift, py + coordinatesShift);
ts.put(rt.getId(), rt);
List<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
Iterator<RoutingTile> it = ts.valueCollection().iterator();
while(it.hasNext()){
loadTileData(ctx, it.next(), dataObjects);
}
RouteSegment road = null;
double sdist = 0;
int foundProjX = 0;
int foundProjY = 0;
for(RouteDataObject r : dataObjects){
if(r.getPointsLength() > 1){
@ -125,13 +144,15 @@ public class BinaryRoutePlanner {
ro.pointTypes.add(j, null);
}
sdist = currentsDist;
foundProjX = prx;
foundProjY = pry;
}
}
}
}
if(road != null) {
// re-register the best road because one more point was inserted
registerRouteDataObject(ctx, road.getRoad(), tl);
registerRouteDataObject(ctx, road.getRoad(), ctx.getRoutingTile(foundProjX, foundProjY));
}
return road;
}
@ -179,13 +200,13 @@ public class BinaryRoutePlanner {
TLongObjectHashMap<RouteSegment> visitedDirectSegments = new TLongObjectHashMap<RouteSegment>();
TLongObjectHashMap<RouteSegment> visitedOppositeSegments = new TLongObjectHashMap<RouteSegment>();
ctx.targetEndX = end.road.getPoint31XTile(end.segmentStart);
ctx.targetEndY = end.road.getPoint31YTile(end.segmentStart);
ctx.startX = start.road.getPoint31XTile(start.segmentStart);
ctx.startY = start.road.getPoint31YTile(start.segmentStart);
// for start : f(start) = g(start) + h(start) = 0 + h(start) = h(start)
ctx.estimatedDistance = (float) h(ctx, ctx.targetEndX, ctx.targetEndY, ctx.startX, ctx.startY);
end.distanceToEnd = start.distanceToEnd = ctx.estimatedDistance;
int targetEndX = end.road.getPoint31XTile(end.segmentStart);
int targetEndY = end.road.getPoint31YTile(end.segmentStart);
int startX = start.road.getPoint31XTile(start.segmentStart);
int startY = start.road.getPoint31YTile(start.segmentStart);
float estimatedDistance = (float) h(ctx, targetEndX, targetEndY, startX, startY);
end.distanceToEnd = start.distanceToEnd = estimatedDistance;
graphDirectSegments.add(start);
graphReverseSegments.add(end);
@ -210,10 +231,10 @@ public class BinaryRoutePlanner {
}
boolean routeFound = false;
if (!inverse) {
routeFound = processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, ctx.targetEndX, ctx.targetEndY,
routeFound = processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY,
segment, visitedOppositeSegments);
} else {
routeFound = processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, ctx.startX, ctx.startY, segment,
routeFound = processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment,
visitedDirectSegments);
}
if (graphReverseSegments.isEmpty() || graphDirectSegments.isEmpty() || routeFound) {
@ -239,21 +260,18 @@ public class BinaryRoutePlanner {
graphSegments = graphDirectSegments;
}
ctx.garbageCollectorIteration++;
if (ctx.garbageCollectorIteration > RoutingContext.ITERATIONS_TO_RUN_GC ||
ctx.getCurrentlyLoadedTiles() > 30) {
ctx.garbageCollectorIteration = 0;
if (ctx.isUseRelaxingStrategy()) {
relaxNotNeededSegments(ctx, graphDirectSegments, true);
relaxNotNeededSegments(ctx, graphReverseSegments, false);
}
unloadUnusedTiles(ctx, 30);
if(ctx.runTilesGC()) {
unloadUnusedTiles(ctx, ctx.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY);
}
if(ctx.runRelaxingStrategy()) {
relaxNotNeededSegments(ctx, graphDirectSegments, true);
relaxNotNeededSegments(ctx, graphReverseSegments, false);
}
}
printDebugMemoryInformation(ctx, graphDirectSegments, graphReverseSegments, visitedDirectSegments, visitedOppositeSegments);
// 4. Route is found : collect all segments and prepare result
return prepareResult(ctx);
return prepareResult(ctx, start, end);
}
@ -412,15 +430,18 @@ public class BinaryRoutePlanner {
}
public RoutingTile loadRoutes(final RoutingContext ctx, int tile31X, int tile31Y, final List<RouteDataObject> toFillIn) {
int zoomToLoad = 31 - ctx.getZoomToLoadTileWithRoads();
int tileX = tile31X >> zoomToLoad;
int tileY = tile31Y >> zoomToLoad;
public RoutingTile loadRoutes(final RoutingContext ctx, int tile31X, int tile31Y) {
final RoutingTile tile = ctx.getRoutingTile(tile31X, tile31Y);
if (tile.isLoaded() && toFillIn == null) {
if (tile.isLoaded()) {
tile.access++;
return tile;
}
loadTileData(ctx, tile, null);
return tile;
}
private void loadTileData(final RoutingContext ctx, final RoutingTile tile, final List<RouteDataObject> toFillIn) {
long now = System.nanoTime();
ResultMatcher<RouteDataObject> matcher = new ResultMatcher<RouteDataObject>() {
@Override
@ -439,6 +460,9 @@ public class BinaryRoutePlanner {
return false;
}
};
int zoomToLoad = 31 - tile.getZoom();
int tileX = tile.getTileX();
int tileY = tile.getTileY();
SearchRequest<RouteDataObject> request = BinaryMapIndexReader.buildSearchRouteRequest(tileX << zoomToLoad,
(tileX + 1) << zoomToLoad, tileY << zoomToLoad, (tileY + 1) << zoomToLoad, matcher);
for (Entry<BinaryMapIndexReader, List<RouteSubregion>> r : map.entrySet()) {
@ -449,12 +473,11 @@ public class BinaryRoutePlanner {
}
}
ctx.loadedTiles++;
if(tile.isUnloaded()) {
if (tile.isUnloaded()) {
ctx.loadedPrevUnloadedTiles++;
}
tile.setLoaded();
ctx.timeToLoad += (System.nanoTime() - now);
return tile;
}
@ -524,7 +547,7 @@ public class BinaryRoutePlanner {
// 2. calculate point and try to load neighbor ways if they are not loaded
int x = road.getPoint31XTile(segmentEnd);
int y = road.getPoint31YTile(segmentEnd);
RoutingTile tile = loadRoutes(ctx, x, y, null);
RoutingTile tile = loadRoutes(ctx, x, y);
// 2.1 calculate possible obstacle plus time
if(d > 0){
@ -732,7 +755,7 @@ public class BinaryRoutePlanner {
/**
* Helper method to prepare final result
*/
private List<RouteSegmentResult> prepareResult(RoutingContext ctx) {
private List<RouteSegmentResult> prepareResult(RoutingContext ctx, RouteSegment start, RouteSegment end) {
List<RouteSegmentResult> result = new ArrayList<RouteSegmentResult>();
RouteSegment segment = ctx.finalReverseRoute;
@ -779,12 +802,12 @@ public class BinaryRoutePlanner {
}
if (PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST) {
System.out.println("ROUTE : ");
double startLat = MapUtils.get31LatitudeY(ctx.startY);
double startLon = MapUtils.get31LongitudeX(ctx.startX);
double endLat = MapUtils.get31LatitudeY(ctx.targetEndY);
double endLon = MapUtils.get31LongitudeX(ctx.targetEndX);
System.out.println(MessageFormat.format("<test regions=\"\" description=\"\" best_percent=\"\" vehicle=\"\" \n" +
println("ROUTE : ");
double startLat = MapUtils.get31LatitudeY(start.road.getPoint31YTile(start.segmentStart));
double startLon = MapUtils.get31LongitudeX(start.road.getPoint31XTile(start.segmentStart));
double endLat = MapUtils.get31LatitudeY(end.road.getPoint31YTile(end.segmentStart));
double endLon = MapUtils.get31LongitudeX(end.road.getPoint31XTile(end.segmentStart));
println(MessageFormat.format("<test regions=\"\" description=\"\" best_percent=\"\" vehicle=\"\" \n" +
" start_lat=\"{0}\" start_lon=\"{1}\" target_lat=\"{2}\" target_lon=\"{3}\" complete_time=\"{4}\">",
startLat+"", startLon+"", endLat+"", endLon+"", completeTime+""));
for (RouteSegmentResult res : result) {
@ -793,10 +816,10 @@ public class BinaryRoutePlanner {
if(ref != null) {
name += " " + ref;
}
System.out.println(MessageFormat.format("\t<segment id=\"{0}\" start=\"{1}\" end=\"{2}\" time=\"{4}\" name=\"{3}\"/>",
println(MessageFormat.format("\t<segment id=\"{0}\" start=\"{1}\" end=\"{2}\" time=\"{4}\" name=\"{3}\"/>",
(res.getObject().getId())+"", res.getStartPointIndex()+"", res.getEndPointIndex()+"", name, res.getSegmentTime()));
}
System.out.println("</test>");
println("</test>");
}
return result;
}

View file

@ -6,7 +6,6 @@ import java.util.Iterator;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.TIntSet;
import gnu.trove.set.TLongSet;
import gnu.trove.set.hash.TIntHashSet;
import gnu.trove.set.hash.TLongHashSet;
@ -18,44 +17,52 @@ import net.osmand.router.BinaryRoutePlanner.RouteSegmentVisitor;
public class RoutingContext {
private static int DEFAULT_HEURISTIC_COEFFICIENT = 1;
private static int ZOOM_TO_LOAD_TILES = 13; // 12?, 14?
public static int ITERATIONS_TO_RUN_GC = 100;
// 1. parameters of routing and different tweaks
private double heuristicCoefficient = DEFAULT_HEURISTIC_COEFFICIENT;
private int zoomToLoadTileWithRoads = ZOOM_TO_LOAD_TILES;
// Influence on A* : f(x) + heuristicCoefficient*g(X)
private double heuristicCoefficient = 1;
// 1.1 tile load parameters (should not affect routing)
public int ZOOM_TO_LOAD_TILES = 13; //12?, 14?
public int ITERATIONS_TO_RUN_GC = 100;
public int NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 25;
private int garbageCollectorIteration = 0;
// 1.2 Dynamic road prioritizing (heuristic)
private boolean useDynamicRoadPrioritising = true;
// 1.3 Relaxing strategy
private boolean useRelaxingStrategy = true;
public int ITERATIONS_TO_RELAX_NODES = 100;
private int relaxingIteration = 0;
// 1.4 Build A* graph in backward/forward direction (can affect results)
// null - 2 ways, true - direct way, false - reverse way
private Boolean planRoadDirection = null;
// 1.5 Router specific coefficients and restrictions
private VehicleRouter router = new CarRouter();
private boolean useDynamicRoadPrioritising = true;
// not used right now
private boolean usingShortestWay = false;
// 2. Routing memory cache (big objects)
TIntObjectHashMap<RoutingTile> tiles = new TIntObjectHashMap<RoutingContext.RoutingTile>();
int garbageCollectorIteration = 0;
// 4. Warm object caches
// 3. Warm object caches
TLongSet nonRestrictedIds = new TLongHashSet();
ArrayList<RouteSegment> segmentsToVisitPrescripted = new ArrayList<BinaryRoutePlanner.RouteSegment>(5);
ArrayList<RouteSegment> segmentsToVisitNotForbidden = new ArrayList<BinaryRoutePlanner.RouteSegment>(5);
public int targetEndX;
public int targetEndY;
public int startX;
public int startY;
public float estimatedDistance;
// 4. Final results
RouteSegment finalDirectRoute = null;
int finalDirectEndSegment = 0;
RouteSegment finalReverseRoute = null;
int finalReverseEndSegment = 0;
// 3. debug information (package accessor)
// 5. debug information (package accessor)
long timeToLoad = 0;
long timeToCalculate = 0;
int loadedTiles = 0;
@ -84,6 +91,26 @@ public class RoutingContext {
return cnt;
}
public boolean runTilesGC() {
garbageCollectorIteration++;
int loadedTilesCritical = NUMBER_OF_DESIRABLE_TILES_IN_MEMORY * 3 /2;
if (garbageCollectorIteration > ITERATIONS_TO_RUN_GC ||
getCurrentlyLoadedTiles() > loadedTilesCritical) {
garbageCollectorIteration = 0;
return true;
}
return false;
}
public boolean runRelaxingStrategy(){
relaxingIteration++;
if(relaxingIteration > ITERATIONS_TO_RELAX_NODES){
relaxingIteration = 0;
return true;
}
return false;
}
public void setVisitor(RouteSegmentVisitor visitor) {
this.visitor = visitor;
@ -93,10 +120,6 @@ public class RoutingContext {
return useDynamicRoadPrioritising;
}
public int getZoomToLoadTileWithRoads() {
return zoomToLoadTileWithRoads;
}
public boolean isUseRelaxingStrategy() {
return useRelaxingStrategy;
}
@ -148,21 +171,21 @@ public class RoutingContext {
}
public RoutingTile getRoutingTile(int x31, int y31){
int xloc = x31 >> (31 - zoomToLoadTileWithRoads);
int yloc = y31 >> (31 - zoomToLoadTileWithRoads);
int l = (xloc << zoomToLoadTileWithRoads) + yloc;
int xloc = x31 >> (31 - ZOOM_TO_LOAD_TILES);
int yloc = y31 >> (31 - ZOOM_TO_LOAD_TILES);
int l = (xloc << ZOOM_TO_LOAD_TILES) + yloc;
RoutingTile tl = tiles.get(l);
if(tl == null) {
tl = new RoutingTile(xloc, yloc, zoomToLoadTileWithRoads);
tl = new RoutingTile(xloc, yloc, ZOOM_TO_LOAD_TILES);
tiles.put(l, tl);
}
return tiles.get(l);
}
public void unloadTile(RoutingTile tile, boolean createEmpty){
int l = (tile.tileX << zoomToLoadTileWithRoads) + tile.tileY;
int l = (tile.tileX << ZOOM_TO_LOAD_TILES) + tile.tileY;
RoutingTile old = tiles.remove(l);
RoutingTile n = new RoutingTile(tile.tileX, tile.tileY, zoomToLoadTileWithRoads);
RoutingTile n = new RoutingTile(tile.tileX, tile.tileY, ZOOM_TO_LOAD_TILES);
n.isLoaded = old.isLoaded;
n.setUnloaded();
tiles.put(l, n);
@ -178,12 +201,31 @@ public class RoutingContext {
// make it without get/set for fast access
public int access;
TLongObjectMap<RouteSegment> routes = new TLongObjectHashMap<RouteSegment>();
TLongObjectHashMap<RouteDataObject> idObjects = new TLongObjectHashMap<RouteDataObject>();
public RoutingTile(int tileX, int tileY, int zoom) {
this.tileX = tileX;
this.tileY = tileY;
this.zoom = zoom;
}
public int getId(){
return (tileX << zoom) + tileY;
}
public int getZoom() {
return zoom;
}
public int getTileX() {
return tileX;
}
public int getTileY() {
return tileY;
}
public boolean isLoaded() {
return isLoaded > 0;
}
@ -208,10 +250,6 @@ public class RoutingContext {
isLoaded = Math.abs(isLoaded) + 1;
}
TLongObjectMap<RouteSegment> routes = new TLongObjectHashMap<RouteSegment>();
TIntSet loadedTiles = new TIntHashSet();
// TODO delete this object ?
TLongObjectHashMap<RouteDataObject> idObjects = new TLongObjectHashMap<RouteDataObject>();
public boolean checkContains(int x31, int y31) {
return tileX == (x31 >> (31 - zoom)) && tileY == (y31 >> (31 - zoom));

View file

@ -2,7 +2,6 @@ package net.osmand.swing;
import gnu.trove.set.hash.TLongHashSet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
@ -28,8 +27,6 @@ import org.apache.commons.logging.LogFactory;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteDataObject;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;
import net.osmand.data.DataTileManager;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
@ -282,7 +279,7 @@ public class MapClusterLayer implements MapPanelLayer {
w.addNode(new Node(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x), -1), 0);
}
router.loadRoutes(ctx, x ,y , null);
router.loadRoutes(ctx, x, y);
long l = (((long) x) << 31) + (long) y;
next = ctx.getRoutingTile(x, y).getLoadedRoutes().get(l);
boolean addToQueue = true;;

View file

@ -128,6 +128,7 @@ public class OsmExtractionUI implements IMapLocationListener {
private JCheckBox buildPoiIndex;
private JCheckBox buildAddressIndex;
private JCheckBox buildMapIndex;
private JCheckBox buildRoutingIndex;
private JCheckBox buildTransportIndex;
private JCheckBox normalizingStreets;
private JCheckBox showOfflineIndex;
@ -191,6 +192,11 @@ public class OsmExtractionUI implements IMapLocationListener {
panel.add(buildMapIndex);
buildMapIndex.setSelected(true);
buildRoutingIndex = new JCheckBox();
buildRoutingIndex.setText(Messages.getString("OsmExtractionUI.BUILD_ROUTING")); //$NON-NLS-1$
panel.add(buildRoutingIndex);
buildRoutingIndex.setSelected(true);
buildPoiIndex = new JCheckBox();
buildPoiIndex.setText(Messages.getString("OsmExtractionUI.BUILD_POI")); //$NON-NLS-1$
panel.add(buildPoiIndex);
@ -203,7 +209,7 @@ public class OsmExtractionUI implements IMapLocationListener {
normalizingStreets = new JCheckBox();
normalizingStreets.setText(Messages.getString("OsmExtractionUI.NORMALIZE_STREETS")); //$NON-NLS-1$
panel.add(normalizingStreets);
// panel.add(normalizingStreets);
normalizingStreets.setSelected(true);
buildTransportIndex = new JCheckBox();
@ -483,6 +489,7 @@ public class OsmExtractionUI implements IMapLocationListener {
creator.setNormalizeStreets(normalizingStreets.isSelected());
creator.setIndexTransport(buildTransportIndex.isSelected());
creator.setIndexMap(buildMapIndex.isSelected());
creator.setIndexRouting(buildRoutingIndex.isSelected());
creator.setCityAdminLevel(DataExtractionSettings.getSettings().getCityAdminLevel());
String fn = DataExtractionSettings.getSettings().getMapRenderingTypesFile();
MapRenderingTypes types;

View file

@ -45,6 +45,7 @@ OsmExtractionPreferencesDialog.CANCEL=Cancel
OsmExtractionUI.ADDRESS=address
OsmExtractionUI.BUILD_ADDRESS=Build Address index
OsmExtractionUI.BUILD_MAP=Build map index
OsmExtractionUI.BUILD_ROUTING=Build routing index
OsmExtractionUI.BUILD_POI=Build POI index
OsmExtractionUI.BUILD_TRANSPORT=Build transport index
OsmExtractionUI.CHOOSE_OSM_FILE=Choose osm file

View file

@ -13,7 +13,7 @@
-->
<!-- zoomWaySmoothness - 1-4, typical mapZooms - 8-10;11-12;13-14;15 -->
<process directory_for_osm_files=".work/osm" directory_for_index_files="/var/lib/jenkins/indexes" directory_for_generation=".work"
skipExistingIndexesAt="/var/lib/jenkins/indexes/uploaded" indexPOI="true" indexMap="true" indexTransport="true" indexAddress="true">
skipExistingIndexesAt="/var/lib/jenkins/indexes/uploaded" indexPOI="true" indexMap="true" indexRouting="true" indexTransport="true" indexAddress="true">
<!-- Add wget="C:/Program Files/GNUWin32/bin/wget.exe" to process, to use wget for download.
On linux systems if wget is in your path it can be wget="wget" or you can make own script with wget command:
wget="/path/to/script/wget.sh"