Skip to content

Commit ee9bf6a

Browse files
authored
move relation and turn relation parsing out of FlagEncoder (graphhopper#1775)
* move relation handling out of FlagEncoder and made core green * made all green * do not remove module permanently * remove more code in HikeFlagEncoder * use Helper.toLowerCase * reduce code for Car4WDFlagEncoder * minor improvements * made tests passing in GH core * all tests pass * moved code from OSMReader into OSMTurnCostParser * less clutter in TurnCostParser interface * minor renaming * remove method * fix bug for ways with multiple relations; removed Route.java * merged master * clean up * move turn cost flags creation into new TurnCost class; fixed some TODO NOWs * Fix merge issue * deleted TurnCostAccess * fixed merge conflicts * renamed TurnCostExtension to TurnCostStorage * remove TCEntry.flags * refactor method signature for similarity with TagParser interface * delay decision into TurnWeighting refactoring * More add/set turn cost renaming * Cleanup in tests, fix signature in ShortcutUnpackerTest * Put back setRandomCostOrRestriction * Fix test * include comment regarding u-turn again * Minor comments, change field name * get rid of TCEntry
1 parent 03f1f65 commit ee9bf6a

File tree

99 files changed

+1666
-1677
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+1666
-1677
lines changed

api/src/main/java/com/graphhopper/util/Helper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public static int countBitValue(int maxTurnCosts) {
8484
maxTurnCosts >>= 1;
8585
counter++;
8686
}
87-
return counter++;
87+
return counter;
8888
}
8989

9090
public static void saveProperties(Map<String, String> map, Writer tmpWriter) throws IOException {

core/src/main/java/com/graphhopper/routing/Path.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
public class Path {
4343
protected Graph graph;
4444
protected double distance;
45-
protected boolean reverseOrder = true;
4645
protected long time;
4746
protected int endNode = -1;
47+
private boolean reverseOrder = true;
4848
private List<String> description;
4949
private boolean found;
5050
private int fromNode = -1;

core/src/main/java/com/graphhopper/routing/profiles/DefaultEncodedValueFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package com.graphhopper.routing.profiles;
1919

20+
import com.graphhopper.routing.util.EncodingManager;
2021
import com.graphhopper.util.Helper;
2122

2223
public class DefaultEncodedValueFactory implements EncodedValueFactory {
@@ -59,6 +60,8 @@ public EncodedValue create(String string) {
5960
enc = new EnumEncodedValue<>(Toll.KEY, Toll.class);
6061
} else if (TrackType.KEY.equals(name)) {
6162
enc = new EnumEncodedValue<>(TrackType.KEY, TrackType.class);
63+
} else if (name.endsWith(EncodingManager.getKey("", RouteNetwork.EV_SUFFIX))) {
64+
enc = new EnumEncodedValue<>(EncodingManager.getKey(name, RouteNetwork.EV_SUFFIX), RouteNetwork.class);
6265
} else if (Hazmat.KEY.equals(name)) {
6366
enc = new EnumEncodedValue<>(Hazmat.KEY, Hazmat.class);
6467
} else if (HazmatTunnel.KEY.equals(name)) {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package com.graphhopper.routing.profiles;
19+
20+
import com.graphhopper.util.Helper;
21+
22+
public enum RouteNetwork {
23+
24+
OTHER("other"), INTERNATIONAL("international"), NATIONAL("national"), REGIONAL("regional"),
25+
LOCAL("local");
26+
27+
/**
28+
* You need to call EncodingManager.getKey(prefix, EV_SUFFIX) as this EncodedValue can be used for e.g. bike and hike
29+
*/
30+
public static final String EV_SUFFIX = "network";
31+
32+
private final String name;
33+
34+
RouteNetwork(String name) {
35+
this.name = name;
36+
}
37+
38+
@Override
39+
public String toString() {
40+
return name;
41+
}
42+
43+
public static RouteNetwork find(String name) {
44+
if (name == null)
45+
return OTHER;
46+
try {
47+
return RouteNetwork.valueOf(Helper.toUpperCase(name));
48+
} catch (IllegalArgumentException ex) {
49+
return OTHER;
50+
}
51+
}
52+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.graphhopper.routing.profiles;
2+
3+
import com.graphhopper.storage.IntsRef;
4+
import com.graphhopper.util.Helper;
5+
6+
import static com.graphhopper.routing.util.EncodingManager.getKey;
7+
8+
public class TurnCost {
9+
/**
10+
* You need to call EncodingManager.getKey(prefix, EV_SUFFIX) as this EncodedValue can be used for e.g. car and bike
11+
*/
12+
public final static String EV_SUFFIX = "turn_cost";
13+
14+
/**
15+
* This creates an EncodedValue specifically for the turn costs
16+
*/
17+
public static DecimalEncodedValue create(String name, int maxTurnCosts) {
18+
int turnBits = Helper.countBitValue(maxTurnCosts);
19+
return new UnsignedDecimalEncodedValue(getKey(name, EV_SUFFIX), turnBits, 1, 0, false, true);
20+
}
21+
22+
public static IntsRef createFlags() {
23+
return new IntsRef(1);
24+
}
25+
}

core/src/main/java/com/graphhopper/routing/profiles/UnsignedDecimalEncodedValue.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
* of bits.
2525
*/
2626
public final class UnsignedDecimalEncodedValue extends UnsignedIntEncodedValue implements DecimalEncodedValue {
27-
private final double factor;
27+
protected final double factor;
2828
private final double defaultValue;
29+
private final boolean useMaximumAsInfinity;
2930

3031
public UnsignedDecimalEncodedValue(String name, int bits, double factor, boolean storeTwoDirections) {
3132
this(name, bits, factor, 0, storeTwoDirections);
@@ -39,9 +40,16 @@ public UnsignedDecimalEncodedValue(String name, int bits, double factor, boolean
3940
* @param storeTwoDirections true if forward and backward direction of the edge should get two independent values.
4041
*/
4142
public UnsignedDecimalEncodedValue(String name, int bits, double factor, double defaultValue, boolean storeTwoDirections) {
43+
this(name, bits, factor, defaultValue, storeTwoDirections, false);
44+
}
45+
46+
public UnsignedDecimalEncodedValue(String name, int bits, double factor, double defaultValue, boolean storeTwoDirections, boolean useMaximumAsInfinity) {
4247
super(name, bits, storeTwoDirections);
4348
this.factor = factor;
4449
this.defaultValue = defaultValue;
50+
this.useMaximumAsInfinity = useMaximumAsInfinity;
51+
if (useMaximumAsInfinity && Double.isInfinite(defaultValue))
52+
throw new IllegalArgumentException("Default value and maximum value cannot be both infinity");
4553
}
4654

4755
private int toInt(double val) {
@@ -52,6 +60,10 @@ private int toInt(double val) {
5260
public final void setDecimal(boolean reverse, IntsRef ints, double value) {
5361
if (!isInitialized())
5462
throw new IllegalStateException("Call init before usage for EncodedValue " + toString());
63+
if (useMaximumAsInfinity && Double.isInfinite(value)) {
64+
super.setInt(reverse, ints, maxValue);
65+
return;
66+
}
5567
if (value == defaultValue)
5668
value = 0;
5769
if (value > maxValue * factor)
@@ -67,6 +79,8 @@ public final void setDecimal(boolean reverse, IntsRef ints, double value) {
6779
@Override
6880
public final double getDecimal(boolean reverse, IntsRef ref) {
6981
int value = getInt(reverse, ref);
82+
if (useMaximumAsInfinity && value == maxValue)
83+
return Double.POSITIVE_INFINITY;
7084
if (value == 0)
7185
return defaultValue;
7286
return value * factor;

core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnExt.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.carrotsearch.hppc.IntArrayList;
2222
import com.graphhopper.storage.Graph;
23+
import com.graphhopper.storage.IntsRef;
2324
import com.graphhopper.storage.TurnCostStorage;
2425

2526
/**
@@ -40,19 +41,19 @@ class QueryGraphTurnExt extends TurnCostStorage {
4041
}
4142

4243
@Override
43-
public long getTurnCostFlags(int edgeFrom, int nodeVia, int edgeTo) {
44-
if (isVirtualNode(nodeVia)) {
45-
return 0;
46-
} else if (isVirtualEdge(edgeFrom) || isVirtualEdge(edgeTo)) {
47-
if (isVirtualEdge(edgeFrom)) {
48-
edgeFrom = getOriginalEdge(edgeFrom);
44+
public IntsRef readFlags(IntsRef tcFlags, int fromEdge, int viaNode, int toEdge) {
45+
if (isVirtualNode(viaNode)) {
46+
return tcFlags;
47+
} else if (isVirtualEdge(fromEdge) || isVirtualEdge(toEdge)) {
48+
if (isVirtualEdge(fromEdge)) {
49+
fromEdge = getOriginalEdge(fromEdge);
4950
}
50-
if (isVirtualEdge(edgeTo)) {
51-
edgeTo = getOriginalEdge(edgeTo);
51+
if (isVirtualEdge(toEdge)) {
52+
toEdge = getOriginalEdge(toEdge);
5253
}
53-
return mainTurnCostStorage.getTurnCostFlags(edgeFrom, nodeVia, edgeTo);
54+
return mainTurnCostStorage.readFlags(tcFlags, fromEdge, viaNode, toEdge);
5455
} else {
55-
return mainTurnCostStorage.getTurnCostFlags(edgeFrom, nodeVia, edgeTo);
56+
return mainTurnCostStorage.readFlags(tcFlags, fromEdge, viaNode, toEdge);
5657
}
5758
}
5859

core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java

Lines changed: 9 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
*/
1818
package com.graphhopper.routing.util;
1919

20-
import com.graphhopper.reader.*;
20+
import com.graphhopper.reader.ConditionalTagInspector;
21+
import com.graphhopper.reader.OSMTurnRelation;
22+
import com.graphhopper.reader.ReaderNode;
23+
import com.graphhopper.reader.ReaderWay;
2124
import com.graphhopper.reader.osm.conditional.ConditionalOSMTagInspector;
2225
import com.graphhopper.reader.osm.conditional.DateRangeParser;
2326
import com.graphhopper.routing.profiles.*;
@@ -66,8 +69,6 @@ public abstract class AbstractFlagEncoder implements FlagEncoder {
6669
/* Edge Flag Encoder fields */
6770
private long nodeBitMask;
6871
private long relBitMask;
69-
private EncodedValueOld turnCostEncoder;
70-
private long turnRestrictionBit;
7172
private boolean blockByDefault = true;
7273
private boolean blockFords = true;
7374
private boolean registered;
@@ -169,24 +170,15 @@ public void createEncodedValues(List<EncodedValue> registerNewEncodedValue, Stri
169170
}
170171

171172
/**
172-
* Defines the bits which are used for relation flags.
173-
*
174-
* @return incremented shift value pointing behind the last used bit
173+
* Analyze properties of a way and create the edge flags. This method is called in the second
174+
* parsing step.
175175
*/
176-
public int defineRelationBits(int index, int shift) {
177-
return shift;
178-
}
176+
public abstract IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.Access access);
179177

180-
public boolean acceptsTurnRelation(OSMTurnRelation relation) {
181-
return true;
178+
public int getMaxTurnCosts() {
179+
return maxTurnCosts;
182180
}
183181

184-
/**
185-
* Analyze the properties of a relation and create the routing flags for the second read step.
186-
* In the pre-parsing step this method will be called to determine the useful relation tags.
187-
*/
188-
public abstract long handleRelationTags(long oldRelation, ReaderRelation relation);
189-
190182
/**
191183
* Decide whether a way is routable for a given mode of travel. This skips some ways before
192184
* handleWayTags is called.
@@ -195,16 +187,6 @@ public boolean acceptsTurnRelation(OSMTurnRelation relation) {
195187
*/
196188
public abstract EncodingManager.Access getAccess(ReaderWay way);
197189

198-
/**
199-
* Analyze properties of a way and create the edge flags. This method is called in the second
200-
* parsing step.
201-
*/
202-
public abstract IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.Access access, long relationFlags);
203-
204-
public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.Access access) {
205-
return handleWayTags(edgeFlags, way, access, 0);
206-
}
207-
208190
/**
209191
* Parse tags on nodes. Node tags can add to speed (like traffic_signals) where the value is
210192
* strict negative or blocks access (like a barrier), then the value is strictly positive. This
@@ -422,15 +404,6 @@ protected double getFerrySpeed(ReaderWay way) {
422404
}
423405
}
424406

425-
void setRelBitMask(int usedBits, int shift) {
426-
relBitMask = (1L << usedBits) - 1;
427-
relBitMask <<= shift;
428-
}
429-
430-
long getRelBitMask() {
431-
return relBitMask;
432-
}
433-
434407
void setNodeBitMask(int usedBits, int shift) {
435408
nodeBitMask = (1L << usedBits) - 1;
436409
nodeBitMask <<= shift;
@@ -440,89 +413,6 @@ long getNodeBitMask() {
440413
return nodeBitMask;
441414
}
442415

443-
/**
444-
* Defines the bits reserved for storing turn restriction and turn cost
445-
* <p>
446-
*
447-
* @param shift bit offset for the first bit used by this encoder
448-
* @return incremented shift value pointing behind the last used bit
449-
*/
450-
public int defineTurnBits(int index, int shift) {
451-
if (maxTurnCosts == 0)
452-
return shift;
453-
454-
// optimization for turn restrictions only
455-
else if (maxTurnCosts == 1) {
456-
turnRestrictionBit = 1L << shift;
457-
return shift + 1;
458-
}
459-
460-
int turnBits = Helper.countBitValue(maxTurnCosts);
461-
turnCostEncoder = new EncodedValueOld("TurnCost", shift, turnBits, 1, 0, maxTurnCosts) {
462-
// override to avoid expensive Math.round
463-
@Override
464-
public final long getValue(long flags) {
465-
// find value
466-
flags &= mask;
467-
flags >>>= shift;
468-
return flags;
469-
}
470-
};
471-
return shift + turnBits;
472-
}
473-
474-
@Override
475-
public boolean isTurnRestricted(long flags) {
476-
if (maxTurnCosts == 0)
477-
return false;
478-
479-
else if (maxTurnCosts == 1)
480-
return (flags & turnRestrictionBit) != 0;
481-
482-
return turnCostEncoder.getValue(flags) == maxTurnCosts;
483-
}
484-
485-
@Override
486-
public double getTurnCost(long flags) {
487-
if (maxTurnCosts == 0)
488-
return 0;
489-
490-
else if (maxTurnCosts == 1)
491-
return ((flags & turnRestrictionBit) == 0) ? 0 : Double.POSITIVE_INFINITY;
492-
493-
long cost = turnCostEncoder.getValue(flags);
494-
if (cost == maxTurnCosts)
495-
return Double.POSITIVE_INFINITY;
496-
497-
return cost;
498-
}
499-
500-
@Override
501-
public long getTurnFlags(boolean restricted, double costs) {
502-
if (maxTurnCosts == 0)
503-
return 0;
504-
505-
else if (maxTurnCosts == 1) {
506-
if (costs != 0)
507-
throw new IllegalArgumentException("Only restrictions are supported");
508-
509-
return restricted ? turnRestrictionBit : 0;
510-
}
511-
512-
if (restricted) {
513-
if (costs != 0 || Double.isInfinite(costs))
514-
throw new IllegalArgumentException("Restricted turn can only have infinite costs (or use 0)");
515-
} else if (costs >= maxTurnCosts)
516-
throw new IllegalArgumentException("Cost is too high. Or specify restricted == true");
517-
518-
if (costs < 0)
519-
throw new IllegalArgumentException("Turn costs cannot be negative");
520-
521-
if (costs >= maxTurnCosts || restricted)
522-
costs = maxTurnCosts;
523-
return turnCostEncoder.setValue(0L, (int) costs);
524-
}
525-
526416
public final DecimalEncodedValue getAverageSpeedEnc() {
527417
if (avgSpeedEnc == null)
528418
throw new NullPointerException("FlagEncoder " + toString() + " not yet initialized");

0 commit comments

Comments
 (0)