1 package org.opentrafficsim.road.network.factory.osm;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.Objects;
7
8 import org.opentrafficsim.road.network.factory.osm.events.WarningEvent;
9 import org.opentrafficsim.road.network.factory.osm.events.WarningListener;
10
11
12
13
14
15
16
17
18
19
20
21 public class OSMLink implements Serializable
22 {
23
24 private static final long serialVersionUID = 20141231L;
25
26
27 private final String id;
28
29
30 private final OSMNode start;
31
32
33 private final OSMNode end;
34
35
36 private List<OSMNode> intermediateNodes;
37
38
39 private final double length;
40
41
42 private List<OSMTag> tags;
43
44
45 private byte lanes;
46
47
48 private byte forwardLanes;
49
50
51 private boolean oneway;
52
53
54
55
56
57
58
59
60
61 public OSMLink(final OSMNode fromNode, final OSMNode toNode, final List<OSMTag> tags, final double length,
62 final WarningListener warningListener)
63 {
64 if (fromNode == toNode)
65 {
66 throw new Error("Start and end of link are the same Node: " + fromNode);
67 }
68 String name = "";
69 for (OSMTag tag : tags)
70 {
71 if (tag.getKey().equals("name"))
72 {
73 name = ": " + tag.getValue();
74 }
75 }
76 this.id = Objects.toString(fromNode.getId()) + Objects.toString(toNode.getId()) + name;
77 this.start = fromNode;
78 this.end = toNode;
79 this.length = length;
80 this.lanes = 1;
81 this.forwardLanes = 1;
82 boolean forwardDefined = false;
83
84 List<OSMTag> linkTags = new ArrayList<OSMTag>(tags);
85 for (OSMTag tag : tags)
86 {
87 if (tag.getKey().equals("oneway") && tag.getValue().equals("yes"))
88 {
89 this.setOneway(true);
90 linkTags.remove(tag);
91 this.forwardLanes = this.lanes;
92 }
93 if (tag.getKey().equals("highway") && tag.getValue().equals("motorway_link"))
94 {
95 this.setOneway(true);
96 this.lanes = 1;
97 this.forwardLanes = this.lanes;
98 }
99 if (tag.getKey().equals("highway") && tag.getValue().equals("motorway"))
100 {
101 this.setOneway(true);
102 this.forwardLanes = this.lanes;
103 }
104 if (tag.getKey().equals("highway") && (tag.getValue().equals("cycleway") || tag.getValue().equals("footway")
105 || tag.getValue().equals("pedestrian") || tag.getValue().equals("steps")))
106 {
107 this.lanes = 1;
108 }
109 }
110
111 for (OSMTag tag2 : new ArrayList<OSMTag>(linkTags))
112 {
113 if (tag2.getKey().equals("lanes"))
114 {
115 if (isByte(tag2.getValue()))
116 {
117 this.lanes = Byte.parseByte(tag2.getValue());
118 linkTags.remove(tag2);
119 if (this.oneway)
120 {
121 this.forwardLanes = this.lanes;
122 forwardDefined = true;
123 }
124 }
125 else
126 {
127 String warning = "Illegal value for the tag 'lanes' at link " + this.id;
128 warningListener.warning(new WarningEvent(this, warning));
129 }
130 }
131 if (tag2.getKey().equals("lanes:forward"))
132 {
133 if (isByte(tag2.getValue()))
134 {
135 this.forwardLanes = Byte.parseByte(tag2.getValue());
136 linkTags.remove(tag2);
137 forwardDefined = true;
138 }
139 else
140 {
141 String warning = "Illegal value for the tag 'lanes:forward' at link " + this.id;
142 warningListener.warning(new WarningEvent(this, warning));
143 }
144 }
145 }
146 this.tags = linkTags;
147 if (!forwardDefined && this.lanes > 1)
148 {
149 this.forwardLanes = (byte) (this.lanes / 2);
150 String warning = "No forward lanes defined at link " + this.id;
151 warningListener.warning(new WarningEvent(this, warning));
152 }
153 this.intermediateNodes = new ArrayList<OSMNode>();
154 }
155
156
157
158
159
160
161
162
163
164
165 public OSMLink(final OSMNode startNode, final OSMNode endNode, final List<OSMTag> tags, final double length,
166 final byte lanes, final byte flanes)
167 {
168 if (startNode == endNode)
169 {
170 throw new Error("start and end of link are the same Node: " + startNode);
171 }
172 this.id = Objects.toString(startNode.getId()) + Objects.toString(endNode.getId());
173 this.start = startNode;
174 this.end = endNode;
175 this.tags = tags;
176 this.length = length;
177 this.lanes = lanes;
178 this.forwardLanes = flanes;
179 this.intermediateNodes = new ArrayList<OSMNode>();
180 }
181
182
183
184
185 public final String getId()
186 {
187 return this.id;
188 }
189
190
191
192
193 public final OSMNode getStart()
194 {
195 return this.start;
196 }
197
198
199
200
201 public final OSMNode getEnd()
202 {
203 return this.end;
204 }
205
206
207
208
209
210
211 public final List<OSMTag> getTags()
212 {
213 return new ArrayList<OSMTag>(this.tags);
214 }
215
216
217
218
219
220 public final boolean isOneway()
221 {
222 return this.oneway;
223 }
224
225
226
227
228
229 public final void setOneway(final boolean isOneWay)
230 {
231 this.oneway = isOneWay;
232 }
233
234
235
236
237
238 public final byte getLanes()
239 {
240 return this.lanes;
241 }
242
243
244
245
246
247
248 public final byte getForwardLanes()
249 {
250 return this.forwardLanes;
251 }
252
253
254
255
256
257 public final void addTag(final OSMTag tag)
258 {
259 this.tags.add(tag);
260 }
261
262
263
264
265
266 public final double getLength()
267 {
268 return this.length;
269 }
270
271
272
273
274
275 public final List<OSMNode> getSplineList()
276 {
277 return this.intermediateNodes;
278 }
279
280
281
282
283
284 public final void addSpline(final OSMNode shapeNode)
285 {
286 this.intermediateNodes.add(shapeNode);
287 }
288
289
290
291
292
293
294 public final boolean hasTag(final String key)
295 {
296 for (OSMTag t : this.tags)
297 {
298 if (t.getKey().equals(key))
299 {
300 return true;
301 }
302 }
303 return false;
304 }
305
306
307
308
309
310
311 private boolean isByte(final String s)
312 {
313 try
314 {
315 Byte.parseByte(s);
316 }
317 catch (NumberFormatException e)
318 {
319 return false;
320 }
321 return true;
322 }
323
324
325 public final String toString()
326 {
327 return String.format("Link %s from %d to %d", getId(), getStart().getId(), getEnd().getId());
328 }
329
330
331
332
333
334
335 public final boolean containsAllTags(final List<OSMTag> tagsToCheck)
336 {
337 return this.tags.containsAll(tagsToCheck);
338 }
339
340 }