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 @Override
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 @Override
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 }