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