1 package org.opentrafficsim.importexport.osm.output;
2
3 import java.awt.Color;
4 import java.io.IOException;
5 import java.rmi.RemoteException;
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Objects;
11 import java.util.SortedMap;
12 import java.util.TreeMap;
13
14 import javax.naming.NamingException;
15
16 import org.geotools.referencing.CRS;
17 import org.geotools.referencing.crs.DefaultGeocentricCRS;
18 import org.geotools.referencing.crs.DefaultGeographicCRS;
19 import org.opengis.referencing.FactoryException;
20 import org.opengis.referencing.crs.CoordinateReferenceSystem;
21 import org.opengis.referencing.operation.MathTransform;
22 import org.opengis.referencing.operation.TransformException;
23 import org.opentrafficsim.core.dsol.OTSAnimatorInterface;
24 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
25 import org.opentrafficsim.core.gtu.GTUType;
26 import org.opentrafficsim.core.network.LongitudinalDirectionality;
27 import org.opentrafficsim.core.network.NetworkException;
28 import org.opentrafficsim.core.network.animation.LaneAnimation;
29 import org.opentrafficsim.core.network.geotools.LinearGeometry;
30 import org.opentrafficsim.core.network.geotools.NodeGeotools;
31 import org.opentrafficsim.core.network.lane.CrossSectionLink;
32 import org.opentrafficsim.core.network.lane.Lane;
33 import org.opentrafficsim.core.network.lane.LaneType;
34 import org.opentrafficsim.core.network.lane.SinkLane;
35 import org.opentrafficsim.core.network.lane.SourceLane;
36 import org.opentrafficsim.core.unit.FrequencyUnit;
37 import org.opentrafficsim.core.unit.LengthUnit;
38 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
39 import org.opentrafficsim.importexport.osm.Link;
40
41 import com.vividsolutions.jts.geom.Coordinate;
42 import com.vividsolutions.jts.geom.GeometryFactory;
43 import com.vividsolutions.jts.geom.LineString;
44
45
46
47
48
49
50
51
52
53
54
55 public final class Convert
56 {
57
58 private Convert()
59 {
60
61 }
62
63
64
65
66
67
68
69 public static Coordinate transform(final Coordinate c) throws FactoryException, TransformException
70 {
71 final CoordinateReferenceSystem wgs84 = DefaultGeographicCRS.WGS84;
72 final CoordinateReferenceSystem cartesianCRS = DefaultGeocentricCRS.CARTESIAN;
73 final MathTransform mathTransform;
74 try
75 {
76 mathTransform = CRS.findMathTransform(wgs84, cartesianCRS, false);
77 double[] srcPt = {c.x, c.y};
78 double[] dstPt = new double[mathTransform.getTargetDimensions()];
79
80 mathTransform.transform(srcPt, 0, dstPt, 0, 1);
81 Coordinate c2 = new Coordinate(dstPt[0], dstPt[1]);
82 return c2;
83 }
84 catch (FactoryException e)
85 {
86 throw new FactoryException(e);
87 }
88 catch (TransformException exception)
89 {
90 throw new TransformException(exception.getMessage());
91 }
92 }
93
94
95
96
97
98
99 public static CrossSectionLink<?, ?> convertLink(final org.opentrafficsim.importexport.osm.Link link)
100 {
101 NodeGeotools.STR start = convertNode(link.getStart());
102 NodeGeotools.STR end = convertNode(link.getEnd());
103 CrossSectionLink<?, ?> l2;
104 if (link.getSplineList().isEmpty())
105 {
106 GeometryFactory factory = new GeometryFactory();
107 Coordinate[] coordinates = new Coordinate[2];
108 coordinates[0] = new Coordinate(start.getPoint().x, start.getPoint().y, 0);
109 coordinates[1] = new Coordinate(end.getPoint().x, end.getPoint().y, 0);
110 LineString lineString = factory.createLineString(coordinates);
111 l2 =
112 new CrossSectionLink<String, String>(link.getID(), start, end, new DoubleScalar.Rel<LengthUnit>(
113 lineString.getLength(), LengthUnit.METER));
114 try
115 {
116 new LinearGeometry(l2, lineString, null);
117 }
118 catch (NetworkException exception)
119 {
120 throw new Error("Network exception in LinearGeometry");
121 }
122
123 }
124 else
125 {
126 List<Coordinate> iC = new ArrayList<Coordinate>();
127 for (org.opentrafficsim.importexport.osm.Node spline : link.getSplineList())
128 {
129 Coordinate coord = new Coordinate(spline.getLongitude(), spline.getLatitude());
130 iC.add(coord);
131 }
132 Coordinate[] intermediateCoordinates = new Coordinate[iC.size()];
133 iC.toArray(intermediateCoordinates);
134 int coordinateCount = 2 + (null == intermediateCoordinates ? 0 : intermediateCoordinates.length);
135 Coordinate[] coordinates = new Coordinate[coordinateCount];
136 coordinates[0] = new Coordinate(start.getPoint().x, start.getPoint().y, 0);
137 coordinates[coordinates.length - 1] = new Coordinate(end.getPoint().x, end.getPoint().y, 0);
138 if (null != intermediateCoordinates)
139 {
140 for (int i = 0; i < intermediateCoordinates.length; i++)
141 {
142 coordinates[i + 1] = new Coordinate(intermediateCoordinates[i]);
143 }
144 }
145 GeometryFactory factory = new GeometryFactory();
146 LineString lineString = factory.createLineString(coordinates);
147 l2 =
148 new CrossSectionLink<String, String>(link.getID(), start, end, new DoubleScalar.Rel<LengthUnit>(
149 lineString.getLength(), LengthUnit.METER));
150 try
151 {
152 new LinearGeometry(l2, lineString, null);
153 }
154 catch (NetworkException exception)
155 {
156 throw new Error("Network exception in LinearGeometry");
157 }
158 }
159 return l2;
160 }
161
162
163
164
165
166
167 public static NodeGeotools.STR convertNode(final org.opentrafficsim.importexport.osm.Node node)
168 {
169 Coordinate coordWGS84;
170 Coordinate coordGCC;
171 if (node.contains("ele"))
172 {
173 try
174 {
175 coordWGS84 =
176 new Coordinate(node.getLongitude(), node.getLatitude(), Double.parseDouble(node.getTag("ele")
177 .getValue()));
178 try
179 {
180 coordGCC = Convert.transform(coordWGS84);
181 NodeGeotools.STR n2 = new NodeGeotools.STR(Objects.toString(node.getID()), coordGCC);
182 return n2;
183 }
184 catch (FactoryException exception)
185 {
186 exception.printStackTrace();
187 }
188 catch (TransformException exception)
189 {
190 exception.printStackTrace();
191 }
192 }
193 catch (NumberFormatException exception)
194 {
195 exception.printStackTrace();
196 }
197 catch (IOException exception)
198 {
199 exception.printStackTrace();
200 }
201 }
202 else
203 {
204 coordWGS84 = new Coordinate(node.getLongitude(), node.getLatitude(), 0D);
205 try
206 {
207 coordGCC = Convert.transform(coordWGS84);
208 NodeGeotools.STR n2 = new NodeGeotools.STR(Objects.toString(node.getID()), coordGCC);
209 return n2;
210 }
211 catch (FactoryException exception)
212 {
213 exception.printStackTrace();
214 }
215 catch (TransformException exception)
216 {
217 exception.printStackTrace();
218 }
219 }
220 return null;
221 }
222
223
224
225
226
227 private static HashMap<Double, LaneAttributes> makeStructure(final org.opentrafficsim.importexport.osm.Link osmlink)
228 {
229 SortedMap<Integer, LaneAttributes> structure = new TreeMap<Integer, LaneAttributes>();
230 HashMap<Double, LaneAttributes> structurewithOffset = new HashMap<Double, LaneAttributes>();
231 int forwards = osmlink.getForwardLanes();
232 int backwards = osmlink.getLanes() - osmlink.getForwardLanes();
233 LaneType<String> lt;
234 LaneAttributes la;
235
236 for (org.opentrafficsim.importexport.osm.Tag t : osmlink.getTags())
237 {
238 if (t.getKey().equals("highway")
239 && (t.getValue().equals("primary") || t.getValue().equals("secondary")
240 || t.getValue().equals("tertiary") || t.getValue().equals("residential")
241 || t.getValue().equals("trunk") || t.getValue().equals("motorway")
242 || t.getValue().equals("service") || t.getValue().equals("unclassified")
243 || t.getValue().equals("motorway_link") || t.getValue().equals("primary_link")
244 || t.getValue().equals("secondary_link") || t.getValue().equals("tertiary_link")
245 || t.getValue().equals("trunk_link") || t.getValue().equals("road")))
246 {
247 lt = makeLaneType(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.car);
248 if (osmlink.getLanes() == 1 && !osmlink.isOneway())
249 {
250 la = new LaneAttributes(lt, Color.LIGHT_GRAY, LongitudinalDirectionality.BOTH);
251 structure.put(0, la);
252 }
253 for (int i = 0 - backwards; i < forwards; i++)
254 {
255 if (i < 0)
256 {
257 la = new LaneAttributes(lt, Color.LIGHT_GRAY, LongitudinalDirectionality.BACKWARD);
258 structure.put(i, la);
259 }
260 if (i >= 0)
261 {
262 la = new LaneAttributes(lt, Color.LIGHT_GRAY, LongitudinalDirectionality.FORWARD);
263 structure.put(i, la);
264 }
265 }
266 }
267 else if (t.getKey().equals("highway") && t.getValue().equals("path"))
268 {
269 List<GTUType<String>> types = new ArrayList<GTUType<String>>();
270 for (org.opentrafficsim.importexport.osm.Tag t2 : osmlink.getTags())
271 {
272 if (t2.getKey().equals("bicycle"))
273 {
274 types.add(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.bike);
275 }
276
277
278
279
280 }
281 lt = makeLaneType(types);
282 types.add(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.pedestrian);
283 if (!types.isEmpty())
284 {
285 if (osmlink.getLanes() == 1 && !osmlink.isOneway())
286 {
287 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.BOTH);
288 structure.put(0, la);
289 }
290 for (int i = 0 - backwards; i < forwards; i++)
291 {
292 if (i < 0)
293 {
294 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.BACKWARD);
295 structure.put(i, la);
296 }
297 if (i >= 0)
298 {
299 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.FORWARD);
300 structure.put(i, la);
301 }
302 }
303 }
304 types.clear();
305 }
306 }
307 for (org.opentrafficsim.importexport.osm.Tag t : osmlink.getTags())
308 {
309 if (t.getKey().equals("cycleway"))
310 {
311 lt = makeLaneType(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.bike);
312 switch (t.getValue())
313 {
314 case "lane":
315 forwards++;
316 backwards++;
317 la = new LaneAttributes(lt, Color.ORANGE, LongitudinalDirectionality.BACKWARD);
318 structure.put(0 - backwards, la);
319 la = new LaneAttributes(lt, Color.ORANGE, LongitudinalDirectionality.FORWARD);
320 structure.put(forwards - 1, la);
321 break;
322 case "track":
323 forwards++;
324 backwards++;
325 la = new LaneAttributes(lt, Color.ORANGE, LongitudinalDirectionality.BACKWARD);
326 structure.put(0 - backwards, la);
327 la = new LaneAttributes(lt, Color.ORANGE, LongitudinalDirectionality.FORWARD);
328 structure.put(forwards - 1, la);
329 break;
330 case "shared_lane":
331 List<GTUType<String>> types = new ArrayList<GTUType<String>>();
332 types.add(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.bike);
333 types.add(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.car);
334 lt = makeLaneType(types);
335 la = new LaneAttributes(lt, Color.ORANGE, LongitudinalDirectionality.BACKWARD);
336 structure.put(0 - backwards, la);
337 la = new LaneAttributes(lt, Color.ORANGE, LongitudinalDirectionality.FORWARD);
338 structure.put(forwards - 1, la);
339 break;
340 default:
341 break;
342 }
343 }
344 }
345 for (org.opentrafficsim.importexport.osm.Tag t : osmlink.getTags())
346 {
347 if (t.getKey().equals("sidewalk"))
348 {
349 lt = makeLaneType(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.pedestrian);
350 switch (t.getValue())
351 {
352 case "both":
353 forwards++;
354 backwards++;
355 la = new LaneAttributes(lt, Color.YELLOW, LongitudinalDirectionality.BACKWARD);
356 structure.put(0 - backwards, la);
357 la = new LaneAttributes(lt, Color.YELLOW, LongitudinalDirectionality.FORWARD);
358 structure.put(forwards - 1, la);
359 break;
360 case "left":
361 backwards++;
362 la = new LaneAttributes(lt, Color.YELLOW, LongitudinalDirectionality.BOTH);
363 structure.put(0 - backwards, la);
364 break;
365 case "right":
366 forwards++;
367 la = new LaneAttributes(lt, Color.YELLOW, LongitudinalDirectionality.BOTH);
368 structure.put(forwards - 1, la);
369 break;
370 default:
371 break;
372 }
373 }
374 }
375 for (org.opentrafficsim.importexport.osm.Tag t : osmlink.getTags())
376 {
377 if (t.getKey().equals("highway")
378 && (t.getValue().equals("cycleway") || t.getValue().equals("footway")
379 || t.getValue().equals("pedestrian") || t.getValue().equals("steps")))
380 {
381 if (t.getValue().equals("footway") || t.getValue().equals("pedestrian") || t.getValue().equals("steps"))
382 {
383 lt = makeLaneType(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.pedestrian);
384 if (osmlink.getLanes() == 1 && !osmlink.isOneway())
385 {
386 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.BOTH);
387 structure.put(0, la);
388 }
389 for (int i = 0 - backwards; i < forwards; i++)
390 {
391 if (i < 0)
392 {
393 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.BACKWARD);
394 structure.put(i, la);
395 }
396 if (i >= 0)
397 {
398 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.FORWARD);
399 structure.put(i, la);
400 }
401 }
402 }
403 if (t.getValue().equals("cycleway"))
404 {
405 lt = makeLaneType(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.bike);
406 if (osmlink.getLanes() == 1 && !osmlink.isOneway())
407 {
408 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.BOTH);
409 structure.put(0, la);
410 }
411 for (int i = 0 - backwards; i < forwards; i++)
412 {
413 if (i < 0)
414 {
415 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.BACKWARD);
416 structure.put(i, la);
417 }
418 if (i >= 0)
419 {
420 la = new LaneAttributes(lt, Color.GREEN, LongitudinalDirectionality.FORWARD);
421 structure.put(i, la);
422 }
423 }
424 }
425 }
426 }
427 structurewithOffset = calculateOffsets(structure, osmlink, forwards, backwards);
428 return structurewithOffset;
429 }
430
431
432
433
434
435
436
437
438 private static HashMap<Double, LaneAttributes> calculateOffsets(final SortedMap<Integer, LaneAttributes> structure,
439 final org.opentrafficsim.importexport.osm.Link osmlink, final Integer forwards, final Integer backwards)
440 {
441 HashMap<Double, LaneAttributes> structurewithOffset = new HashMap<Double, LaneAttributes>();
442 LaneType<?> lt;
443 Double width = 3.05D;
444 LaneAttributes la;
445
446
447 for (org.opentrafficsim.importexport.osm.Tag t : osmlink.getTags())
448 {
449 if (t.getKey().equals("width"))
450 {
451 String w = t.getValue().replace(",", ".");
452 width = Double.parseDouble(w) / osmlink.getLanes();
453
454 }
455 }
456 double currentOffset = 0.0D;
457 if (structure.lastKey() >= 0)
458 {
459 for (int i = 0; i < forwards; i++)
460 {
461 la = structure.get(i);
462 lt = la.getLaneType();
463
464
465
466 if (lt.isCompatible(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.car))
467 {
468 la.setWidth(width);
469 structurewithOffset.put(currentOffset, la);
470 currentOffset += width;
471 }
472 else if (lt.isCompatible(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.bike))
473 {
474 la.setWidth(0.8D);
475 structurewithOffset.put(currentOffset, la);
476 currentOffset += 0.8D;
477 }
478 else if (lt.isCompatible(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.pedestrian))
479 {
480 la.setWidth(0.95D);
481 structurewithOffset.put(currentOffset, la);
482 currentOffset += 0.95D;
483 }
484 }
485 }
486 if (structure.firstKey() < 0)
487 {
488 currentOffset = 0.0D;
489 for (int i = -1; i >= (0 - backwards); i--)
490 {
491 la = structure.get(i);
492 LaneAttributes la2 = structure.get(i + 1);
493 lt = la.getLaneType();
494 LaneType<?> lt2 = la2.getLaneType();
495 if (lt2.isCompatible(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.car))
496 {
497 la.setWidth(width);
498 currentOffset -= width;
499 structurewithOffset.put(currentOffset, la);
500 }
501 else if (lt2.isCompatible(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.bike))
502 {
503 la.setWidth(0.8D);
504 currentOffset -= 0.8D;
505 structurewithOffset.put(currentOffset, la);
506 }
507 else if (lt2.isCompatible(org.opentrafficsim.importexport.osm.PredefinedGTUTypes.pedestrian))
508 {
509 la.setWidth(0.95D);
510 currentOffset -= 0.95D;
511 structurewithOffset.put(currentOffset, la);
512 }
513 }
514 }
515 return structurewithOffset;
516 }
517
518
519
520
521
522
523
524
525
526
527
528
529 public static List<Lane> makeLanes(final org.opentrafficsim.importexport.osm.Link osmlink,
530 final OTSDEVSSimulatorInterface simulator) throws NetworkException, RemoteException, NamingException
531 {
532 CrossSectionLink<?, ?> otslink = convertLink(osmlink);
533 List<Lane> lanes = new ArrayList<Lane>();
534 LaneType<?> lt = null;
535 Lane result = null;
536 Color color = Color.LIGHT_GRAY;
537 HashMap<Double, LaneAttributes> structure = makeStructure(osmlink);
538
539 DoubleScalar.Abs<FrequencyUnit> f2000 = new DoubleScalar.Abs<FrequencyUnit>(2000.0, FrequencyUnit.PER_HOUR);
540
541 Iterator<Double> iter = structure.keySet().iterator();
542 while (iter.hasNext())
543 {
544 Double i = iter.next();
545 LaneAttributes la = structure.get(i);
546 lt = la.getLaneType();
547 Double offSet = i;
548 DoubleScalar.Rel<LengthUnit> latPos = new DoubleScalar.Rel<LengthUnit>(offSet, LengthUnit.METER);
549 if (osmlink.hasTag("hasPreceding") && i >= 0)
550 {
551 color = Color.RED;
552 result = new SinkLane(otslink, latPos, la.getWidth(), lt, la.getDirectionality());
553 }
554 else if (osmlink.hasTag("hasPreceding") && i < 0)
555 {
556 color = Color.BLUE;
557 result = new SourceLane(otslink, latPos, la.getWidth(), lt, la.getDirectionality());
558 }
559 else if (osmlink.hasTag("hasFollowing") && i >= 0)
560 {
561 color = Color.BLUE;
562 result = new SourceLane(otslink, latPos, la.getWidth(), lt, la.getDirectionality());
563 }
564 else if (osmlink.hasTag("hasFollowing") && i < 0)
565 {
566 color = Color.RED;
567 result = new SinkLane(otslink, latPos, la.getWidth(), lt, la.getDirectionality());
568 }
569 else
570 {
571 color = la.getColor();
572 result =
573 new Lane(otslink, latPos, latPos, la.getWidth(), la.getWidth(), lt, la.getDirectionality(),
574 f2000);
575 }
576 animateLane(result, simulator, color);
577 lanes.add(result);
578 }
579 return lanes;
580 }
581
582
583
584
585
586
587
588
589
590 private static void animateLane(final Lane l, final OTSDEVSSimulatorInterface simulator, final Color color)
591 throws RemoteException, NamingException
592 {
593 if (simulator instanceof OTSAnimatorInterface)
594 {
595 new LaneAnimation(l, simulator, color);
596 }
597 }
598
599
600
601
602
603
604 public static LaneType<String> makeLaneType(final List<GTUType<String>> gtuTypes)
605 {
606 String iD = "";
607 for (GTUType<String> gtu : gtuTypes)
608 {
609 iD += gtu.getId() + "|";
610 }
611 LaneType<String> lt = new LaneType<String>(iD);
612 for (GTUType<String> gtu : gtuTypes)
613 {
614 lt.addPermeability(gtu);
615 }
616 return lt;
617 }
618
619
620
621
622
623
624 public static LaneType<String> makeLaneType(final GTUType<String> gtuType)
625 {
626 String iD = gtuType.getId();
627 LaneType<String> lt = new LaneType<String>(iD);
628 lt.addPermeability(gtuType);
629 return lt;
630 }
631
632
633
634
635
636
637 private static ArrayList<org.opentrafficsim.importexport.osm.Link> findPossibleSinks(
638 final List<org.opentrafficsim.importexport.osm.Node> nodes,
639 final List<org.opentrafficsim.importexport.osm.Link> links)
640 {
641 ArrayList<org.opentrafficsim.importexport.osm.Node> foundSinkNodes =
642 new ArrayList<org.opentrafficsim.importexport.osm.Node>();
643 ArrayList<org.opentrafficsim.importexport.osm.Link> foundSinkLinks =
644 new ArrayList<org.opentrafficsim.importexport.osm.Link>();
645 for (org.opentrafficsim.importexport.osm.Node n : nodes)
646 {
647 int count = 0;
648 for (org.opentrafficsim.importexport.osm.Link l : links)
649 {
650 if (l.getStart().equals(n) || l.getEnd().equals(n) || l.getSplineList().contains(n))
651 {
652 count += 1;
653 if (count > 1)
654 {
655 break;
656 }
657 }
658 }
659 if (count == 1)
660 {
661 foundSinkNodes.add(n);
662 }
663 }
664 for (org.opentrafficsim.importexport.osm.Link l : links)
665 {
666 if (foundSinkNodes.contains(l.getEnd()) || foundSinkNodes.contains(l.getStart()))
667 {
668 foundSinkLinks.add(l);
669 }
670 else
671 {
672 for (org.opentrafficsim.importexport.osm.Node n : l.getSplineList())
673 {
674 if (foundSinkNodes.contains(n))
675 {
676 foundSinkLinks.add(l);
677 }
678 }
679 }
680 }
681
682
683
684
685 return foundSinkLinks;
686 }
687
688
689
690
691
692 public static org.opentrafficsim.importexport.osm.Network findSinksandSources(
693 final org.opentrafficsim.importexport.osm.Network net)
694 {
695 List<org.opentrafficsim.importexport.osm.Node> nodes =
696 new ArrayList<org.opentrafficsim.importexport.osm.Node>();
697 nodes.addAll(net.getNodes().values());
698 ArrayList<org.opentrafficsim.importexport.osm.Link> foundSinkLinks = findPossibleSinks(nodes, net.getLinks());
699 for (org.opentrafficsim.importexport.osm.Link l : net.getLinks())
700 {
701 if (foundSinkLinks.contains(l))
702 {
703 if (net.hasFollowingLink(l))
704 {
705 l.addTag(new org.opentrafficsim.importexport.osm.Tag("hasFollowing", ""));
706 }
707 else if (net.hasPrecedingLink(l))
708 {
709 l.addTag(new org.opentrafficsim.importexport.osm.Tag("hasPreceding", ""));
710 }
711 }
712 }
713 return net;
714 }
715 }
716
717
718
719
720
721
722
723
724
725
726 class LaneAttributes
727 {
728
729 private LaneType<?> laneType;
730
731
732 private Color color;
733
734
735 private LongitudinalDirectionality directionaility;
736
737
738 private DoubleScalar.Rel<LengthUnit> width;
739
740
741
742
743
744
745 public LaneAttributes(final LaneType<?> lt, final Color c, final LongitudinalDirectionality d)
746 {
747 this.laneType = lt;
748 this.color = c;
749 this.directionaility = d;
750 }
751
752
753
754
755
756
757
758 public LaneAttributes(final LaneType<?> lt, final Color c, final LongitudinalDirectionality d, final Double w)
759 {
760 this.laneType = lt;
761 this.color = c;
762 this.directionaility = d;
763 this.setWidth(w);
764 }
765
766
767
768
769 public LaneType<?> getLaneType()
770 {
771 return this.laneType;
772 }
773
774
775
776
777 public Color getColor()
778 {
779 return this.color;
780 }
781
782
783
784
785 public LongitudinalDirectionality getDirectionality()
786 {
787 return this.directionaility;
788 }
789
790
791
792
793 public DoubleScalar.Rel<LengthUnit> getWidth()
794 {
795 return this.width;
796 }
797
798
799
800
801 public void setWidth(final Double width)
802 {
803 DoubleScalar.Rel<LengthUnit> w = new DoubleScalar.Rel<LengthUnit>(width, LengthUnit.METER);
804 this.width = w;
805 }
806 }