Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into issue2980
Browse files Browse the repository at this point in the history
  • Loading branch information
ratrun committed May 1, 2024
2 parents be90372 + ee68d2b commit 3ba603d
Show file tree
Hide file tree
Showing 68 changed files with 914 additions and 737 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
### 9.0 [not yet released]
### 10.0 [not yet released]

- constructor of BaseGraph.Builder uses byte instead of integer count.
- KeyValue is now KValue as it holds the value only. Note, the two parameter constructor uses one value for the forward and one for the backward direction (and no longer "key, value")

### 9.0 [23 Apr 2024]

- max_slope is now a signed decimal, see #2955
- move sac_scale handling out of foot_access parser and made foot safer via lowering to sac_scale<2, same for hike sac_scale<5
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@ We even have [good first issues](https://github.com/graphhopper/graphhopper/issu

To get started you can try [GraphHopper Maps](README.md#graphhopper-maps), read through our documentation and install the GraphHopper Web Service locally.

* 8.x: [documentation](https://github.com/graphhopper/graphhopper/blob/8.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/8.0/graphhopper-web-8.0.jar)
, [announcement](https://www.graphhopper.com/blog/2023/10/18/graphhopper-routing-engine-8-0-released/)
* 9.x: [documentation](https://github.com/graphhopper/graphhopper/blob/9.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/9.0/graphhopper-web-9.0.jar)
, [announcement](https://www.graphhopper.com/blog/2024/04/23/graphhopper-routing-engine-9-0-released)
* unstable master: [documentation](https://github.com/graphhopper/graphhopper/blob/master/docs/index.md)

<details><summary>Click to see older releases</summary>

* See our [changelog file](./CHANGELOG.md) for Java API Changes.

* 8.x: [documentation](https://github.com/graphhopper/graphhopper/blob/8.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/8.0/graphhopper-web-8.0.jar)
, [announcement](https://www.graphhopper.com/blog/2023/10/18/graphhopper-routing-engine-8-0-released/)
* 7.x: [documentation](https://github.com/graphhopper/graphhopper/blob/7.x/docs/index.md)
, [web service jar](https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/7.0/graphhopper-web-7.0.jar)
, [announcement](https://www.graphhopper.com/blog/2023/03/14/graphhopper-routing-engine-7-0-released/)
Expand Down
4 changes: 2 additions & 2 deletions client-hc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>directions-api-client-hc</artifactId>
<version>9.0-SNAPSHOT</version>
<version>10.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>GraphHopper Directions API hand-crafted Java Client.</name>

<parent>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-parent</artifactId>
<version>9.0-SNAPSHOT</version>
<version>10.0-SNAPSHOT</version>
</parent>

<dependencies>
Expand Down
4 changes: 2 additions & 2 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<artifactId>graphhopper-core</artifactId>
<name>GraphHopper Core</name>
<version>9.0-SNAPSHOT</version>
<version>10.0-SNAPSHOT</version>
<packaging>jar</packaging>
<description>
GraphHopper is a fast and memory efficient Java road routing engine
Expand All @@ -14,7 +14,7 @@
<parent>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-parent</artifactId>
<version>9.0-SNAPSHOT</version>
<version>10.0-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,9 @@ public void addCoordinatesToPointList(long id, PointList pointList) {
public void setTags(ReaderNode node) {
int tagIndex = Math.toIntExact(nodeTagIndicesByOsmNodeIds.get(node.getId()));
if (tagIndex == -1) {
long pointer = nodeKVStorage.add(node.getTags().entrySet().stream().map(m -> new KVStorage.KeyValue(m.getKey(),
m.getValue() instanceof String ? KVStorage.cutString((String) m.getValue()) : m.getValue())).
collect(Collectors.toList()));
long pointer = nodeKVStorage.add(node.getTags().entrySet().stream().collect(
Collectors.toMap(Map.Entry::getKey, // same key
e -> new KVStorage.KValue(e.getValue() instanceof String ? KVStorage.cutString((String) e.getValue()) : e.getValue()))));
if (pointer > Integer.MAX_VALUE)
throw new IllegalStateException("Too many key value pairs are stored in node tags, was " + pointer);
nodeTagIndicesByOsmNodeIds.put(node.getId(), (int) pointer);
Expand Down
51 changes: 27 additions & 24 deletions core/src/main/java/com/graphhopper/reader/osm/OSMReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.graphhopper.search.KVStorage.KeyValue.*;
import static com.graphhopper.search.KVStorage.KValue;
import static com.graphhopper.util.GHUtility.OSM_WARNING_LOGGER;
import static com.graphhopper.util.Helper.nf;
import static com.graphhopper.util.Parameters.Details.*;
import static java.util.Collections.emptyList;

/**
Expand Down Expand Up @@ -103,7 +104,7 @@ public class OSMReader {

public OSMReader(BaseGraph baseGraph, OSMParsers osmParsers, OSMReaderConfig config) {
this.baseGraph = baseGraph;
this.edgeIntAccess = baseGraph.createEdgeIntAccess();
this.edgeIntAccess = baseGraph.getEdgeAccess();
this.config = config;
this.nodeAccess = baseGraph.getNodeAccess();
this.osmParsers = osmParsers;
Expand Down Expand Up @@ -370,9 +371,9 @@ else if (!config.getElevationSmoothing().isEmpty())
IntsRef relationFlags = getRelFlagsMap(way.getId());
EdgeIteratorState edge = baseGraph.edge(fromIndex, toIndex).setDistance(distance);
osmParsers.handleWayTags(edge.getEdge(), edgeIntAccess, way, relationFlags);
List<KVStorage.KeyValue> list = way.getTag("key_values", Collections.emptyList());
if (!list.isEmpty())
edge.setKeyValues(list);
Map<String, KValue> map = way.getTag("key_values", Collections.emptyMap());
if (!map.isEmpty())
edge.setKeyValues(map);

// If the entire way is just the first and last point, do not waste space storing an empty way geometry
if (pointList.size() > 2) {
Expand Down Expand Up @@ -414,7 +415,7 @@ else if (Math.abs(edgeDistance - geometryDistance) > tolerance)
*/
protected void preprocessWay(ReaderWay way, WaySegmentParser.CoordinateSupplier coordinateSupplier,
WaySegmentParser.NodeTagSupplier nodeTagSupplier) {
List<KVStorage.KeyValue> list = new ArrayList<>();
Map<String, KValue> map = new LinkedHashMap<>();
if (config.isParseWayNames()) {
// http://wiki.openstreetmap.org/wiki/Key:name
String name = "";
Expand All @@ -423,28 +424,28 @@ protected void preprocessWay(ReaderWay way, WaySegmentParser.CoordinateSupplier
if (name.isEmpty())
name = fixWayName(way.getTag("name"));
if (!name.isEmpty())
list.add(new KVStorage.KeyValue(STREET_NAME, name));
map.put(STREET_NAME, new KValue(name));

// http://wiki.openstreetmap.org/wiki/Key:ref
String refName = fixWayName(way.getTag("ref"));
if (!refName.isEmpty())
list.add(new KVStorage.KeyValue(STREET_REF, refName));
map.put(STREET_REF, new KValue(refName));

if (way.hasTag("destination:ref")) {
list.add(new KVStorage.KeyValue(STREET_DESTINATION_REF, fixWayName(way.getTag("destination:ref"))));
map.put(STREET_DESTINATION_REF, new KValue(fixWayName(way.getTag("destination:ref"))));
} else {
if (way.hasTag("destination:ref:forward"))
list.add(new KVStorage.KeyValue(STREET_DESTINATION_REF, fixWayName(way.getTag("destination:ref:forward")), true, false));
if (way.hasTag("destination:ref:backward"))
list.add(new KVStorage.KeyValue(STREET_DESTINATION_REF, fixWayName(way.getTag("destination:ref:backward")), false, true));
String fwdStr = fixWayName(way.getTag("destination:ref:forward"));
String bwdStr = fixWayName(way.getTag("destination:ref:backward"));
if (!fwdStr.isEmpty() || !bwdStr.isEmpty())
map.put(STREET_DESTINATION_REF, new KValue(fwdStr.isEmpty() ? null : fwdStr, bwdStr.isEmpty() ? null : bwdStr));
}
if (way.hasTag("destination")) {
list.add(new KVStorage.KeyValue(STREET_DESTINATION, fixWayName(way.getTag("destination"))));
map.put(STREET_DESTINATION, new KValue(fixWayName(way.getTag("destination"))));
} else {
if (way.hasTag("destination:forward"))
list.add(new KVStorage.KeyValue(STREET_DESTINATION, fixWayName(way.getTag("destination:forward")), true, false));
if (way.hasTag("destination:backward"))
list.add(new KVStorage.KeyValue(STREET_DESTINATION, fixWayName(way.getTag("destination:backward")), false, true));
String fwdStr = fixWayName(way.getTag("destination:forward"));
String bwdStr = fixWayName(way.getTag("destination:backward"));
if (!fwdStr.isEmpty() || !bwdStr.isEmpty())
map.put(STREET_DESTINATION, new KValue(fwdStr.isEmpty() ? null : fwdStr, bwdStr.isEmpty() ? null : bwdStr));
}

// copy node name of motorway_junction
Expand All @@ -454,7 +455,7 @@ protected void preprocessWay(ReaderWay way, WaySegmentParser.CoordinateSupplier
Map<String, Object> nodeTags = nodeTagSupplier.getTags(nodes.get(0));
String nodeName = (String) nodeTags.getOrDefault("name", "");
if (!nodeName.isEmpty() && "motorway_junction".equals(nodeTags.getOrDefault("highway", "")))
list.add(new KVStorage.KeyValue(MOTORWAY_JUNCTION, nodeName));
map.put(MOTORWAY_JUNCTION, new KValue(nodeName));
}
}

Expand All @@ -469,14 +470,16 @@ protected void preprocessWay(ReaderWay way, WaySegmentParser.CoordinateSupplier
String key = entry.getKey().replace(':', '_').replace("bicycle", "bike");
boolean fwd = key.contains("forward");
boolean bwd = key.contains("backward");
if (!fwd && !bwd)
list.add(new KVStorage.KeyValue(key, value, true, true));
else
list.add(new KVStorage.KeyValue(key, value, fwd, bwd));
if (!value.isEmpty()) {
if (fwd == bwd)
map.put(key, new KValue(value));
else
map.put(key, new KValue(fwd ? value : null, bwd ? value : null));
}
}
}

way.setTag("key_values", list);
way.setTag("key_values", map);

if (!isCalculateWayDistance(way))
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
import com.graphhopper.util.*;
import com.graphhopper.util.shapes.GHPoint;

import static com.graphhopper.search.KVStorage.KeyValue.*;
import static com.graphhopper.search.KVStorage.KValue.*;
import static com.graphhopper.util.Parameters.Details.*;

/**
* This class calculates instructions from the edges in a Path.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public ArrayEdgeIntAccess(int intsPerEdge) {
this.intsPerEdge = intsPerEdge;
}

/**
* Ensures that the underlying storage has enough integers reserved for the specified bytes.
*/
public static ArrayEdgeIntAccess createFromBytes(int bytes) {
return new ArrayEdgeIntAccess((int) Math.ceil((double) bytes / 4));
}

@Override
public int getInt(int edgeId, int index) {
int arrIndex = edgeId * intsPerEdge + index;
Expand All @@ -42,4 +49,4 @@ public void setInt(int edgeId, int index, int value) {
arr.set(arrIndex, value);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ void next(int usedBits) {
nextShift = shift + usedBits;
}

public int getRequiredBits() {
private int getRequiredBits() {
return (dataIndex) * 32 + nextShift;
}

public int getRequiredInts() {
return (int) Math.ceil((double) getRequiredBits() / 32.0);
}

public int getRequiredBytes() {
return (int) Math.ceil((double) getRequiredBits() / 8.0);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ final void uncheckedSet(boolean reverse, int edgeId, EdgeIntAccess edgeIntAccess

@Override
public final int getInt(boolean reverse, int edgeId, EdgeIntAccess edgeIntAccess) {
assert fwdShift >= 0 : "incorrect shift " + fwdShift + " for " + getName();
assert bits > 0 : "incorrect bits " + bits + " for " + getName();

int flags;
// if we do not store both directions ignore reverse == true for convenient reading
if (storeTwoDirections && reverse) {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/com/graphhopper/routing/ev/MaxWeight.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ public class MaxWeight {
public static final String KEY = "max_weight";

/**
* Currently enables to store 0.1 to max=0.1*2 tons and infinity. If a value is between the maximum and infinity
* Currently enables to store 0.1 to max=0.1*2 tons and infinity. If a value is between the maximum and infinity
* it is assumed to use the maximum value. To save bits it might make more sense to store only a few values like
* it was done with the MappedDecimalEncodedValue still handling (or rounding) of unknown values is unclear.
*/
public static DecimalEncodedValue create() {
return new DecimalEncodedValueImpl(KEY, 8, 0, 0.1, false, false, true);
return new DecimalEncodedValueImpl(KEY, 9, 0, 0.1, false, false, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@
import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.*;

import static com.graphhopper.util.DistancePlaneProjection.DIST_PLANE;

Expand Down Expand Up @@ -233,7 +230,7 @@ private void createEdges(int origEdgeKey, int origRevEdgeKey,

boolean reverse = closestEdge.get(EdgeIteratorState.REVERSE_STATE);
// edges between base and snapped point
List<KVStorage.KeyValue> keyValues = closestEdge.getKeyValues();
Map<String, KVStorage.KValue> keyValues = closestEdge.getKeyValues();
VirtualEdgeIteratorState baseEdge = new VirtualEdgeIteratorState(origEdgeKey, GHUtility.createEdgeKey(virtEdgeId, false),
prevNodeId, nodeId, baseDistance, closestEdge.getFlags(), keyValues, basePoints, reverse);
VirtualEdgeIteratorState baseReverseEdge = new VirtualEdgeIteratorState(origRevEdgeKey, GHUtility.createEdgeKey(virtEdgeId, true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.graphhopper.util.PointList;

import java.util.List;
import java.util.Map;

/**
* @author Peter Karich
Expand Down Expand Up @@ -262,12 +263,12 @@ public String getName() {
}

@Override
public List<KVStorage.KeyValue> getKeyValues() {
public Map<String, KVStorage.KValue> getKeyValues() {
return getCurrentEdge().getKeyValues();
}

@Override
public EdgeIteratorState setKeyValues(List<KVStorage.KeyValue> list) {
public EdgeIteratorState setKeyValues(Map<String, KVStorage.KValue> list) {
return getCurrentEdge().setKeyValues(list);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import com.graphhopper.util.GHUtility;
import com.graphhopper.util.PointList;

import java.util.List;
import java.util.Map;

import static com.graphhopper.util.Parameters.Details.STREET_NAME;

/**
* Creates an edge state decoupled from a graph where nodes, pointList, etc are kept in memory.
Expand All @@ -42,14 +44,14 @@ public class VirtualEdgeIteratorState implements EdgeIteratorState {
private double distance;
private IntsRef edgeFlags;
private EdgeIntAccess edgeIntAccess;
private List<KVStorage.KeyValue> keyValues;
private Map<String, KVStorage.KValue> keyValues;
// true if edge should be avoided as start/stop
private boolean unfavored;
private EdgeIteratorState reverseEdge;
private final boolean reverse;

public VirtualEdgeIteratorState(int originalEdgeKey, int edgeKey, int baseNode, int adjNode, double distance,
IntsRef edgeFlags, List<KVStorage.KeyValue> keyValues, PointList pointList, boolean reverse) {
IntsRef edgeFlags, Map<String, KVStorage.KValue> keyValues, PointList pointList, boolean reverse) {
this.originalEdgeKey = originalEdgeKey;
this.edgeKey = edgeKey;
this.baseNode = baseNode;
Expand Down Expand Up @@ -313,27 +315,28 @@ public EdgeIteratorState set(StringEncodedValue property, String fwd, String bwd

@Override
public String getName() {
String name = (String) getValue(KVStorage.KeyValue.STREET_NAME);
String name = (String) getValue(STREET_NAME);
// preserve backward compatibility (returns empty string if name tag missing)
return name == null ? "" : name;
}

@Override
public EdgeIteratorState setKeyValues(List<KVStorage.KeyValue> list) {
public EdgeIteratorState setKeyValues(Map<String, KVStorage.KValue> list) {
this.keyValues = list;
return this;
}

@Override
public List<KVStorage.KeyValue> getKeyValues() {
public Map<String, KVStorage.KValue> getKeyValues() {
return keyValues;
}

@Override
public Object getValue(String key) {
for (KVStorage.KeyValue keyValue : keyValues) {
if (keyValue.key.equals(key) && (!reverse && keyValue.fwd || reverse && keyValue.bwd))
return keyValue.value;
KVStorage.KValue value = keyValues.get(key);
if (value != null) {
if (!reverse && value.getFwd() != null) return value.getFwd();
if (reverse && value.getBwd() != null) return value.getBwd();
}
return null;
}
Expand Down
Loading

0 comments on commit 3ba603d

Please sign in to comment.