Skip to content

Commit 6342596

Browse files
otbutzkarussell
authored andcommitted
Add support for EU tunnel codes (graphhopper#1786)
* Define EU tunnel codes * Add a parser for EU tunnel codes * Add a junit test for the tunnel code parser
1 parent c42279e commit 6342596

File tree

7 files changed

+276
-2
lines changed

7 files changed

+276
-2
lines changed

config-example.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ graphhopper:
1515

1616
# Add additional information to every edge. Used for path details.
1717
# If road_environment is added and elevation is enabled then also a tunnel and bridge interpolation is done, see #798.
18-
# More options are: surface,max_width,max_height,max_weight,max_axle_load,max_length,hazmat,hazmat_water,toll,track_type
18+
# More options are: surface,max_width,max_height,max_weight,max_axle_load,max_length,hazmat,hazmat_tunnel,hazmat_water,toll,track_type
1919
graph.encoded_values: road_class,road_class_link,road_environment,max_speed,road_access
2020

2121
##### Elevation #####

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public EncodedValue create(String string) {
6161
enc = new EnumEncodedValue<>(TrackType.KEY, TrackType.class);
6262
} else if (Hazmat.KEY.equals(name)) {
6363
enc = new EnumEncodedValue<>(Hazmat.KEY, Hazmat.class);
64+
} else if (HazmatTunnel.KEY.equals(name)) {
65+
enc = new EnumEncodedValue<>(HazmatTunnel.KEY, HazmatTunnel.class);
6466
} else if (HazmatWater.KEY.equals(name)) {
6567
enc = new EnumEncodedValue<>(HazmatWater.KEY, HazmatWater.class);
6668
} else {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.graphhopper.routing.profiles;
2+
3+
/**
4+
* Defines the degree of restriction for the transport of hazardous goods through tunnels.<br>
5+
* If not tagged it will be {@link #A}
6+
*
7+
* @see https://wiki.openstreetmap.org/wiki/Key:hazmat#Tunnel_restrictions
8+
*/
9+
public enum HazmatTunnel {
10+
/** driving with any dangerous goods allowed */
11+
A("A"),
12+
/** no goods with very large explosion range */
13+
B("B"),
14+
/** no goods with large explosion or poisoning range */
15+
C("C"),
16+
/** no goods which threaten a large explosion, poisoning or fire */
17+
D("D"),
18+
/** forbids all dangerous goods except: UN 2919,3291, 3331, 3359, 3373 */
19+
E("E");
20+
21+
public static final String KEY = "hazmat_tunnel";
22+
23+
private final String name;
24+
25+
HazmatTunnel(String name) {
26+
this.name = name;
27+
}
28+
29+
@Override
30+
public String toString() {
31+
return name;
32+
}
33+
}

core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ else if (name.equals(TrackType.KEY))
6060
return new OSMTrackTypeParser();
6161
else if (name.equals(Hazmat.KEY))
6262
return new OSMHazmatParser();
63+
else if (name.equals(HazmatTunnel.KEY))
64+
return new OSMHazmatTunnelParser();
6365
else if (name.equals(HazmatWater.KEY))
6466
return new OSMHazmatWaterParser();
6567
throw new IllegalArgumentException("entry in encoder list not supported " + name);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.graphhopper.routing.util.parsers;
2+
3+
import java.util.List;
4+
5+
import com.graphhopper.reader.ReaderWay;
6+
import com.graphhopper.routing.profiles.EncodedValue;
7+
import com.graphhopper.routing.profiles.EncodedValueLookup;
8+
import com.graphhopper.routing.profiles.EnumEncodedValue;
9+
import com.graphhopper.routing.profiles.HazmatTunnel;
10+
import com.graphhopper.routing.util.EncodingManager.Access;
11+
import com.graphhopper.storage.IntsRef;
12+
13+
public class OSMHazmatTunnelParser implements TagParser {
14+
15+
private static final String[] TUNNEL_CATEGORY_NAMES;
16+
static {
17+
HazmatTunnel[] categories = HazmatTunnel.values();
18+
TUNNEL_CATEGORY_NAMES = new String[categories.length];
19+
for (int i = 0; i < categories.length; i++) {
20+
TUNNEL_CATEGORY_NAMES[i] = categories[i].name();
21+
}
22+
}
23+
24+
private final EnumEncodedValue<HazmatTunnel> hazTunnelEnc;
25+
26+
public OSMHazmatTunnelParser() {
27+
this.hazTunnelEnc = new EnumEncodedValue<>(HazmatTunnel.KEY, HazmatTunnel.class);
28+
}
29+
30+
@Override
31+
public void createEncodedValues(EncodedValueLookup lookup,
32+
List<EncodedValue> registerNewEncodedValue) {
33+
registerNewEncodedValue.add(hazTunnelEnc);
34+
}
35+
36+
@Override
37+
public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, Access access,
38+
long relationFlags) {
39+
40+
if (readerWay.hasTag("hazmat:adr_tunnel_cat", TUNNEL_CATEGORY_NAMES)) {
41+
HazmatTunnel code = HazmatTunnel.valueOf(readerWay.getTag("hazmat:adr_tunnel_cat"));
42+
hazTunnelEnc.setEnum(false, edgeFlags, code);
43+
} else if (readerWay.hasTag("hazmat:tunnel_cat", TUNNEL_CATEGORY_NAMES)) {
44+
HazmatTunnel code = HazmatTunnel.valueOf(readerWay.getTag("hazmat:tunnel_cat"));
45+
hazTunnelEnc.setEnum(false, edgeFlags, code);
46+
} else if (readerWay.hasTag("tunnel", "yes")) {
47+
HazmatTunnel[] codes = HazmatTunnel.values();
48+
for (int i = codes.length - 1; i >= 0; i--) {
49+
if (readerWay.hasTag("hazmat:" + codes[i].name(), "no")) {
50+
hazTunnelEnc.setEnum(false, edgeFlags, codes[i]);
51+
break;
52+
}
53+
}
54+
}
55+
56+
return edgeFlags;
57+
}
58+
}

core/src/main/java/com/graphhopper/util/details/PathDetailsBuilderFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public List<PathDetailsBuilder> createPathDetailsBuilders(List<String> requested
7373
new MapEntry<>(RoadEnvironment.KEY, RoadEnvironment.class), new MapEntry<>(Surface.KEY, Surface.class),
7474
new MapEntry<>(RoadAccess.KEY, RoadAccess.class), new MapEntry<>(Toll.KEY, Toll.class),
7575
new MapEntry<>(TrackType.KEY, TrackType.class), new MapEntry<>(Hazmat.KEY, Hazmat.class),
76-
new MapEntry<>(HazmatWater.KEY, HazmatWater.class),
76+
new MapEntry<>(HazmatTunnel.KEY, HazmatTunnel.class), new MapEntry<>(HazmatWater.KEY, HazmatWater.class),
7777
new MapEntry<>(Country.KEY, Country.class))) {
7878
String key = (String) entry.getKey();
7979
if (requestedPathDetails.contains(key) && encoder.hasEncodedValue(key))
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package com.graphhopper.routing.util.parsers;
2+
3+
import static com.graphhopper.routing.util.EncodingManager.Access.WAY;
4+
import static org.junit.Assert.assertEquals;
5+
6+
import org.junit.Before;
7+
import org.junit.Test;
8+
9+
import com.graphhopper.reader.ReaderWay;
10+
import com.graphhopper.routing.profiles.EnumEncodedValue;
11+
import com.graphhopper.routing.profiles.HazmatTunnel;
12+
import com.graphhopper.routing.util.EncodingManager;
13+
import com.graphhopper.storage.IntsRef;
14+
15+
public class OSMHazmatTunnelParserTest {
16+
17+
private EncodingManager em;
18+
private EnumEncodedValue<HazmatTunnel> hazTunnelEnc;
19+
private OSMHazmatTunnelParser parser;
20+
21+
@Before
22+
public void setUp() {
23+
parser = new OSMHazmatTunnelParser();
24+
em = new EncodingManager.Builder().add(parser).build();
25+
hazTunnelEnc = em.getEnumEncodedValue(HazmatTunnel.KEY, HazmatTunnel.class);
26+
}
27+
28+
@Test
29+
public void testADRTunnelCat() {
30+
IntsRef intsRef = em.createEdgeFlags();
31+
ReaderWay readerWay = new ReaderWay(1);
32+
readerWay.setTag("hazmat:adr_tunnel_cat", "A");
33+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
34+
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
35+
36+
intsRef = em.createEdgeFlags();
37+
readerWay = new ReaderWay(1);
38+
readerWay.setTag("hazmat:adr_tunnel_cat", "B");
39+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
40+
assertEquals(HazmatTunnel.B, hazTunnelEnc.getEnum(false, intsRef));
41+
42+
intsRef = em.createEdgeFlags();
43+
readerWay = new ReaderWay(1);
44+
readerWay.setTag("hazmat:adr_tunnel_cat", "C");
45+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
46+
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));
47+
48+
intsRef = em.createEdgeFlags();
49+
readerWay = new ReaderWay(1);
50+
readerWay.setTag("hazmat:adr_tunnel_cat", "D");
51+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
52+
assertEquals(HazmatTunnel.D, hazTunnelEnc.getEnum(false, intsRef));
53+
54+
intsRef = em.createEdgeFlags();
55+
readerWay = new ReaderWay(1);
56+
readerWay.setTag("hazmat:adr_tunnel_cat", "E");
57+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
58+
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
59+
}
60+
61+
@Test
62+
public void testTunnelCat() {
63+
IntsRef intsRef = em.createEdgeFlags();
64+
ReaderWay readerWay = new ReaderWay(1);
65+
readerWay.setTag("hazmat:tunnel_cat", "A");
66+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
67+
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
68+
69+
intsRef = em.createEdgeFlags();
70+
readerWay = new ReaderWay(1);
71+
readerWay.setTag("hazmat:tunnel_cat", "B");
72+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
73+
assertEquals(HazmatTunnel.B, hazTunnelEnc.getEnum(false, intsRef));
74+
75+
intsRef = em.createEdgeFlags();
76+
readerWay = new ReaderWay(1);
77+
readerWay.setTag("hazmat:tunnel_cat", "C");
78+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
79+
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));
80+
81+
intsRef = em.createEdgeFlags();
82+
readerWay = new ReaderWay(1);
83+
readerWay.setTag("hazmat:tunnel_cat", "D");
84+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
85+
assertEquals(HazmatTunnel.D, hazTunnelEnc.getEnum(false, intsRef));
86+
87+
intsRef = em.createEdgeFlags();
88+
readerWay = new ReaderWay(1);
89+
readerWay.setTag("hazmat:tunnel_cat", "E");
90+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
91+
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
92+
}
93+
94+
@Test
95+
public void testHazmatSubtags() {
96+
IntsRef intsRef = em.createEdgeFlags();
97+
ReaderWay readerWay = new ReaderWay(1);
98+
readerWay.setTag("tunnel", "yes");
99+
readerWay.setTag("hazmat:A", "no");
100+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
101+
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
102+
103+
intsRef = em.createEdgeFlags();
104+
readerWay = new ReaderWay(1);
105+
readerWay.setTag("tunnel", "yes");
106+
readerWay.setTag("hazmat:B", "no");
107+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
108+
assertEquals(HazmatTunnel.B, hazTunnelEnc.getEnum(false, intsRef));
109+
110+
intsRef = em.createEdgeFlags();
111+
readerWay = new ReaderWay(1);
112+
readerWay.setTag("tunnel", "yes");
113+
readerWay.setTag("hazmat:C", "no");
114+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
115+
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));
116+
117+
intsRef = em.createEdgeFlags();
118+
readerWay = new ReaderWay(1);
119+
readerWay.setTag("tunnel", "yes");
120+
readerWay.setTag("hazmat:D", "no");
121+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
122+
assertEquals(HazmatTunnel.D, hazTunnelEnc.getEnum(false, intsRef));
123+
124+
intsRef = em.createEdgeFlags();
125+
readerWay = new ReaderWay(1);
126+
readerWay.setTag("tunnel", "yes");
127+
readerWay.setTag("hazmat:E", "no");
128+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
129+
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
130+
}
131+
132+
@Test
133+
public void testOrder() {
134+
IntsRef intsRef = em.createEdgeFlags();
135+
ReaderWay readerWay = new ReaderWay(1);
136+
readerWay.setTag("tunnel", "yes");
137+
readerWay.setTag("hazmat:A", "no");
138+
readerWay.setTag("hazmat:B", "no");
139+
readerWay.setTag("hazmat:C", "no");
140+
readerWay.setTag("hazmat:D", "no");
141+
readerWay.setTag("hazmat:E", "no");
142+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
143+
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
144+
145+
intsRef = em.createEdgeFlags();
146+
readerWay = new ReaderWay(1);
147+
readerWay.setTag("tunnel", "yes");
148+
readerWay.setTag("hazmat:A", "no");
149+
readerWay.setTag("hazmat:B", "no");
150+
readerWay.setTag("hazmat:C", "no");
151+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
152+
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));
153+
154+
intsRef = em.createEdgeFlags();
155+
readerWay = new ReaderWay(1);
156+
readerWay.setTag("tunnel", "yes");
157+
readerWay.setTag("hazmat:B", "no");
158+
readerWay.setTag("hazmat:E", "no");
159+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
160+
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
161+
}
162+
163+
@Test
164+
public void testIgnoreNonTunnelSubtags() {
165+
IntsRef intsRef = em.createEdgeFlags();
166+
ReaderWay readerWay = new ReaderWay(1);
167+
readerWay.setTag("hazmat:B", "no");
168+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
169+
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
170+
}
171+
172+
@Test
173+
public void testNoNPE() {
174+
ReaderWay readerWay = new ReaderWay(1);
175+
IntsRef intsRef = em.createEdgeFlags();
176+
parser.handleWayTags(intsRef, readerWay, WAY, 0);
177+
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
178+
}
179+
}

0 commit comments

Comments
 (0)