Way.java (4005B) download
1package osm.message;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5import java.util.List;
6import java.util.Map;
7import java.util.Set;
8
9import protobuf.ProtobufReader;
10
11// required int64 id = 1;
12// repeated uint32 keys = 2 [packed = true];
13// repeated uint32 vals = 3 [packed = true];
14// optional Info info = 4;
15// repeated sint64 refs = 8 [packed = true]; // DELTA coded
16public class Way extends AbstractEntity<Way> {
17 public enum Direction {
18 FORWARDS(1), BACKWARDS(-1);
19
20 public final int increment;
21
22 private Direction(int increment) {
23 this.increment = increment;
24 }
25
26 public int getStartPoint(int size) {
27 return switch (increment) {
28 case 1 -> 0;
29 case -1 -> size - 1;
30 default -> throw new RuntimeException("increment must be -1 or 1");
31 };
32 }
33 }
34
35 public static final Set<String> WAY_NO_ALLOWED = Set.of(
36 "pedestrian",
37 "path",
38 "bridleway",
39 "cycleway",
40 "footway",
41 "steps");
42
43 public static final Map<String, String> WAY_DEFAULT_SPEED = Map.of(
44 "motorway", "120",
45 "trunk", "100",
46 "primary", "80",
47 "secondary", "80",
48 "tertiary", "60",
49 "unclassified", "60",
50 "residential", "50");
51
52 public static final String WAY_UNLIMITED_SPEED = "100";
53
54 public final List<Long> children = new ArrayList<>();
55 public double speedForwards = 0;
56 public double speedBackwards = 0;
57
58 public Way(PrimitiveBlock block) {
59 super(block);
60 }
61
62 protected boolean isAllowed(Direction direction) {
63 if (!tags.containsKey("highway"))
64 return false;
65
66 boolean allowed = !WAY_NO_ALLOWED.contains(tags.get("highway"))
67 || tags.getBoolean("access", v -> false)
68 || tags.getBoolean("motor_vehicle", v -> false)
69 || tags.getBoolean("taxi", v -> false)
70 || tags.getBoolean("psv", v -> false);
71
72 if (direction == Direction.BACKWARDS) {
73 if (tags.getBoolean("oneway"))
74 allowed = false;
75
76 allowed = allowed
77 || tags.getBoolean("access:backwards", v -> false)
78 || tags.getBoolean("motor_vehicle:backwards", v -> false)
79 || tags.getBoolean("psv:backwards", v -> false)
80 || tags.getBoolean("taxi:backwards", v -> false);
81 }
82
83 return allowed;
84 }
85
86 protected double getSpeed(Direction direction) {
87 String speed = "60";
88 String defaultSpeed;
89
90 defaultSpeed = speed = WAY_DEFAULT_SPEED.getOrDefault(tags.get("highway"), speed);
91 speed = tags.getOrDefault("maxspeed", speed);
92
93 if (direction == Direction.BACKWARDS)
94 speed = tags.getOrDefault("maxspeed:backwards", speed);
95
96 if (speed.equals("none"))
97 speed = WAY_UNLIMITED_SPEED;
98
99 try {
100 return Double.parseDouble(speed) / 3.6;
101 } catch (NumberFormatException exc) {
102 return Double.parseDouble(defaultSpeed) / 3.6;
103 }
104 }
105
106 @Override
107 public Way parseRemaining(Iterator<ProtobufReader> tags) {
108 while (tags.hasNext()) {
109 ProtobufReader message = tags.next();
110 switch (message.tag()) {
111 case 4 -> message.skip();
112 case 8 -> message.packed(message::svarint64, 0l, Long::sum)
113 .forEachRemaining(children::add);
114 default -> message.throwUnexpected();
115 }
116 }
117
118 if (isAllowed(Direction.FORWARDS))
119 speedForwards = getSpeed(Direction.FORWARDS);
120
121 if (isAllowed(Direction.BACKWARDS))
122 speedBackwards = getSpeed(Direction.BACKWARDS);
123
124 return this;
125 }
126
127 @Override
128 public String toString() {
129 return String.format("Way#%d[%dnodes]", id, children.size());
130 }
131}