Skip to content

Commit

Permalink
Add support for EU tunnel codes (#1786)
Browse files Browse the repository at this point in the history
* Define EU tunnel codes

* Add a parser for EU tunnel codes

* Add a junit test for the tunnel code parser
  • Loading branch information
otbutz authored and karussell committed Nov 18, 2019
1 parent c42279e commit 6342596
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 2 deletions.
2 changes: 1 addition & 1 deletion config-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ graphhopper:

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

##### Elevation #####
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public EncodedValue create(String string) {
enc = new EnumEncodedValue<>(TrackType.KEY, TrackType.class);
} else if (Hazmat.KEY.equals(name)) {
enc = new EnumEncodedValue<>(Hazmat.KEY, Hazmat.class);
} else if (HazmatTunnel.KEY.equals(name)) {
enc = new EnumEncodedValue<>(HazmatTunnel.KEY, HazmatTunnel.class);
} else if (HazmatWater.KEY.equals(name)) {
enc = new EnumEncodedValue<>(HazmatWater.KEY, HazmatWater.class);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.graphhopper.routing.profiles;

/**
* Defines the degree of restriction for the transport of hazardous goods through tunnels.<br>
* If not tagged it will be {@link #A}
*
* @see https://wiki.openstreetmap.org/wiki/Key:hazmat#Tunnel_restrictions
*/
public enum HazmatTunnel {
/** driving with any dangerous goods allowed */
A("A"),
/** no goods with very large explosion range */
B("B"),
/** no goods with large explosion or poisoning range */
C("C"),
/** no goods which threaten a large explosion, poisoning or fire */
D("D"),
/** forbids all dangerous goods except: UN 2919,3291, 3331, 3359, 3373 */
E("E");

public static final String KEY = "hazmat_tunnel";

private final String name;

HazmatTunnel(String name) {
this.name = name;
}

@Override
public String toString() {
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ else if (name.equals(TrackType.KEY))
return new OSMTrackTypeParser();
else if (name.equals(Hazmat.KEY))
return new OSMHazmatParser();
else if (name.equals(HazmatTunnel.KEY))
return new OSMHazmatTunnelParser();
else if (name.equals(HazmatWater.KEY))
return new OSMHazmatWaterParser();
throw new IllegalArgumentException("entry in encoder list not supported " + name);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.graphhopper.routing.util.parsers;

import java.util.List;

import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.profiles.EncodedValue;
import com.graphhopper.routing.profiles.EncodedValueLookup;
import com.graphhopper.routing.profiles.EnumEncodedValue;
import com.graphhopper.routing.profiles.HazmatTunnel;
import com.graphhopper.routing.util.EncodingManager.Access;
import com.graphhopper.storage.IntsRef;

public class OSMHazmatTunnelParser implements TagParser {

private static final String[] TUNNEL_CATEGORY_NAMES;
static {
HazmatTunnel[] categories = HazmatTunnel.values();
TUNNEL_CATEGORY_NAMES = new String[categories.length];
for (int i = 0; i < categories.length; i++) {
TUNNEL_CATEGORY_NAMES[i] = categories[i].name();
}
}

private final EnumEncodedValue<HazmatTunnel> hazTunnelEnc;

public OSMHazmatTunnelParser() {
this.hazTunnelEnc = new EnumEncodedValue<>(HazmatTunnel.KEY, HazmatTunnel.class);
}

@Override
public void createEncodedValues(EncodedValueLookup lookup,
List<EncodedValue> registerNewEncodedValue) {
registerNewEncodedValue.add(hazTunnelEnc);
}

@Override
public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, Access access,
long relationFlags) {

if (readerWay.hasTag("hazmat:adr_tunnel_cat", TUNNEL_CATEGORY_NAMES)) {
HazmatTunnel code = HazmatTunnel.valueOf(readerWay.getTag("hazmat:adr_tunnel_cat"));
hazTunnelEnc.setEnum(false, edgeFlags, code);
} else if (readerWay.hasTag("hazmat:tunnel_cat", TUNNEL_CATEGORY_NAMES)) {
HazmatTunnel code = HazmatTunnel.valueOf(readerWay.getTag("hazmat:tunnel_cat"));
hazTunnelEnc.setEnum(false, edgeFlags, code);
} else if (readerWay.hasTag("tunnel", "yes")) {
HazmatTunnel[] codes = HazmatTunnel.values();
for (int i = codes.length - 1; i >= 0; i--) {
if (readerWay.hasTag("hazmat:" + codes[i].name(), "no")) {
hazTunnelEnc.setEnum(false, edgeFlags, codes[i]);
break;
}
}
}

return edgeFlags;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public List<PathDetailsBuilder> createPathDetailsBuilders(List<String> requested
new MapEntry<>(RoadEnvironment.KEY, RoadEnvironment.class), new MapEntry<>(Surface.KEY, Surface.class),
new MapEntry<>(RoadAccess.KEY, RoadAccess.class), new MapEntry<>(Toll.KEY, Toll.class),
new MapEntry<>(TrackType.KEY, TrackType.class), new MapEntry<>(Hazmat.KEY, Hazmat.class),
new MapEntry<>(HazmatWater.KEY, HazmatWater.class),
new MapEntry<>(HazmatTunnel.KEY, HazmatTunnel.class), new MapEntry<>(HazmatWater.KEY, HazmatWater.class),
new MapEntry<>(Country.KEY, Country.class))) {
String key = (String) entry.getKey();
if (requestedPathDetails.contains(key) && encoder.hasEncodedValue(key))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package com.graphhopper.routing.util.parsers;

import static com.graphhopper.routing.util.EncodingManager.Access.WAY;
import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.profiles.EnumEncodedValue;
import com.graphhopper.routing.profiles.HazmatTunnel;
import com.graphhopper.routing.util.EncodingManager;
import com.graphhopper.storage.IntsRef;

public class OSMHazmatTunnelParserTest {

private EncodingManager em;
private EnumEncodedValue<HazmatTunnel> hazTunnelEnc;
private OSMHazmatTunnelParser parser;

@Before
public void setUp() {
parser = new OSMHazmatTunnelParser();
em = new EncodingManager.Builder().add(parser).build();
hazTunnelEnc = em.getEnumEncodedValue(HazmatTunnel.KEY, HazmatTunnel.class);
}

@Test
public void testADRTunnelCat() {
IntsRef intsRef = em.createEdgeFlags();
ReaderWay readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:adr_tunnel_cat", "A");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:adr_tunnel_cat", "B");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.B, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:adr_tunnel_cat", "C");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:adr_tunnel_cat", "D");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.D, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:adr_tunnel_cat", "E");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
}

@Test
public void testTunnelCat() {
IntsRef intsRef = em.createEdgeFlags();
ReaderWay readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:tunnel_cat", "A");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:tunnel_cat", "B");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.B, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:tunnel_cat", "C");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:tunnel_cat", "D");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.D, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:tunnel_cat", "E");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
}

@Test
public void testHazmatSubtags() {
IntsRef intsRef = em.createEdgeFlags();
ReaderWay readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:A", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:B", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.B, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:C", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:D", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.D, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:E", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
}

@Test
public void testOrder() {
IntsRef intsRef = em.createEdgeFlags();
ReaderWay readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:A", "no");
readerWay.setTag("hazmat:B", "no");
readerWay.setTag("hazmat:C", "no");
readerWay.setTag("hazmat:D", "no");
readerWay.setTag("hazmat:E", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:A", "no");
readerWay.setTag("hazmat:B", "no");
readerWay.setTag("hazmat:C", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.C, hazTunnelEnc.getEnum(false, intsRef));

intsRef = em.createEdgeFlags();
readerWay = new ReaderWay(1);
readerWay.setTag("tunnel", "yes");
readerWay.setTag("hazmat:B", "no");
readerWay.setTag("hazmat:E", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.E, hazTunnelEnc.getEnum(false, intsRef));
}

@Test
public void testIgnoreNonTunnelSubtags() {
IntsRef intsRef = em.createEdgeFlags();
ReaderWay readerWay = new ReaderWay(1);
readerWay.setTag("hazmat:B", "no");
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
}

@Test
public void testNoNPE() {
ReaderWay readerWay = new ReaderWay(1);
IntsRef intsRef = em.createEdgeFlags();
parser.handleWayTags(intsRef, readerWay, WAY, 0);
assertEquals(HazmatTunnel.A, hazTunnelEnc.getEnum(false, intsRef));
}
}

0 comments on commit 6342596

Please sign in to comment.