lmConfigs = createLMConfigs(lmPreparationHandler.getLMProfiles());
+ if (lmPreparationHandler.loadOrDoWork(lmConfigs, ghStorage, locationIndex, closeEarly)) {
for (LMProfile profile : lmPreparationHandler.getLMProfiles()) {
// potentially overwrite existing keys from CH
setProfileVersion(profile.getProfile(), profilesByName.get(profile.getProfile()).getVersion());
@@ -1300,4 +1216,8 @@ public boolean getFullyLoaded() {
public RouterConfig getRouterConfig() {
return routerConfig;
}
-}
+
+ public OSMReaderConfig getReaderConfig() {
+ return osmReaderConfig;
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/com/graphhopper/coll/GHLongIntBTree.java b/core/src/main/java/com/graphhopper/coll/GHLongIntBTree.java
index b6ded2c3d28..e556083e464 100644
--- a/core/src/main/java/com/graphhopper/coll/GHLongIntBTree.java
+++ b/core/src/main/java/com/graphhopper/coll/GHLongIntBTree.java
@@ -31,13 +31,13 @@
* @author Peter Karich
*/
public class GHLongIntBTree implements LongIntMap {
+ private final static Logger logger = LoggerFactory.getLogger(GHLongIntBTree.class);
private final int noNumberValue = -1;
- private Logger logger = LoggerFactory.getLogger(getClass());
+ private final int maxLeafEntries;
+ private final int initLeafSize;
+ private final int splitIndex;
+ private final float factor;
private long size;
- private int maxLeafEntries;
- private int initLeafSize;
- private int splitIndex;
- private float factor;
private int height;
private BTreeEntry root;
@@ -64,8 +64,7 @@ public GHLongIntBTree(int maxLeafEntries) {
clear();
}
- // LATER: see OSMIDMap for a version where we use DataAccess
- static int binarySearch(long keys[], int start, int len, long key) {
+ static int binarySearch(long[] keys, int start, int len, long key) {
int high = start + len, low = start - 1, guess;
while (high - low > 1) {
// use >>> for average or we could get an integer overflow.
@@ -184,9 +183,9 @@ public ReturnValue(int oldValue) {
class BTreeEntry {
int entrySize;
- long keys[];
- int values[];
- BTreeEntry children[];
+ long[] keys;
+ int[] values;
+ BTreeEntry[] children;
boolean isLeaf;
public BTreeEntry(int tmpSize, boolean leaf) {
diff --git a/core/src/main/java/com/graphhopper/coll/OSMIDMap.java b/core/src/main/java/com/graphhopper/coll/OSMIDMap.java
deleted file mode 100644
index 079bf2c99a5..00000000000
--- a/core/src/main/java/com/graphhopper/coll/OSMIDMap.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Licensed to GraphHopper GmbH under one or more contributor
- * license agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * GraphHopper GmbH licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.graphhopper.coll;
-
-import com.graphhopper.storage.DataAccess;
-import com.graphhopper.storage.Directory;
-import com.graphhopper.util.BitUtil;
-import com.graphhopper.util.Helper;
-
-/**
- * This is a special purpose map for writing increasing OSM IDs with consecutive values. It stores
- * a map from long to int in a memory friendly way and but does NOT provide O(1) access.
- *
- *
- * @author Peter Karich
- */
-public class OSMIDMap implements LongIntMap {
- private static final BitUtil bitUtil = BitUtil.LITTLE;
- private final DataAccess keys;
- private final DataAccess values;
- private final int noEntryValue;
- private final Directory dir;
- private long lastKey = Long.MIN_VALUE;
- private long size;
-
- public OSMIDMap(Directory dir) {
- this(dir, -1);
- }
-
- public OSMIDMap(Directory dir, int noNumber) {
- this.dir = dir;
- this.noEntryValue = noNumber;
- keys = dir.find("osmid_map_keys");
- keys.create(2000);
- values = dir.find("osmid_map_values");
- values.create(1000);
- }
-
- static long binarySearch(DataAccess da, long start, long len, long key) {
- long high = start + len, low = start - 1, guess;
- byte[] longBytes = new byte[8];
- while (high - low > 1) {
- // use >>> for average or we could get an integer overflow.
- guess = (high + low) >>> 1;
- long tmp = guess << 3;
- da.getBytes(tmp, longBytes, 8);
- long guessedKey = bitUtil.toLong(longBytes);
- if (guessedKey < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
-
- long tmp = high << 3;
- da.getBytes(tmp, longBytes, 8);
- long highKey = bitUtil.toLong(longBytes);
- if (highKey == key)
- return high;
- else
- return ~high;
- }
-
- public void remove() {
- dir.remove(keys);
- }
-
- @Override
- public int put(long key, int value) {
- if (key <= lastKey) {
- long oldValueIndex = binarySearch(keys, 0, getSize(), key);
- if (oldValueIndex < 0) {
- throw new IllegalStateException("Cannot insert keys lower than "
- + "the last key " + key + " < " + lastKey + ". Only updating supported");
- }
- oldValueIndex *= 4;
- int oldValue = values.getInt(oldValueIndex);
- values.setInt(oldValueIndex, value);
- return oldValue;
- }
-
- values.ensureCapacity(size + 4);
- values.setInt(size, value);
- long doubleSize = size * 2;
- keys.ensureCapacity(doubleSize + 8);
-
- // store long => double of the orig size
- byte[] longBytes = bitUtil.fromLong(key);
- keys.setBytes(doubleSize, longBytes, 8);
- lastKey = key;
- size += 4;
- return -1;
- }
-
- @Override
- public int get(long key) {
- long retIndex = binarySearch(keys, 0, getSize(), key);
- if (retIndex < 0)
- return noEntryValue;
-
- return values.getInt(retIndex * 4);
- }
-
- @Override
- public long getSize() {
- return size / 4;
- }
-
- public long getCapacity() {
- return keys.getCapacity();
- }
-
- @Override
- public int getMemoryUsage() {
- return Math.round(getCapacity() / Helper.MB);
- }
-
- @Override
- public void optimize() {
- }
-}
diff --git a/core/src/main/java/com/graphhopper/reader/PillarInfo.java b/core/src/main/java/com/graphhopper/reader/PillarInfo.java
index 81ec1f8c893..fd2e3eb221d 100644
--- a/core/src/main/java/com/graphhopper/reader/PillarInfo.java
+++ b/core/src/main/java/com/graphhopper/reader/PillarInfo.java
@@ -38,7 +38,7 @@ public class PillarInfo implements PointAccess {
public PillarInfo(boolean enabled3D, Directory dir) {
this.enabled3D = enabled3D;
this.dir = dir;
- this.da = dir.find("tmp_pillar_info").create(100);
+ this.da = dir.create("tmp_pillar_info").create(100);
this.rowSizeInBytes = getDimension() * 4;
}
diff --git a/core/src/main/java/com/graphhopper/reader/ReaderElement.java b/core/src/main/java/com/graphhopper/reader/ReaderElement.java
index 3688ebe925c..d313429dcf0 100644
--- a/core/src/main/java/com/graphhopper/reader/ReaderElement.java
+++ b/core/src/main/java/com/graphhopper/reader/ReaderElement.java
@@ -37,13 +37,13 @@ public abstract class ReaderElement {
private final Map properties;
protected ReaderElement(long id, int type) {
- this(id, type, 4);
+ this(id, type, new HashMap<>(4));
}
- protected ReaderElement(long id, int type, int propertyMapSize) {
+ protected ReaderElement(long id, int type, Map properties) {
this.id = id;
this.type = type;
- properties = new HashMap<>(propertyMapSize);
+ this.properties = properties;
}
// ORS-GH MOD START
@@ -76,11 +76,7 @@ protected String tagsToString() {
return tagTxt.toString();
}
- // ORS-GH MOD START - change access level
- // Used in OSMReader mod to get node tags when processing edge edge
- //protected Map getTags()
public Map getTags() {
- // ORS-GH MOD END
return properties;
}
diff --git a/core/src/main/java/com/graphhopper/reader/ReaderNode.java b/core/src/main/java/com/graphhopper/reader/ReaderNode.java
index 46106aff418..f40f520fd42 100644
--- a/core/src/main/java/com/graphhopper/reader/ReaderNode.java
+++ b/core/src/main/java/com/graphhopper/reader/ReaderNode.java
@@ -17,6 +17,8 @@
*/
package com.graphhopper.reader;
+import java.util.Map;
+
/**
* Represents a node received from the reader.
*
@@ -33,6 +35,12 @@ public ReaderNode(long id, double lat, double lon) {
this.lon = lon;
}
+ public ReaderNode(long id, double lat, double lon, Map tags) {
+ super(id, NODE, tags);
+ this.lat = lat;
+ this.lon = lon;
+ }
+
public double getLat() {
return lat;
}
@@ -74,7 +82,7 @@ public String toString() {
txt.append(getLat());
txt.append(" lon=");
txt.append(getLon());
- if (!getTags().isEmpty()) {
+ if (hasTags()) {
txt.append("\n");
txt.append(tagsToString());
}
diff --git a/core/src/main/java/com/graphhopper/reader/ReaderRelation.java b/core/src/main/java/com/graphhopper/reader/ReaderRelation.java
index e3c41549e31..4011fbb530a 100644
--- a/core/src/main/java/com/graphhopper/reader/ReaderRelation.java
+++ b/core/src/main/java/com/graphhopper/reader/ReaderRelation.java
@@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
/**
@@ -31,7 +32,7 @@ public class ReaderRelation extends ReaderElement {
protected List members;
public ReaderRelation(long id) {
- super(id, RELATION, 2);
+ super(id, RELATION, new HashMap<>(2));
}
@Override
diff --git a/core/src/main/java/com/graphhopper/reader/dem/AbstractSRTMElevationProvider.java b/core/src/main/java/com/graphhopper/reader/dem/AbstractSRTMElevationProvider.java
index d6b599a2d8f..6185ed9669d 100644
--- a/core/src/main/java/com/graphhopper/reader/dem/AbstractSRTMElevationProvider.java
+++ b/core/src/main/java/com/graphhopper/reader/dem/AbstractSRTMElevationProvider.java
@@ -34,8 +34,6 @@
* @author Robin Boldt
*/
public abstract class AbstractSRTMElevationProvider extends TileBasedElevationProvider {
-
- private static final BitUtil BIT_UTIL = BitUtil.BIG;
private final int DEFAULT_WIDTH;
private final int MIN_LAT;
private final int MAX_LAT;
@@ -102,7 +100,7 @@ public double getEle(double lat, double lon) {
if (fileName == null)
return 0;
- DataAccess heights = getDirectory().find("dem" + intKey);
+ DataAccess heights = getDirectory().create("dem" + intKey);
boolean loadExisting = false;
try {
loadExisting = heights.loadExisting();
@@ -146,7 +144,8 @@ private void updateHeightsFromFile(double lat, double lon, DataAccess heights) t
byte[] bytes = getByteArrayFromFile(lat, lon);
heights.create(bytes.length);
for (int bytePos = 0; bytePos < bytes.length; bytePos += 2) {
- short val = BIT_UTIL.toShort(bytes, bytePos);
+ // we need big endianess to read the SRTM files
+ short val = BitUtil.BIG.toShort(bytes, bytePos);
if (val < -1000 || val > 12000)
val = Short.MIN_VALUE;
diff --git a/core/src/main/java/com/graphhopper/reader/dem/AbstractTiffElevationProvider.java b/core/src/main/java/com/graphhopper/reader/dem/AbstractTiffElevationProvider.java
index 0383d2af57b..142a85e3418 100644
--- a/core/src/main/java/com/graphhopper/reader/dem/AbstractTiffElevationProvider.java
+++ b/core/src/main/java/com/graphhopper/reader/dem/AbstractTiffElevationProvider.java
@@ -117,7 +117,7 @@ public double getEle(double lat, double lon) {
demProvider.setInterpolate(interpolate);
cacheData.put(name, demProvider);
- DataAccess heights = getDirectory().find(name + ".gh");
+ DataAccess heights = getDirectory().create(name + ".gh");
demProvider.setHeights(heights);
boolean loadExisting = false;
try {
diff --git a/core/src/main/java/com/graphhopper/reader/osm/OSMInputFile.java b/core/src/main/java/com/graphhopper/reader/osm/OSMInputFile.java
index 8d98c4589a4..6e2a4204a39 100644
--- a/core/src/main/java/com/graphhopper/reader/osm/OSMInputFile.java
+++ b/core/src/main/java/com/graphhopper/reader/osm/OSMInputFile.java
@@ -75,8 +75,8 @@ public OSMInputFile open() throws XMLStreamException {
/**
* Currently on for pbf format. Default is number of cores.
*/
- public OSMInputFile setWorkerThreads(int num) {
- workerThreads = num;
+ public OSMInputFile setWorkerThreads(int threads) {
+ workerThreads = threads;
return this;
}
diff --git a/core/src/main/java/com/graphhopper/reader/osm/OSMNodeData.java b/core/src/main/java/com/graphhopper/reader/osm/OSMNodeData.java
new file mode 100644
index 00000000000..60ac89d37c0
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/OSMNodeData.java
@@ -0,0 +1,287 @@
+/*
+ * Licensed to GraphHopper GmbH under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper GmbH licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.graphhopper.reader.osm;
+
+import com.graphhopper.coll.GHLongIntBTree;
+import com.graphhopper.coll.LongIntMap;
+import com.graphhopper.reader.PillarInfo;
+import com.graphhopper.reader.ReaderNode;
+import com.graphhopper.storage.Directory;
+import com.graphhopper.util.PointAccess;
+import com.graphhopper.util.PointList;
+import com.graphhopper.util.shapes.GHPoint3D;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.IntUnaryOperator;
+
+import static java.util.Collections.emptyMap;
+
+/**
+ * This class stores OSM node data while reading an OSM file in {@link WaySegmentParser}. It is not trivial to do this
+ * in a memory-efficient way. We use the following approach:
+ *
+ * - For each OSM node we store an integer id that points to the nodes coordinates. We use both positive and negative
+ * ids to make use of the full integer range (~4 billion nodes). We separate nodes into (potential) tower nodes and
+ * pillar nodes. We use the negative ids for tower nodes and positive ids for pillar nodes. In the future we might
+ * have to consider the fact that there are more pillar nodes than tower nodes and use a different separation.
+ * - We reserve a few special ids like {@link #JUNCTION_NODE} to distinguish the different node types when we read the
+ * OSM file for the first time (pass1) in {@link WaySegmentParser}. We then assign actual ids in the second pass.
+ * - We store the node coordinates for tower and pillar nodes in different places. The pillar node storage is only
+ * temporary, because at the time we store the coordinates it is unknown to which edge each pillar node will belong.
+ * The tower node storage, however, can be re-used for the final graph created by {@link OSMReader} so we store the
+ * tower coordinates there already to save memory during import.
+ * - We store an additional mapping between OSM node Ids and tag indices that point into a list of node tags. We use
+ * a different mapping, because we store node tags for only a small fraction of all OSM nodes.
+ *
+ */
+// ORS-GH MOD START expose to ORS
+public class OSMNodeData {
+// ORS-GH MOD END
+ static final int JUNCTION_NODE = -2;
+ static final int EMPTY_NODE = -1;
+ static final int END_NODE = 0;
+ static final int INTERMEDIATE_NODE = 1;
+ static final int CONNECTION_NODE = 2;
+
+ // this map stores our internal node id for each OSM node
+ private final LongIntMap idsByOsmNodeIds;
+
+ // here we store node coordinates, separated for pillar and tower nodes
+ private final PillarInfo pillarNodes;
+ private final PointAccess towerNodes;
+
+ // this map stores an index for each OSM node we keep the node tags of. a value of -1 means there is no entry
+ // yet and a value of -2 means there was an entry but it was removed again
+ private final LongIntMap nodeTagIndicesByOsmNodeIds;
+
+ // stores node tags
+ private final List