fix indexing issues

git-svn-id: https://osmand.googlecode.com/svn/trunk@631 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-11-05 12:11:09 +00:00
parent a9475d2196
commit 880b5e5541
9 changed files with 3825 additions and 588 deletions

View file

@ -8,9 +8,8 @@ package net.osmand;
public class ToDoConstants {
// TODO max 101
// introduce bidforfix on site
// !!! Fix progress in DataExtractionOsm
// !!! Fix files in IndexCreator (create one file!)
// Outside base 0.4 release
// 69. Add phone and site information to POI (enable call to POI and open site)

View file

@ -5,20 +5,26 @@ import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import net.osmand.Algoritms;
import net.osmand.binary.OsmandOdb.CityIndex;
import net.osmand.binary.OsmandOdb.InteresectedStreets;
import net.osmand.binary.OsmandOdb.OsmAndTransportIndex;
import net.osmand.binary.OsmandOdb.PostcodeIndex;
import net.osmand.binary.OsmandOdb.StreetIndex;
import net.osmand.binary.OsmandOdb.StreetIntersection;
import net.osmand.binary.OsmandOdb.TransportRoute;
import net.osmand.binary.OsmandOdb.TransportRouteStop;
import net.osmand.data.Building;
import net.osmand.data.City;
import net.osmand.data.MapObject;
import net.osmand.data.Street;
import net.osmand.data.TransportStop;
import net.osmand.data.index.IndexConstants;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
@ -68,6 +74,9 @@ public class BinaryMapIndexWriter {
private final static int CITY_INDEX_INIT = 6;
private final static int POSTCODES_INDEX_INIT = 7;
private final static int VILLAGES_INDEX_INIT = 8;
private final static int TRANSPORT_INDEX_INIT = 9;
private final static int TRANSPORT_STOPS_TREE = 10;
public BinaryMapIndexWriter(final RandomAccessFile raf) throws IOException{
this.raf = raf;
@ -386,24 +395,26 @@ public class BinaryMapIndexWriter {
if(wayNodes != null){
InteresectedStreets.Builder sbuilders = OsmandOdb.InteresectedStreets.newBuilder();
Map<Long, Set<Integer>> reverseMap = new LinkedHashMap<Long, Set<Integer>>();
for (int i = 0; i < streets.size(); i++) {
for (int j = i + 1; j < streets.size(); j++) {
Node intersection = null;
List<Node> l1 = wayNodes.get(streets.get(i));
List<Node> l2 = wayNodes.get(streets.get(j));
if (l1 != null && l2 != null) {
loop: for (Node n : l1) {
for (Node n2 : l2) {
if (n.getId() == n2.getId()) {
intersection = n;
break loop;
}
}
}
streets.get(i).setIndexInCity(i);
for (Node n : wayNodes.get(streets.get(i))) {
if(!reverseMap.containsKey(n.getId())){
reverseMap.put(n.getId(), new LinkedHashSet<Integer>(3));
}
if(intersection != null){
reverseMap.get(n.getId()).add(i);
}
}
Set<Integer> checkedStreets = new LinkedHashSet<Integer>();
for (int i = 0; i < streets.size(); i++) {
Street s1 = streets.get(i);
checkedStreets.clear();
for(Node intersection : wayNodes.get(s1)){
for(Integer j : reverseMap.get(intersection.getId())){
if(i >= j || checkedStreets.contains(j)){
continue;
}
checkedStreets.add(j);
StreetIntersection.Builder builder = OsmandOdb.StreetIntersection.newBuilder();
builder.setIntersectedStreet1(i);
builder.setIntersectedStreet2(j);
@ -515,6 +526,120 @@ public class BinaryMapIndexWriter {
return streetBuilder.build();
}
public void startWriteTransportIndex() throws IOException {
pushState(TRANSPORT_INDEX_INIT, OSMAND_STRUCTURE_INIT);
codedOutStream.writeTag(OsmandOdb.OsmAndStructure.TRANSPORTINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
stackBounds.push(new Bounds(0, 0, 0, 0)); // for transport stops tree
preserveInt32Size();
}
public void endWriteTransportIndex() throws IOException {
popState(TRANSPORT_INDEX_INIT);
int len = writeInt32Size();
stackBounds.pop();
System.out.println("TRANSPORT INDEX SIZE : " + len);
}
private int registerString(Map<String, Integer> stringTable, String s) {
if (stringTable.containsKey(s)) {
return stringTable.get(s);
}
int size = stringTable.size();
stringTable.put(s, size);
return size;
}
public void writeTransportRoute(long idRoute, String routeName, String routeEnName, String ref, String operator, String type,
int dist, List<TransportStop> directStops, List<TransportStop> reverseStops, Map<String, Integer> stringTable) throws IOException {
checkPeekState(TRANSPORT_INDEX_INIT);
TransportRoute.Builder tRoute = OsmandOdb.TransportRoute.newBuilder();
tRoute.setRef(ref);
tRoute.setOperator(registerString(stringTable, operator));
tRoute.setType(registerString(stringTable, type));
tRoute.setId(idRoute);
tRoute.setName(registerString(stringTable, routeName));
tRoute.setDistance(dist);
if(routeEnName != null){
tRoute.setNameEn(registerString(stringTable, routeEnName));
}
for (int i = 0; i < 2; i++) {
List<TransportStop> stops = i == 0 ? directStops : reverseStops;
long id = 0;
int x24 = 0;
int y24 = 0;
for (TransportStop st : stops) {
TransportRouteStop.Builder tStop = OsmandOdb.TransportRouteStop.newBuilder();
tStop.setId(st.getId() - id);
id = st.getId();
int x = (int) MapUtils.getTileNumberX(24, st.getLocation().getLongitude());
int y = (int) MapUtils.getTileNumberY(24, st.getLocation().getLatitude());
tStop.setDx(x - x24);
tStop.setDy(y - y24);
x24 = x;
y24 = y;
tStop.setName(registerString(stringTable, st.getName()));
if (st.getEnName() != null) {
tStop.setNameEn(registerString(stringTable, st.getEnName()));
}
if (i == 0) {
tRoute.addDirectStops(tStop.build());
} else {
tRoute.addReverseStops(tStop.build());
}
}
}
codedOutStream.writeMessage(OsmandOdb.OsmAndTransportIndex.ROUTES_FIELD_NUMBER, tRoute.build());
}
public void startTransportTreeElement(int leftX, int rightX, int topY, int bottomY) throws IOException {
checkPeekState(TRANSPORT_STOPS_TREE, TRANSPORT_INDEX_INIT);
if(state.peek() == TRANSPORT_STOPS_TREE){
codedOutStream.writeTag(OsmandOdb.TransportStopsTree.SUBTREES_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
} else {
codedOutStream.writeTag(OsmandOdb.OsmAndTransportIndex.STOPS_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED);
}
state.push(TRANSPORT_STOPS_TREE);
preserveInt32Size();
Bounds bounds = stackBounds.peek();
codedOutStream.writeSInt32(OsmandOdb.TransportStopsTree.LEFT_FIELD_NUMBER, leftX - bounds.leftX);
codedOutStream.writeSInt32(OsmandOdb.TransportStopsTree.RIGHT_FIELD_NUMBER, rightX - bounds.rightX);
codedOutStream.writeSInt32(OsmandOdb.TransportStopsTree.TOP_FIELD_NUMBER, topY - bounds.topY);
codedOutStream.writeSInt32(OsmandOdb.TransportStopsTree.BOTTOM_FIELD_NUMBER, bottomY - bounds.bottomY);
stackBounds.push(new Bounds(leftX, rightX, topY, bottomY));
stackBaseIds.push(-1L);
}
public void endWriteTransportTreeElement() throws IOException {
Long baseId = stackBaseIds.pop();
if(baseId >= 0){
codedOutStream.writeUInt64(OsmandOdb.TransportStopsTree.BASEID_FIELD_NUMBER, baseId);
}
popState(TRANSPORT_STOPS_TREE);
stackBounds.pop();
writeInt32Size();
}
public void writeTransportStringTable(Map<String, Integer> stringTable) throws IOException {
checkPeekState(TRANSPORT_INDEX_INIT);
// expect linked hash map
int i = 0;
OsmandOdb.StringTable.Builder st = OsmandOdb.StringTable.newBuilder();
for(String s : stringTable.keySet()){
if(stringTable.get(s) != i++){
throw new IllegalStateException();
}
st.addS(s);
}
codedOutStream.writeMessage(OsmAndTransportIndex.STRINGTABLE_FIELD_NUMBER, st.build());
}
private void pushState(int push, int peek){
if(state.peek() != peek){
@ -544,4 +669,6 @@ public class BinaryMapIndexWriter {
codedOutStream.writeInt32(OsmandOdb.OsmAndStructure.VERSIONCONFIRM_FIELD_NUMBER, IndexConstants.BINARY_MAP_VERSION);
codedOutStream.flush();
}
}

File diff suppressed because it is too large Load diff

View file

@ -134,7 +134,7 @@ public class DataIndexWriter {
}
private static void writeRouteStops(PreparedStatement prepRouteStops, PreparedStatement prepStops, Map<PreparedStatement, Integer> count,
private static void writeRouteStops(RTree transportStopsTree, PreparedStatement prepRouteStops, PreparedStatement prepStops, Map<PreparedStatement, Integer> count,
Set<Long> writtenStops, TransportRoute r, List<TransportStop> stops, boolean direction) throws SQLException {
int i = 0;
for(TransportStop s : stops){
@ -145,7 +145,16 @@ public class DataIndexWriter {
prepStops.setDouble(IndexTransportStop.LONGITUDE.ordinal() + 1, s.getLocation().getLongitude());
prepStops.setString(IndexTransportStop.NAME.ordinal() + 1, s.getName());
prepStops.setString(IndexTransportStop.NAME_EN.ordinal() + 1, s.getEnName());
int x = (int) MapUtils.getTileNumberX(24, s.getLocation().getLongitude());
int y = (int) MapUtils.getTileNumberX(24, s.getLocation().getLatitude());
addBatch(count, prepStops);
try {
transportStopsTree.insert(new LeafElement(new Rect(x, y, x, y), s.getId()));
} catch (RTreeInsertException e) {
throw new IllegalArgumentException(e);
} catch (IllegalValueException e) {
throw new IllegalArgumentException(e);
}
writtenStops.add(s.getId());
}
assert IndexTransportRouteStop.values().length == 4;
@ -159,7 +168,8 @@ public class DataIndexWriter {
public static void insertTransportIntoIndex(PreparedStatement prepRoute, PreparedStatement prepRouteStops,
PreparedStatement prepStops, Set<Long> writtenStops, TransportRoute route, Map<PreparedStatement, Integer> statements,
PreparedStatement prepStops, RTree transportStopsTree,
Set<Long> writtenStops, TransportRoute route, Map<PreparedStatement, Integer> statements,
int batchSize) throws SQLException {
assert IndexTransportRoute.values().length == 7;
prepRoute.setLong(IndexTransportRoute.ID.ordinal() + 1, route.getId());
@ -171,8 +181,8 @@ public class DataIndexWriter {
prepRoute.setInt(IndexTransportRoute.DIST.ordinal() + 1, route.getAvgBothDistance());
addBatch(statements, prepRoute);
writeRouteStops(prepRouteStops, prepStops, statements, writtenStops, route, route.getForwardStops(), true);
writeRouteStops(prepRouteStops, prepStops, statements, writtenStops, route, route.getBackwardStops(), false);
writeRouteStops(transportStopsTree, prepRouteStops, prepStops, statements, writtenStops, route, route.getForwardStops(), true);
writeRouteStops(transportStopsTree, prepRouteStops, prepStops, statements, writtenStops, route, route.getBackwardStops(), false);
}
@ -268,8 +278,6 @@ public class DataIndexWriter {
mapBinaryStat.setInt(IndexBinaryMapRenderObject.HIGHWAY.ordinal() + 1, highwayAttributes);
mapBinaryStat.setString(IndexBinaryMapRenderObject.NAME.ordinal() + 1, name);
addBatch(statements, mapBinaryStat);
try {
mapTree.insert(new LeafElement(new Rect(minX, minY, maxX, maxY), id));
} catch (RTreeInsertException e1) {

View file

@ -282,8 +282,6 @@ public class IndexBatchCreator {
indexCreator.setNormalizeStreets(true);
indexCreator.setSaveAddressWays(writeWayNodes);
String transportFileName = regionName + "_" + IndexConstants.TRANSPORT_TABLE_VERSION + IndexConstants.TRANSPORT_INDEX_EXT;
indexCreator.setTransportFileName(transportFileName);
String poiFileName = regionName + "_" + IndexConstants.POI_TABLE_VERSION + IndexConstants.POI_INDEX_EXT;
indexCreator.setPoiFileName(poiFileName);
String mapFileName = regionName + "_" + IndexConstants.BINARY_MAP_VERSION + IndexConstants.BINARY_MAP_INDEX_EXT;
@ -294,10 +292,7 @@ public class IndexBatchCreator {
if (indexPOI) {
uploadIndex(new File(indexDirFiles, poiFileName), alreadyUploadedFiles);
}
if (indexTransport) {
uploadIndex(new File(indexDirFiles, transportFileName), alreadyUploadedFiles);
}
if (indexMap || indexAddress) {
if (indexMap || indexAddress || indexTransport) {
uploadIndex(new File(indexDirFiles, mapFileName), alreadyUploadedFiles);
}
} catch (Exception e) {
@ -355,10 +350,21 @@ public class IndexBatchCreator {
summary = "Transport index for ";
} else if(f.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT) || f.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP)){
regionName = f.getName().substring(0, f.getName().length() - IndexConstants.BINARY_MAP_INDEX_EXT.length() - 2);
summary = "Map index for ";
if(indexAddress){
summary = "Address, " + summary;
summary = " index for ";
boolean fir = true;
if (indexAddress) {
summary = "Address" + (fir ? "" : ", ") + summary;
fir = false;
}
if (indexTransport) {
summary = "Transport" + (fir ? "" : ", ") + summary;
fir = false;
}
if (indexMap) {
summary = "Map" + (fir ? "" : ", ") + summary;
fir = false;
}
} else {
return;
}

View file

@ -411,46 +411,6 @@ public class IndexConstants {
}
public static String indexMapLocationsTable = "map_locations"; //$NON-NLS-1$
public static String indexMapLocationsTable2 = "map_locations_2"; //$NON-NLS-1$
public static String indexMapLocationsTable3 = "map_locations_3"; //$NON-NLS-1$
public enum IndexMapRenderObject implements IndexColumn {
ID("long", true), TYPE("integer"), NAME, NODES("BLOB"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
boolean index = false;
String type = null;
private IndexMapRenderObject() {
}
private IndexMapRenderObject(String type) {
this.type = type;
}
private IndexMapRenderObject(String type, boolean index) {
this(type);
this.index = index;
}
public static String getTable() {
return "map_objects"; //$NON-NLS-1$
}
public String getTableName() {
return getTable();
}
@Override
public String getType() {
return type;
}
@Override
public boolean isIndex() {
return index;
}
}
public enum IndexBinaryMapRenderObject implements IndexColumn {
ID("long", true), NAME, TYPES("BLOB"), RESTRICTIONS("BLOB"), NODES("BLOB"), HIGHWAY("INT"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
boolean index = false;

View file

@ -112,10 +112,9 @@ public class IndexCreator {
private boolean normalizeStreets = true; // true by default
private boolean saveAddressWays = true; // true by default
private boolean recreateOnlyBinaryFile = false; //false;
private String regionName;
private String transportFileName = null;
private String poiFileName = null;
private String mapFileName = null;
private Long lastModifiedDate = null;
@ -136,23 +135,23 @@ public class IndexCreator {
private PreparedStatement poiPreparedStatement;
Set<Long> visitedStops = new HashSet<Long>();
private File transportIndexFile;
private Connection transportConnection;
private PreparedStatement transRouteStat;
private PreparedStatement transRouteStopsStat;
private PreparedStatement transStopsStat;
private File mapFile;
private RandomAccessFile mapRAFile;
private Connection mapConnection;
private PreparedStatement mapBinaryStat;
private PreparedStatement addressCityStat;
private PreparedStatement addressStreetStat;
private PreparedStatement addressBuildingStat;
private PreparedStatement addressStreetNodeStat;
private PreparedStatement mapBinaryStat;
private Set<Long> visitedStops = new HashSet<Long>();
private PreparedStatement transRouteStat;
private PreparedStatement transRouteStopsStat;
private PreparedStatement transStopsStat;
private RTree transportStopsTree;
private RTree[] mapTree = null;
@ -473,10 +472,6 @@ public class IndexCreator {
this.poiFileName = poiFileName;
}
public void setTransportFileName(String transportFileName) {
this.transportFileName = transportFileName;
}
public void setNodesDBFile(File file){
dbFile = file;
}
@ -495,13 +490,6 @@ public class IndexCreator {
return getMapFileName() + ".tmp";
}
public String getTransportFileName() {
if(transportFileName == null){
return IndexConstants.TRANSPORT_INDEX_DIR + getRegionName() + IndexConstants.TRANSPORT_INDEX_EXT;
}
return transportFileName;
}
public Long getLastModifiedDate() {
return lastModifiedDate;
}
@ -967,7 +955,7 @@ public class IndexCreator {
loadEntityData(e, true);
TransportRoute route = indexTransportRoute((Relation) e);
if (route != null) {
DataIndexWriter.insertTransportIntoIndex(transRouteStat, transRouteStopsStat, transStopsStat, visitedStops, route,
DataIndexWriter.insertTransportIntoIndex(transStopsStat, transRouteStat, transRouteStopsStat, transportStopsTree, visitedStops, route,
pStatements, BATCH_SIZE);
}
}
@ -1493,7 +1481,7 @@ public class IndexCreator {
waynodesStat = reader.getStreetsWayNodesPreparedStatement(mapConnection);
}
int j=0;
int j = 0;
for (; j < cities.size(); j++) {
City c = cities.get(j);
if (c.getType() != CityType.CITY && c.getType() != CityType.TOWN) {
@ -1621,6 +1609,141 @@ public class IndexCreator {
}
}
private int registerString(Map<String, Integer> stringTable, String s) {
if (stringTable.containsKey(s)) {
return stringTable.get(s);
}
int size = stringTable.size();
stringTable.put(s, size);
return size;
}
private Map<String, Integer> createStringTableForTransport(){
Map<String, Integer> stringTable = new LinkedHashMap<String, Integer>();
registerString(stringTable, "bus");
registerString(stringTable, "trolleybus");
registerString(stringTable, "subway");
registerString(stringTable, "tram");
registerString(stringTable, "share_taxi");
registerString(stringTable, "taxi");
registerString(stringTable, "train");
registerString(stringTable, "ferry");
return stringTable;
}
public void writeBinaryTransportIndex(BinaryMapIndexWriter writer) throws IOException, SQLException {
try {
visitedStops = null; // allow gc to collect it
PreparedStatement selectTransportRouteData = mapConnection.prepareStatement("SELECT * FROM " + IndexTransportRoute.getTable());
PreparedStatement selectTransportData = mapConnection.prepareStatement("SELECT S.stop, S.direction," +
" A.latitude, A.longitude, A.name, A.name_en " +
"FROM transport_route_stop S INNER JOIN transport_stop A ON A.id = S.stop ORDER BY S.ord ASC WHERE S.route = ?");
writer.startWriteTransportIndex();
// expect that memory would be enough
Map<String, Integer> stringTable = createStringTableForTransport();
ResultSet rs = selectTransportRouteData.executeQuery();
List<TransportStop> directStops = new ArrayList<TransportStop>();
List<TransportStop> reverseStops = new ArrayList<TransportStop>();
while(rs.next()){
long idRoute = rs.getLong(IndexTransportRoute.ID.ordinal() + 1);
int dist = rs.getInt(IndexTransportRoute.DIST.ordinal() + 1);
String routeName = rs.getString(IndexTransportRoute.NAME.ordinal() + 1);
String routeEnName = rs.getString(IndexTransportRoute.NAME_EN.ordinal() + 1);
if(routeEnName != null && routeEnName.equals(Junidecode.unidecode(routeName))){
routeEnName = null;
}
String ref = rs.getString(IndexTransportRoute.REF.ordinal() + 1);
String operator = rs.getString(IndexTransportRoute.OPERATOR.ordinal() + 1);
String type = rs.getString(IndexTransportRoute.TYPE.ordinal() + 1);
selectTransportData.setLong(1, idRoute);
ResultSet rset = selectTransportData.executeQuery();
while (rset.next()) {
boolean dir = rset.getInt(2) != 0;
long idStop = rset.getInt(1);
String stopName = rset.getString(5);
String stopEnName = rset.getString(6);
if (stopEnName != null && stopEnName.equals(Junidecode.unidecode(stopName))) {
stopEnName = null;
}
TransportStop st = new TransportStop();
st.setId(idStop);
st.setName(stopName);
st.setLocation(rset.getDouble(3), rset.getDouble(4));
if (stopEnName != null) {
st.setEnName(stopEnName);
}
if(dir){
directStops.add(st);
} else {
reverseStops.add(st);
}
}
writer.writeTransportRoute(idRoute, routeName, routeEnName, ref, operator, type, dist, directStops, reverseStops, stringTable);
}
rs.close();
selectTransportRouteData.close();
// TODO prepare transportStopsTree!!!
PreparedStatement selectTransportStop = mapConnection.prepareStatement(
"SELECT A.id, A.latitude, A.longitude, A.name, A.name_en FROM transport_stop A where A.id = ?");
PreparedStatement selectTransportRouteStop = mapConnection.prepareStatement(
"SELECT S.route FROM transport_route_stop S WHERE S.stop = ? ");
long rootIndex = transportStopsTree.getFileHdr().getRootIndex();
rtree.Node root = transportStopsTree.getReadNode(rootIndex);
Rect rootBounds = calcBounds(root);
if (rootBounds != null) {
writer.startTransportTreeElement(rootBounds.getMinX(), rootBounds.getMaxX(), rootBounds.getMinY(), rootBounds.getMaxY());
writeBinaryTransportTree(root, transportStopsTree, writer, selectTransportStop, selectTransportRouteStop);
writer.endWriteTransportTreeElement();
}
writer.writeTransportStringTable(stringTable);
writer.endWriteTransportIndex();
} catch (RTreeException e) {
throw new IllegalStateException(e);
}
}
public void writeBinaryTransportTree(rtree.Node parent, RTree r, BinaryMapIndexWriter writer,
PreparedStatement selectTransportStop, PreparedStatement selectTransportRouteStop) throws IOException, RTreeException, SQLException {
Element[] e = parent.getAllElements();
for (int i = 0; i < parent.getTotalElements(); i++) {
Rect re = e[i].getRect();
if (e[i].getElementType() == rtree.Node.LEAF_NODE) {
long id = ((LeafElement) e[i]).getPtr();
selectTransportStop.setLong(1, id);
selectTransportRouteStop.setLong(1, id);
ResultSet rs = selectTransportStop.executeQuery();
if (rs.next()) {
ResultSet rset = selectTransportRouteStop.executeQuery();
while(rset.next()){
}
rset.close();
} else {
log.error("Something goes wrong with id = " + id);
}
} else {
long ptr = ((NonLeafElement) e[i]).getPtr();
rtree.Node ns = r.getReadNode(ptr);
writer.startTransportTreeElement(re.getMinX(), re.getMaxX(), re.getMinY(), re.getMaxY());
writeBinaryTransportTree(ns, r, writer, selectTransportStop, selectTransportRouteStop);
writer.endWriteTransportTreeElement();
}
}
}
public Rect calcBounds(rtree.Node n) {
Rect r = null;
@ -1651,6 +1774,9 @@ public class IndexCreator {
public String getRTreeMapIndexNonPackFileName(){
return mapFile.getAbsolutePath()+".rtree";
}
public String getRTreeTransportStopsFileName(){
return mapFile.getAbsolutePath()+".trans";
}
public String getRTreeMapIndexPackFileName(){
return mapFile.getAbsolutePath()+".prtree";
@ -1683,6 +1809,7 @@ public class IndexCreator {
normalizeSuffixes = DataExtractionSettings.getSettings().getSuffixesToNormalizeStreets();
}
boolean success = false;
// Main generation method
try {
//////////////////////////////////////////////////////////////////////////
@ -1716,84 +1843,102 @@ public class IndexCreator {
pselectRelation = dbConn.prepareStatement("select * from relations where id = ? order by ord");
pselectTags = dbConn.prepareStatement("select key, value from tags where id = ? and type = ?");
// 2. Create index connections and index structure
createDatabaseIndexesStructure();
// 3. Processing all entries
// 3.1 write all cities
if (indexAddress) {
progress.setGeneralProgress("[40 of 100]");
progress.startTask("Indexing cities...", allNodes);
if (!loadFromPath) {
allNodes = iterateOverEntities(progress, EntityType.NODE, allNodes, STEP_CITY_NODES);
// do not create temp map file and rtree files
if (recreateOnlyBinaryFile) {
mapFile = new File(workingDir, getMapFileName());
File tempDBMapFile = new File(workingDir, getTempMapDBFileName());
mapConnection = DriverManager.getConnection("jdbc:sqlite:" + tempDBMapFile.getAbsolutePath());
mapConnection.setAutoCommit(false);
mapTree = new RTree[MAP_ZOOMS.length - 1];
try {
for (int i = 0; i < MAP_ZOOMS.length - 1; i++) {
mapTree[i] = new RTree(getRTreeMapIndexPackFileName() + i);
}
} catch (RTreeException e) {
log.error("Error flushing", e);
throw new IOException(e);
}
} else {
for (City c : cities.values()) {
DataIndexWriter.writeCity(addressCityStat, pStatements, c, BATCH_SIZE);
}
// commit to put all cities
if (pStatements.get(addressCityStat) > 0) {
addressCityStat.executeBatch();
pStatements.put(addressCityStat, 0);
mapConnection.commit();
}
// 2. Create index connections and index structure
createDatabaseIndexesStructure();
}
// 3. Processing all entries
// 3.1 write all cities
// 3.2 index address relations
if (indexAddress || indexMap) {
progress.setGeneralProgress("[40 of 100]");
progress.startTask("Preindexing address and map ways...", allRelations);
allRelations = iterateOverEntities(progress, EntityType.RELATION, allRelations, STEP_ADDRESS_RELATIONS_AND_MULTYPOLYGONS);
// commit to put all cities
if (indexAddress) {
progress.setGeneralProgress("[40 of 100]");
progress.startTask("Indexing cities...", allNodes);
if (!loadFromPath) {
allNodes = iterateOverEntities(progress, EntityType.NODE, allNodes, STEP_CITY_NODES);
}
for (City c : cities.values()) {
DataIndexWriter.writeCity(addressCityStat, pStatements, c, BATCH_SIZE);
}
// commit to put all cities
if (pStatements.get(addressCityStat) > 0) {
addressCityStat.executeBatch();
pStatements.put(addressCityStat, 0);
mapConnection.commit();
}
}
// 3.2 index address relations
if (indexAddress || indexMap) {
progress.setGeneralProgress("[40 of 100]");
progress.startTask("Preindexing address and map ways...", allRelations);
allRelations = iterateOverEntities(progress, EntityType.RELATION, allRelations,
STEP_ADDRESS_RELATIONS_AND_MULTYPOLYGONS);
// commit to put all cities
if (indexAddress) {
if (pStatements.get(addressBuildingStat) > 0) {
addressBuildingStat.executeBatch();
pStatements.put(addressBuildingStat, 0);
}
if (pStatements.get(addressStreetNodeStat) > 0) {
addressStreetNodeStat.executeBatch();
pStatements.put(addressStreetNodeStat, 0);
}
mapConnection.commit();
}
}
// 3.3 MAIN iterate over all entities
progress.setGeneralProgress("[50 of 100]");
progress.startTask("Processing osm nodes...", allNodes);
iterateOverEntities(progress, EntityType.NODE, allNodes, STEP_MAIN);
progress.setGeneralProgress("[70 of 100]");
progress.startTask("Processing osm ways...", allWays);
iterateOverEntities(progress, EntityType.WAY, allWays, STEP_MAIN);
progress.setGeneralProgress("[85 of 100]");
progress.startTask("Processing osm relations...", allRelations);
iterateOverEntities(progress, EntityType.RELATION, allRelations, STEP_MAIN);
// 3.4 update all postal codes from relations
if (indexAddress && !postalCodeRelations.isEmpty()) {
progress.setGeneralProgress("[90 of 100]");
progress.startTask("Registering postcodes...", -1);
if (pStatements.get(addressBuildingStat) > 0) {
addressBuildingStat.executeBatch();
pStatements.put(addressBuildingStat, 0);
mapConnection.commit();
}
if (pStatements.get(addressStreetNodeStat) > 0) {
addressStreetNodeStat.executeBatch();
pStatements.put(addressStreetNodeStat, 0);
}
mapConnection.commit();
processingPostcodes();
}
}
// 3.3 MAIN iterate over all entities
progress.setGeneralProgress("[50 of 100]");
progress.startTask("Processing osm nodes...", allNodes);
iterateOverEntities(progress, EntityType.NODE, allNodes, STEP_MAIN);
progress.setGeneralProgress("[70 of 100]");
progress.startTask("Processing osm nodes...", allWays);
iterateOverEntities(progress, EntityType.WAY, allWays, STEP_MAIN);
progress.setGeneralProgress("[85 of 100]");
progress.startTask("Processing osm nodes...", allRelations);
iterateOverEntities(progress, EntityType.RELATION, allRelations, STEP_MAIN);
// 3.4 update all postal codes from relations
if (indexAddress && !postalCodeRelations.isEmpty()) {
progress.setGeneralProgress("[90 of 100]");
progress.startTask("Registering postcodes...", -1);
if (pStatements.get(addressBuildingStat) > 0) {
addressBuildingStat.executeBatch();
pStatements.put(addressBuildingStat, 0);
mapConnection.commit();
// 4. packing map rtree indexes
if (indexMap) {
progress.setGeneralProgress("[90 of 100]");
progress.startTask("Serializing map data...", -1);
packingRtreeMapIndexes();
log.info("Finish packing RTree files");
}
processingPostcodes();
}
// 4. packing map rtree indexes
if (indexMap) {
progress.setGeneralProgress("[90 of 100]");
progress.startTask("Serializing map data...", -1);
packingRtreeMapIndexes();
log.info("Finish packing RTree files");
}
// 5. Writing binary file
if(indexMap || indexAddress){
if(indexMap || indexAddress || indexTransport){
if(mapFile.exists()){
mapFile.delete();
}
@ -1814,10 +1959,17 @@ public class IndexCreator {
mapConnection.commit();
writeBinaryAddressIndex(writer, progress);
}
if(indexTransport){
progress.setGeneralProgress("[95 of 100]");
progress.startTask("Writing transport index to binary file...", -1);
closePreparedStatements(transRouteStat, transRouteStopsStat, transStopsStat);
mapConnection.commit();
}
progress.finishTask();
writer.close();
log.info("Finish writing binary file");
}
success = true;
} finally {
try {
if (pselectNode != null) {
@ -1847,21 +1999,6 @@ public class IndexCreator {
poiIndexFile.setLastModified(lastModifiedDate);
}
}
if (transportConnection != null) {
transportConnection.commit();
transportConnection.close();
transportConnection = null;
if (lastModifiedDate != null) {
transportIndexFile.setLastModified(lastModifiedDate);
}
}
if (mapRAFile != null) {
mapRAFile.close();
if (lastModifiedDate != null && mapFile.exists()) {
mapFile.setLastModified(lastModifiedDate);
}
}
if (mapConnection != null) {
mapConnection.commit();
mapConnection.close();
@ -1882,12 +2019,12 @@ public class IndexCreator {
}
for (int i = 0; i < mapTree.length; i++) {
File f = new File(getRTreeMapIndexNonPackFileName() + i);
if (f.exists()) {
f.delete();
if (f.exists() && success) {
// f.delete();
}
f = new File(getRTreeMapIndexPackFileName() + i);
if (f.exists()) {
f.delete();
if (f.exists() && success) {
// f.delete();
}
}
@ -1997,7 +2134,7 @@ public class IndexCreator {
private void createDatabaseIndexesStructure() throws SQLException, IOException {
// 2.1 create temporary sqlite database to put temporary results to it
if (indexMap || indexTransport) {
if (indexMap || indexAddress || indexTransport) {
mapFile = new File(workingDir, getMapFileName());
// to save space
mapFile.getParentFile().mkdirs();
@ -2075,35 +2212,37 @@ public class IndexCreator {
}
if (indexTransport) {
transportIndexFile = new File(workingDir, getTransportFileName());
// to save space
if (transportIndexFile.exists()) {
transportIndexFile.delete();
DataIndexWriter.createTransportIndexStructure(mapConnection);
try {
File file = new File(getRTreeTransportStopsFileName());
if (file.exists()) {
file.delete();
}
transportStopsTree = new RTree(file.getAbsolutePath());
} catch (RTreeException e) {
throw new IOException(e);
}
transportIndexFile.getParentFile().mkdirs();
// creating nodes db to fast access for all nodes
transportConnection = DriverManager.getConnection("jdbc:sqlite:" + transportIndexFile.getAbsolutePath());
DataIndexWriter.createTransportIndexStructure(transportConnection);
transRouteStat = transportConnection.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexTransportRoute
transRouteStat = mapConnection.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexTransportRoute
.getTable(), IndexTransportRoute.values().length));
transRouteStopsStat = transportConnection.prepareStatement(IndexConstants.generatePrepareStatementToInsert(
transRouteStopsStat = mapConnection.prepareStatement(IndexConstants.generatePrepareStatementToInsert(
IndexTransportRouteStop.getTable(), IndexTransportRouteStop.values().length));
transStopsStat = transportConnection.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexTransportStop
transStopsStat = mapConnection.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexTransportStop
.getTable(), IndexTransportStop.values().length));
pStatements.put(transRouteStat, 0);
pStatements.put(transRouteStopsStat, 0);
pStatements.put(transStopsStat, 0);
transportConnection.setAutoCommit(false);
mapConnection.setAutoCommit(false);
}
}
protected void closePreparedStatements(PreparedStatement... preparedStatements) throws SQLException{
for(PreparedStatement p : preparedStatements){
p.executeBatch();
p.close();
pStatements.remove(p);
if (p != null) {
p.executeBatch();
p.close();
pStatements.remove(p);
}
}
}
@ -2127,7 +2266,7 @@ public class IndexCreator {
IndexCreator creator = new IndexCreator(new File("e:/Information/OSM maps/osmand/"));
creator.setIndexMap(true);
creator.setIndexAddress(true);
creator.setSaveAddressWays(true);
creator.setSaveAddressWays(false);
creator.setNormalizeStreets(true);
// creator.setIndexPOI(true);
// creator.setIndexTransport(true);

View file

@ -14,9 +14,18 @@ message OsmAndStructure {
repeated OsmAndMapIndex mapIndex = 2;
// encoded as fixed32 length delimited
repeated OsmAndAddressIndex addressIndex = 3;
// encoded as fixed32 length delimited
repeated OsmAndTransportIndex transportIndex = 4;
// last field should version again (to check consistency)
required uint32 versionConfirm = 32;
}
/**
String table, contains the common strings in each block.
*/
message StringTable {
repeated string s = 1;
}
@ -51,16 +60,9 @@ message MapTree {
repeated MapTree subtrees = 7;
repeated MapData leafs = 8;
}
// These messages could be read directly
/**
String table, contains the common strings in each block.
*/
message StringTable {
repeated string s = 1;
}
/// Simple messages
@ -76,7 +78,7 @@ message MapData {
optional int32 highwayMeta = 6;
}
/// Address messages
message OsmAndAddressIndex {
@ -120,7 +122,6 @@ message CityIndex {
}
message InteresectedStreets {
repeated StreetIntersection intersections = 5;
}
@ -162,4 +163,68 @@ message BuildingIndex {
required sint32 x = 3; // delta encoded to street 24 zoom
required sint32 y = 4; // delta encoded to street 24 zoom
}
// transport messages
message TransportRoute {
required uint64 id = 1;
optional uint32 type = 3; // reference in string table
optional uint32 operator = 4; // reference in string table
optional string ref = 5;
optional uint32 name = 6; // reference in string table
optional uint32 name_en = 7; // reference in string table
optional uint32 distance = 8; // distance in meters
repeated TransportRouteStop directStops = 15;
repeated TransportRouteStop reverseStops = 16;
}
message TransportRouteStop {
required sint64 id = 1; // delta encoded to previous stop (first stop is delta to 0)
required sint32 dx = 2; // delta encoded to previous stop (24 zoom)
required sint32 dy = 3; // delta encoded to previous stop (24 zoom)
required uint32 name = 6; // index in message table
optional uint32 name_en = 7; // index in message table
}
message TransportStop {
required sint64 id = 1; // delta encoded to parent base id
required sint32 dx = 2; // delta encoded to parent (24 zoom)
required sint32 dy = 3; // delta encoded to parent (24 zoom)
required uint32 name = 6; // index in message table
optional uint32 name_en = 7; // index in message table
repeated uint32 routes = 16; // -shift to transport route containing that stop
// (TransportStop.Message.start - routes[i] = TransportRoute.Message.start)
}
message TransportStopsTree {
required sint32 left = 1; // delta encoded (24 zoom)
required sint32 right = 2; // delta encoded (24 zoom)
required sint32 top = 3; // delta encoded (24 zoom)
required sint32 bottom = 4; // delta encoded (24 zoom)
// encoded as fixed32 length delimited
repeated TransportStopsTree subtrees = 7;
repeated TransportStop leafs = 8;
// written as last
optional uint64 baseId = 16;
}
message OsmAndTransportIndex {
repeated TransportRoute routes = 3; // routes
// encoded as fixed32 length delimited
optional TransportStopsTree stops = 6;
required StringTable stringTable = 9;
}

View file

@ -81,6 +81,8 @@ public class Pack
return 2;
}
}
public final int BUFFER_SIZE = 8192;
private int packTree(Element[] elmts, RTree rtree, String newFile)
{
try{
@ -112,10 +114,11 @@ public class Pack
//overwrite the old rtree file with the temp file
FileInputStream fis=new FileInputStream(tmpPckFile);
FileOutputStream fos=new FileOutputStream(fo);
int i=fis.available();
byte b[]=new byte[i];
while((i=fis.read(b))!=-1)
fos.write(b);
byte b[]=new byte[BUFFER_SIZE];
int i;
while((i=fis.read(b))!=-1){
fos.write(b, 0, i);
}
fos.close();
fis.close();
rFile.close();