From 1c2f22e7bc306bead9dbef84e8386f20c0e14456 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 20 Apr 2024 19:43:33 +0200 Subject: [PATCH] Use eight bytes for the geo ref (#2978) * Use eight bytes for the geo ref, #500 * minor fix --------- Co-authored-by: easbar --- .../com/graphhopper/storage/BaseGraph.java | 21 ++++----------- .../storage/BaseGraphNodesAndEdges.java | 26 +++++++++++-------- .../java/com/graphhopper/util/Constants.java | 2 +- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/com/graphhopper/storage/BaseGraph.java b/core/src/main/java/com/graphhopper/storage/BaseGraph.java index e1388d0aae4..aae60e2783e 100644 --- a/core/src/main/java/com/graphhopper/storage/BaseGraph.java +++ b/core/src/main/java/com/graphhopper/storage/BaseGraph.java @@ -51,7 +51,6 @@ public class BaseGraph implements Graph, Closeable { final TurnCostStorage turnCostStorage; final BitUtil bitUtil; // length | nodeA | nextNode | ... | nodeB - // as we use integer index in 'edges' area => 'geometry' area is limited to 4GB (we use pos&neg values!) private final DataAccess wayGeometry; private final Directory dir; private final int segmentSize; @@ -352,7 +351,7 @@ private void setWayGeometry_(PointList pillarNodes, long edgePointer, boolean re throw new IllegalArgumentException("Cannot use pointlist which is " + pillarNodes.getDimension() + "D for graph which is " + nodeAccess.getDimension() + "D"); - long existingGeoRef = Integer.toUnsignedLong(store.getGeoRef(edgePointer)); + long existingGeoRef = store.getGeoRef(edgePointer); int len = pillarNodes.size(); int dim = nodeAccess.getDimension(); @@ -367,7 +366,7 @@ private void setWayGeometry_(PointList pillarNodes, long edgePointer, boolean re long nextGeoRef = nextGeoRef(len * dim); setWayGeometryAtGeoRef(pillarNodes, edgePointer, reverse, nextGeoRef); } else { - store.setGeoRef(edgePointer, 0); + store.setGeoRef(edgePointer, 0L); } } @@ -388,14 +387,11 @@ public void setInt(int edgeId, int index, int value) { } private void setWayGeometryAtGeoRef(PointList pillarNodes, long edgePointer, boolean reverse, long geoRef) { - int len = pillarNodes.size(); - int dim = nodeAccess.getDimension(); long geoRefPosition = geoRef * 4; - int totalLen = len * dim * 4 + 4; - ensureGeometry(geoRefPosition, totalLen); byte[] wayGeometryBytes = createWayGeometryBytes(pillarNodes, reverse); + wayGeometry.ensureCapacity(geoRefPosition + wayGeometryBytes.length); wayGeometry.setBytes(geoRefPosition, wayGeometryBytes, wayGeometryBytes.length); - store.setGeoRef(edgePointer, BitUtil.toSignedInt(geoRef)); + store.setGeoRef(edgePointer, geoRef); } private byte[] createWayGeometryBytes(PointList pillarNodes, boolean reverse) { @@ -432,7 +428,7 @@ private PointList fetchWayGeometry_(long edgePointer, boolean reverse, FetchMode pillarNodes.add(nodeAccess, adjNode); return pillarNodes; } - long geoRef = Integer.toUnsignedLong(store.getGeoRef(edgePointer)); + long geoRef = store.getGeoRef(edgePointer); int count = 0; byte[] bytes = null; if (geoRef > 0) { @@ -492,16 +488,9 @@ static int getPointListLength(int pillarNodes, FetchMode mode) { throw new IllegalArgumentException("Mode isn't handled " + mode); } - private void ensureGeometry(long bytePos, int byteLength) { - wayGeometry.ensureCapacity(bytePos + byteLength); - } - private long nextGeoRef(int arrayLength) { long tmp = maxGeoRef; maxGeoRef += arrayLength + 1L; - if (maxGeoRef > MAX_UNSIGNED_INT) - throw new IllegalStateException("Geometry too large, does not fit in 32 bits " + maxGeoRef); - return tmp; } diff --git a/core/src/main/java/com/graphhopper/storage/BaseGraphNodesAndEdges.java b/core/src/main/java/com/graphhopper/storage/BaseGraphNodesAndEdges.java index 673eda58753..0e2e6c2cc2c 100644 --- a/core/src/main/java/com/graphhopper/storage/BaseGraphNodesAndEdges.java +++ b/core/src/main/java/com/graphhopper/storage/BaseGraphNodesAndEdges.java @@ -18,10 +18,7 @@ package com.graphhopper.storage; -import com.graphhopper.util.Constants; -import com.graphhopper.util.EdgeIterator; -import com.graphhopper.util.GHUtility; -import com.graphhopper.util.Helper; +import com.graphhopper.util.*; import com.graphhopper.util.shapes.BBox; import java.util.Locale; @@ -48,7 +45,7 @@ class BaseGraphNodesAndEdges { // edges private final DataAccess edges; - private final int E_NODEA, E_NODEB, E_LINKA, E_LINKB, E_FLAGS, E_DIST, E_GEO, E_KV; + private final int E_NODEA, E_NODEB, E_LINKA, E_LINKB, E_FLAGS, E_DIST, E_GEO_1, E_GEO_2, E_KV; private final int intsForFlags; private int edgeEntryBytes; private int edgeCount; @@ -85,8 +82,9 @@ public BaseGraphNodesAndEdges(Directory dir, int intsForFlags, boolean withEleva E_LINKB = 12; E_FLAGS = 16; E_DIST = E_FLAGS + intsForFlags * 4; - E_GEO = E_DIST + 4; - E_KV = E_GEO + 4; + E_GEO_1 = E_DIST + 4; + E_GEO_2 = E_GEO_1 + 4; + E_KV = E_GEO_2 + 4; edgeEntryBytes = E_KV + 4; } @@ -282,8 +280,11 @@ public void setDist(long edgePointer, double distance) { edges.setInt(edgePointer + E_DIST, distToInt(distance)); } - public void setGeoRef(long edgePointer, int geoRef) { - edges.setInt(edgePointer + E_GEO, geoRef); + public void setGeoRef(long edgePointer, long geoRef) { + int geo1 = BitUtil.LITTLE.getIntLow(geoRef); + int geo2 = BitUtil.LITTLE.getIntHigh(geoRef); + edges.setInt(edgePointer + E_GEO_1, geo1); + edges.setInt(edgePointer + E_GEO_2, geo2); } public void setKeyValuesRef(long edgePointer, int nameRef) { @@ -312,8 +313,11 @@ public double getDist(long pointer) { return val / INT_DIST_FACTOR; } - public int getGeoRef(long edgePointer) { - return edges.getInt(edgePointer + E_GEO); + public long getGeoRef(long edgePointer) { + return BitUtil.LITTLE.toLong( + edges.getInt(edgePointer + E_GEO_1), + edges.getInt(edgePointer + E_GEO_2) + ); } public int getKeyValuesRef(long edgePointer) { diff --git a/core/src/main/java/com/graphhopper/util/Constants.java b/core/src/main/java/com/graphhopper/util/Constants.java index 498479f8d1a..87f6f63d990 100644 --- a/core/src/main/java/com/graphhopper/util/Constants.java +++ b/core/src/main/java/com/graphhopper/util/Constants.java @@ -59,7 +59,7 @@ public class Constants { private static final int JVM_MINOR_VERSION; public static final int VERSION_NODE = 9; - public static final int VERSION_EDGE = 21; + public static final int VERSION_EDGE = 22; // this should be increased whenever the format of the serialized EncodingManager is changed public static final int VERSION_EM = 3; public static final int VERSION_SHORTCUT = 9;