1 package org.opentrafficsim.road.network.factory.xml;
2
3 import java.awt.Color;
4 import java.lang.reflect.Constructor;
5 import java.lang.reflect.InvocationTargetException;
6 import java.rmi.RemoteException;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.LinkedHashMap;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import java.util.UUID;
15
16 import javax.naming.NamingException;
17
18 import org.djunits.unit.AngleUnit;
19 import org.djunits.value.AngleUtil;
20 import org.djunits.value.vdouble.scalar.Direction;
21 import org.djunits.value.vdouble.scalar.Length;
22 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
23 import org.opentrafficsim.core.geometry.Bezier;
24 import org.opentrafficsim.core.geometry.OTSGeometryException;
25 import org.opentrafficsim.core.geometry.OTSLine3D;
26 import org.opentrafficsim.core.geometry.OTSPoint3D;
27 import org.opentrafficsim.core.gtu.GTUException;
28 import org.opentrafficsim.core.gtu.GTUType;
29 import org.opentrafficsim.core.gtu.RelativePosition;
30 import org.opentrafficsim.core.network.LinkType;
31 import org.opentrafficsim.core.network.LongitudinalDirectionality;
32 import org.opentrafficsim.core.network.NetworkException;
33 import org.opentrafficsim.core.network.animation.LinkAnimation;
34 import org.opentrafficsim.road.network.animation.LaneAnimation;
35 import org.opentrafficsim.road.network.animation.ShoulderAnimation;
36 import org.opentrafficsim.road.network.animation.StripeAnimation;
37 import org.opentrafficsim.road.network.factory.xml.ArcTag.ArcDirection;
38 import org.opentrafficsim.road.network.lane.CrossSectionElement;
39 import org.opentrafficsim.road.network.lane.CrossSectionLink;
40 import org.opentrafficsim.road.network.lane.Lane;
41 import org.opentrafficsim.road.network.lane.LaneType;
42 import org.opentrafficsim.road.network.lane.NoTrafficLane;
43 import org.opentrafficsim.road.network.lane.Shoulder;
44 import org.opentrafficsim.road.network.lane.Stripe;
45 import org.opentrafficsim.road.network.lane.Stripe.Permeable;
46 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
47 import org.opentrafficsim.road.network.lane.object.LaneBlock;
48 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
49 import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
50 import org.xml.sax.SAXException;
51
52 import nl.tudelft.simulation.dsol.SimRuntimeException;
53 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
54 import nl.tudelft.simulation.language.d3.CartesianPoint;
55 import nl.tudelft.simulation.language.d3.DirectedPoint;
56 import nl.tudelft.simulation.language.reflection.ClassUtil;
57
58
59
60
61
62
63
64
65
66
67 final class Links
68 {
69
70 private Links()
71 {
72
73 }
74
75
76
77
78
79
80
81 @SuppressWarnings("methodlength")
82 static void calculateNodeCoordinates(final XmlNetworkLaneParser parser) throws NetworkException, NamingException
83 {
84
85 for (LinkTag linkTag : parser.linkTags.values())
86 {
87 if (linkTag.straightTag != null && linkTag.nodeStartTag.coordinate != null && linkTag.nodeEndTag.coordinate != null)
88 {
89 if (linkTag.nodeStartTag.angle == null)
90 {
91 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
92 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
93 linkTag.nodeStartTag.angle = new Direction(Math.atan2(dy, dx), AngleUnit.RADIAN);
94 }
95 if (linkTag.nodeEndTag.angle == null)
96 {
97 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
98 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
99 linkTag.nodeEndTag.angle = new Direction(Math.atan2(dy, dx), AngleUnit.RADIAN);
100 }
101 }
102 }
103
104
105 Set<NodeTag> nodeTags = new HashSet<>();
106 for (LinkTag linkTag : parser.linkTags.values())
107 {
108 if (linkTag.nodeStartTag.coordinate == null)
109 {
110 nodeTags.add(linkTag.nodeStartTag);
111 }
112 if (linkTag.nodeEndTag.coordinate == null)
113 {
114 nodeTags.add(linkTag.nodeEndTag);
115 }
116 }
117
118 while (nodeTags.size() > 0)
119 {
120 boolean found = false;
121 for (LinkTag linkTag : parser.linkTags.values())
122 {
123 if (linkTag.straightTag != null || linkTag.arcTag != null)
124 {
125 if (nodeTags.contains(linkTag.nodeStartTag) == nodeTags.contains(linkTag.nodeEndTag))
126 {
127 continue;
128 }
129
130 if (linkTag.straightTag != null)
131 {
132 double lengthSI = linkTag.straightTag.length.getSI();
133 if (linkTag.nodeEndTag.node == null)
134 {
135 CartesianPoint coordinate = new CartesianPoint(linkTag.nodeStartTag.node.getLocation().getX(),
136 linkTag.nodeStartTag.node.getLocation().getY(),
137 linkTag.nodeStartTag.node.getLocation().getZ());
138 double angle = linkTag.nodeStartTag.node.getDirection().getSI();
139 double slope = linkTag.nodeStartTag.node.getSlope().getSI();
140 coordinate.x += lengthSI * Math.cos(angle);
141 coordinate.y += lengthSI * Math.sin(angle);
142 coordinate.z += lengthSI * Math.sin(slope);
143 NodeTag nodeTag = linkTag.nodeEndTag;
144 nodeTag.angle = new Direction(angle, AngleUnit.SI);
145 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
146 nodeTag.slope = new Direction(slope, AngleUnit.SI);
147 linkTag.nodeEndTag.node = NodeTag.makeOTSNode(nodeTag, parser);
148 nodeTags.remove(linkTag.nodeEndTag);
149 }
150 else if (linkTag.nodeStartTag.node == null)
151 {
152 CartesianPoint coordinate = new CartesianPoint(linkTag.nodeEndTag.node.getLocation().getX(),
153 linkTag.nodeEndTag.node.getLocation().getY(), linkTag.nodeEndTag.node.getLocation().getZ());
154 double angle = linkTag.nodeEndTag.node.getDirection().getSI();
155 double slope = linkTag.nodeEndTag.node.getSlope().getSI();
156 coordinate.x -= lengthSI * Math.cos(angle);
157 coordinate.y -= lengthSI * Math.sin(angle);
158 coordinate.z -= lengthSI * Math.sin(slope);
159 NodeTag nodeTag = linkTag.nodeStartTag;
160 nodeTag.angle = new Direction(angle, AngleUnit.SI);
161 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
162 nodeTag.slope = new Direction(slope, AngleUnit.SI);
163 linkTag.nodeStartTag.node = NodeTag.makeOTSNode(nodeTag, parser);
164 nodeTags.remove(linkTag.nodeStartTag);
165 }
166 }
167 else if (linkTag.arcTag != null)
168 {
169 double radiusSI = linkTag.arcTag.radius.getSI();
170 double angle = linkTag.arcTag.angle.getSI();
171 ArcDirection direction = linkTag.arcTag.direction;
172
173 if (linkTag.nodeEndTag.node == null)
174 {
175 CartesianPoint coordinate = new CartesianPoint(0.0, 0.0, 0.0);
176 double startAngle = linkTag.nodeStartTag.node.getDirection().getSI();
177 double slope = linkTag.nodeStartTag.node.getSlope().getSI();
178 double lengthSI = radiusSI * angle;
179 NodeTag nodeTag = linkTag.nodeEndTag;
180 if (direction.equals(ArcDirection.LEFT))
181 {
182 linkTag.arcTag.center = new OTSPoint3D(
183 linkTag.nodeStartTag.node.getLocation().getX()
184 + radiusSI * Math.cos(startAngle + Math.PI / 2.0),
185 linkTag.nodeStartTag.node.getLocation().getY()
186 + radiusSI * Math.sin(startAngle + Math.PI / 2.0),
187 0.0);
188 linkTag.arcTag.startAngle = startAngle - Math.PI / 2.0;
189 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle + angle);
190 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle + angle);
191 nodeTag.angle = new Direction(AngleUtil.normalize(startAngle + angle), AngleUnit.SI);
192 }
193 else
194 {
195 linkTag.arcTag.center = new OTSPoint3D(
196 linkTag.nodeStartTag.node.getLocation().getX()
197 - radiusSI * Math.cos(startAngle + Math.PI / 2.0),
198 linkTag.nodeStartTag.node.getLocation().getY()
199 - radiusSI * Math.sin(startAngle + Math.PI / 2.0),
200 0.0);
201 linkTag.arcTag.startAngle = startAngle + Math.PI / 2.0;
202 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle - angle);
203 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle - angle);
204 nodeTag.angle = new Direction(AngleUtil.normalize(startAngle - angle), AngleUnit.SI);
205 }
206 coordinate.z = linkTag.nodeStartTag.node.getLocation().getZ() + lengthSI * Math.sin(slope);
207 nodeTag.slope = new Direction(slope, AngleUnit.SI);
208 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
209 linkTag.nodeEndTag.node = NodeTag.makeOTSNode(nodeTag, parser);
210 nodeTags.remove(linkTag.nodeEndTag);
211 }
212
213 else if (linkTag.nodeStartTag.node == null)
214 {
215 CartesianPoint coordinate = new CartesianPoint(linkTag.nodeEndTag.node.getLocation().getX(),
216 linkTag.nodeEndTag.node.getLocation().getY(), linkTag.nodeEndTag.node.getLocation().getZ());
217 double endAngle = linkTag.nodeEndTag.node.getDirection().getSI();
218 double slope = linkTag.nodeEndTag.node.getSlope().getSI();
219 double lengthSI = radiusSI * angle;
220 NodeTag nodeTag = linkTag.nodeStartTag;
221 if (direction.equals(ArcDirection.LEFT))
222 {
223 linkTag.arcTag.center =
224 new OTSPoint3D(coordinate.x + radiusSI * Math.cos(endAngle + Math.PI / 2.0),
225 coordinate.y + radiusSI * Math.sin(endAngle + Math.PI / 2.0), 0.0);
226 linkTag.arcTag.startAngle = endAngle - Math.PI / 2.0 - angle;
227 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle);
228 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle);
229 nodeTag.angle = new Direction(AngleUtil.normalize(linkTag.arcTag.startAngle + Math.PI / 2.0),
230 AngleUnit.SI);
231 }
232 else
233 {
234 linkTag.arcTag.center =
235 new OTSPoint3D(coordinate.x + radiusSI * Math.cos(endAngle - Math.PI / 2.0),
236 coordinate.y + radiusSI * Math.sin(endAngle - Math.PI / 2.0), 0.0);
237 linkTag.arcTag.startAngle = endAngle + Math.PI / 2.0 + angle;
238 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle);
239 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle);
240 nodeTag.angle = new Direction(AngleUtil.normalize(linkTag.arcTag.startAngle - Math.PI / 2.0),
241 AngleUnit.SI);
242 }
243 coordinate.z -= lengthSI * Math.sin(slope);
244 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
245 nodeTag.slope = new Direction(slope, AngleUnit.SI);
246 linkTag.nodeStartTag.node = NodeTag.makeOTSNode(nodeTag, parser);
247 nodeTags.remove(linkTag.nodeStartTag);
248 }
249 }
250 }
251 }
252 if (!found)
253 {
254 throw new NetworkException("Cannot find coordinates of one or more nodes");
255 }
256 }
257
258
259 for (LinkTag linkTag : parser.linkTags.values())
260 {
261 if (linkTag.straightTag != null && linkTag.nodeStartTag.coordinate != null && linkTag.nodeEndTag.coordinate != null)
262 {
263 if (linkTag.nodeStartTag.angle == null)
264 {
265 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
266 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
267 linkTag.nodeStartTag.angle = new Direction(Math.atan2(dy, dx), AngleUnit.RADIAN);
268 }
269 if (linkTag.nodeEndTag.angle == null)
270 {
271 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
272 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
273 linkTag.nodeEndTag.angle = new Direction(Math.atan2(dy, dx), AngleUnit.RADIAN);
274 }
275 }
276 }
277
278
279 for (NodeTag nodeTag : parser.nodeTags.values())
280 {
281 if (nodeTag.coordinate != null && nodeTag.node == null)
282 {
283 if (nodeTag.angle == null)
284 {
285 nodeTag.angle = Direction.ZERO;
286 }
287 if (nodeTag.slope == null)
288 {
289 nodeTag.slope = Direction.ZERO;
290 }
291 nodeTag.node = NodeTag.makeOTSNode(nodeTag, parser);
292 }
293 }
294
295 }
296
297
298
299
300
301
302
303
304
305
306 static void buildLink(final LinkTag linkTag, final XmlNetworkLaneParser parser, final OTSDEVSSimulatorInterface simulator)
307 throws OTSGeometryException, NamingException, NetworkException
308 {
309 NodeTag from = linkTag.nodeStartTag;
310 OTSPoint3D startPoint = new OTSPoint3D(from.coordinate);
311 double startAngle = from.angle.si;
312 if (linkTag.offsetStart != null && linkTag.offsetStart.si != 0.0)
313 {
314
315 double offset = linkTag.offsetStart.si;
316 startPoint = new OTSPoint3D(startPoint.x + offset * Math.cos(startAngle + Math.PI / 2.0),
317 startPoint.y + offset * Math.sin(startAngle + Math.PI / 2.0), startPoint.z);
318 System.out
319 .println("fc = " + from.coordinate + ", sa = " + startAngle + ", so = " + offset + ", sp = " + startPoint);
320 }
321
322 NodeTag to = linkTag.nodeEndTag;
323 OTSPoint3D endPoint = new OTSPoint3D(to.coordinate);
324 double endAngle = to.angle.si;
325 if (linkTag.offsetEnd != null && linkTag.offsetEnd.si != 0.0)
326 {
327
328 double offset = linkTag.offsetEnd.si;
329 endPoint = new OTSPoint3D(endPoint.x + offset * Math.cos(endAngle + Math.PI / 2.0),
330 endPoint.y + offset * Math.sin(endAngle + Math.PI / 2.0), endPoint.z);
331 System.out.println("tc = " + to.coordinate + ", ea = " + endAngle + ", eo = " + offset + ", ep = " + endPoint);
332 }
333
334 OTSPoint3D[] coordinates = null;
335
336 if (linkTag.straightTag != null)
337 {
338 coordinates = new OTSPoint3D[2];
339 coordinates[0] = startPoint;
340 coordinates[1] = endPoint;
341 }
342
343 else if (linkTag.polyLineTag != null)
344 {
345 int intermediatePoints = linkTag.polyLineTag.coordinates.length;
346 coordinates = new OTSPoint3D[intermediatePoints + 2];
347 coordinates[0] = startPoint;
348 coordinates[intermediatePoints + 1] = endPoint;
349 for (int p = 0; p < intermediatePoints; p++)
350 {
351 coordinates[p + 1] = linkTag.polyLineTag.coordinates[p];
352 }
353
354 }
355 else if (linkTag.arcTag != null)
356 {
357
358 int points = (Math.abs(linkTag.arcTag.angle.getSI()) <= Math.PI / 2.0) ? 64 : 128;
359 coordinates = new OTSPoint3D[points];
360 coordinates[0] = new OTSPoint3D(from.coordinate.x, from.coordinate.y, from.coordinate.z);
361 coordinates[coordinates.length - 1] = new OTSPoint3D(to.coordinate.x, to.coordinate.y, to.coordinate.z);
362 double angleStep = linkTag.arcTag.angle.getSI() / points;
363 double slopeStep = (to.coordinate.z - from.coordinate.z) / points;
364 double radiusSI = linkTag.arcTag.radius.getSI();
365 if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
366 {
367 for (int p = 1; p < points - 1; p++)
368 {
369 coordinates[p] = new OTSPoint3D(
370 linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle - angleStep * p),
371 linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle - angleStep * p),
372 from.coordinate.z + slopeStep * p);
373 }
374 }
375 else
376 {
377 for (int p = 1; p < points - 1; p++)
378 {
379 try
380 {
381 System.err.println("linkTag.arcTag.center = " + linkTag.arcTag.center);
382 System.err.println("linkTag.arcTag.startAngle = " + linkTag.arcTag.startAngle);
383 coordinates[p] = new OTSPoint3D(
384 linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle + angleStep * p),
385 linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle + angleStep * p),
386 from.coordinate.z + slopeStep * p);
387 }
388 catch (NullPointerException npe)
389 {
390 npe.printStackTrace();
391 System.err.println(npe.getMessage());
392 }
393 }
394 }
395 }
396
397 else if (linkTag.bezierTag != null)
398 {
399 coordinates = Bezier.cubic(128, new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle),
400 new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle)).getPoints();
401 }
402
403 else
404 {
405 throw new NetworkException(
406 "Making link, but link " + linkTag.name + " has no filled straight, arc, or bezier curve");
407 }
408
409 OTSLine3D designLine = OTSLine3D.createAndCleanOTSLine3D(coordinates);
410
411
412 CrossSectionLink link = new CrossSectionLink(parser.network, linkTag.name, linkTag.nodeStartTag.node,
413 linkTag.nodeEndTag.node, LinkType.ALL, designLine, new HashMap<GTUType, LongitudinalDirectionality>(),
414 linkTag.laneKeepingPolicy);
415 try
416 {
417 new LinkAnimation(link, simulator, 0.5f);
418 }
419 catch (RemoteException exception)
420 {
421 exception.printStackTrace();
422 }
423 linkTag.link = link;
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437 @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:methodlength" })
438 static void applyRoadTypeToLink(final LinkTag linkTag, final XmlNetworkLaneParser parser,
439 final OTSDEVSSimulatorInterface simulator)
440 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
441 {
442 CrossSectionLink csl = linkTag.link;
443 List<CrossSectionElement> cseList = new ArrayList<>();
444 List<Lane> lanes = new ArrayList<>();
445
446 LongitudinalDirectionality linkDirection = LongitudinalDirectionality.DIR_NONE;
447 for (CrossSectionElementTag cseTag : linkTag.roadLayoutTag.cseTags.values())
448 {
449 LaneOverrideTag laneOverrideTag = null;
450 if (linkTag.laneOverrideTags.containsKey(cseTag.name))
451 laneOverrideTag = linkTag.laneOverrideTags.get(cseTag.name);
452
453 switch (cseTag.elementType)
454 {
455 case STRIPE:
456 switch (cseTag.stripeType)
457 {
458 case BLOCKED:
459 case DASHED:
460 Stripe dashedLine = new Stripe(csl, cseTag.offset, cseTag.width);
461 dashedLine.addPermeability(GTUType.ALL, Permeable.BOTH);
462 if (simulator != null && simulator instanceof AnimatorInterface)
463 {
464 try
465 {
466 new StripeAnimation(dashedLine, simulator, StripeAnimation.TYPE.DASHED);
467 }
468 catch (RemoteException exception)
469 {
470 exception.printStackTrace();
471 }
472 }
473 cseList.add(dashedLine);
474 break;
475
476 case DOUBLE:
477 Stripe doubleLine = new Stripe(csl, cseTag.offset, cseTag.width);
478 if (simulator != null && simulator instanceof AnimatorInterface)
479 {
480 try
481 {
482 new StripeAnimation(doubleLine, simulator, StripeAnimation.TYPE.DOUBLE);
483 }
484 catch (RemoteException exception)
485 {
486 exception.printStackTrace();
487 }
488 }
489 cseList.add(doubleLine);
490 break;
491
492 case LEFTONLY:
493 Stripe leftOnlyLine = new Stripe(csl, cseTag.offset, cseTag.width);
494 leftOnlyLine.addPermeability(GTUType.ALL, Permeable.LEFT);
495 if (simulator != null && simulator instanceof AnimatorInterface)
496 {
497 try
498 {
499 new StripeAnimation(leftOnlyLine, simulator, StripeAnimation.TYPE.LEFTONLY);
500 }
501 catch (RemoteException exception)
502 {
503 exception.printStackTrace();
504 }
505 }
506 cseList.add(leftOnlyLine);
507 break;
508
509 case RIGHTONLY:
510 Stripe rightOnlyLine = new Stripe(csl, cseTag.offset, cseTag.width);
511 rightOnlyLine.addPermeability(GTUType.ALL, Permeable.RIGHT);
512 if (simulator != null && simulator instanceof AnimatorInterface)
513 {
514 try
515 {
516 new StripeAnimation(rightOnlyLine, simulator, StripeAnimation.TYPE.RIGHTONLY);
517 }
518 catch (RemoteException exception)
519 {
520 exception.printStackTrace();
521 }
522 }
523 cseList.add(rightOnlyLine);
524 break;
525
526 case SOLID:
527 Stripe solidLine = new Stripe(csl, cseTag.offset, cseTag.width);
528 if (simulator != null && simulator instanceof AnimatorInterface)
529 {
530 try
531 {
532 new StripeAnimation(solidLine, simulator, StripeAnimation.TYPE.SOLID);
533 }
534 catch (RemoteException exception)
535 {
536 exception.printStackTrace();
537 }
538 }
539 cseList.add(solidLine);
540 break;
541
542 default:
543 throw new SAXException("Unknown Stripe type: " + cseTag.stripeType.toString());
544 }
545 break;
546
547 case LANE:
548 {
549 LongitudinalDirectionality direction = cseTag.direction;
550 Color color = cseTag.color;
551 OvertakingConditions overtakingConditions = cseTag.overtakingConditions;
552 if (laneOverrideTag != null)
553 {
554 if (laneOverrideTag.overtakingConditions != null)
555 overtakingConditions = laneOverrideTag.overtakingConditions;
556 if (laneOverrideTag.color != null)
557 color = laneOverrideTag.color;
558 if (laneOverrideTag.direction != null)
559 direction = laneOverrideTag.direction;
560 }
561 Map<GTUType, LongitudinalDirectionality> directionality = new LinkedHashMap<>();
562 directionality.put(GTUType.ALL, direction);
563 if (linkDirection.equals(LongitudinalDirectionality.DIR_NONE))
564 {
565 linkDirection = direction;
566 }
567 else if (linkDirection.isForward())
568 {
569 if (direction.isBackwardOrBoth())
570 {
571 linkDirection = LongitudinalDirectionality.DIR_BOTH;
572 }
573 }
574 else if (linkDirection.isBackward())
575 {
576 if (direction.isForwardOrBoth())
577 {
578 linkDirection = LongitudinalDirectionality.DIR_BOTH;
579 }
580 }
581
582
583 csl.addDirectionality(GTUType.ALL, linkDirection);
584
585
586 Lane lane = new Lane(csl, cseTag.name, cseTag.offset, cseTag.offset, cseTag.width, cseTag.width,
587 LaneType.ALL, directionality, cseTag.legalSpeedLimits, overtakingConditions);
588
589
590
591
592
593
594 cseList.add(lane);
595 lanes.add(lane);
596 linkTag.lanes.put(cseTag.name, lane);
597 if (simulator != null && simulator instanceof AnimatorInterface)
598 {
599 try
600 {
601 new LaneAnimation(lane, simulator, color, false);
602 }
603 catch (RemoteException exception)
604 {
605 exception.printStackTrace();
606 }
607 }
608
609
610 if (linkTag.sinkTags.keySet().contains(cseTag.name))
611 {
612 SinkTag sinkTag = linkTag.sinkTags.get(cseTag.name);
613 Length position = LinkTag.parseBeginEndPosition(sinkTag.positionStr, lane);
614 new SinkSensor(lane, position, simulator);
615 }
616
617
618 if (linkTag.blockTags.containsKey(cseTag.name))
619 {
620 BlockTag blockTag = linkTag.blockTags.get(cseTag.name);
621 Length position = LinkTag.parseBeginEndPosition(blockTag.positionStr, lane);
622 new LaneBlock(UUID.randomUUID().toString(), lane, position, Length.ZERO);
623 }
624
625
626 if (linkTag.trafficLightTags.containsKey(cseTag.name))
627 {
628 for (TrafficLightTag trafficLightTag : linkTag.trafficLightTags.get(cseTag.name))
629 {
630 try
631 {
632 Class<?> clazz = Class.forName(trafficLightTag.className);
633 Constructor<?> trafficLightConstructor = ClassUtil.resolveConstructor(clazz, new Class[] {
634 String.class, Lane.class, Length.class, OTSDEVSSimulatorInterface.class });
635 Length position = LinkTag.parseBeginEndPosition(trafficLightTag.positionStr, lane);
636 SimpleTrafficLight trafficLight = (SimpleTrafficLight) trafficLightConstructor
637 .newInstance(new Object[] { trafficLightTag.name, lane, position, simulator });
638 }
639 catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
640 | IllegalAccessException | IllegalArgumentException | InvocationTargetException
641 | NetworkException exception)
642 {
643 throw new NetworkException("TRAFFICLIGHT: CLASS NAME " + trafficLightTag.className
644 + " for traffic light " + trafficLightTag.name + " on lane " + lane.toString()
645 + " -- class not found or constructor not right", exception);
646 }
647 }
648 }
649
650
651 if (linkTag.generatorTags.containsKey(cseTag.name))
652 {
653 GeneratorTag generatorTag = linkTag.generatorTags.get(cseTag.name);
654 GeneratorTag.makeGenerator(generatorTag, parser, linkTag, simulator);
655 }
656
657
658
659
660 if (linkTag.sensorTags.containsKey(cseTag.name))
661 {
662 for (SensorTag sensorTag : linkTag.sensorTags.get(cseTag.name))
663 {
664 try
665 {
666 Class<?> clazz = Class.forName(sensorTag.className);
667 Constructor<?> sensorConstructor =
668 ClassUtil.resolveConstructor(clazz, new Class[] { String.class, Lane.class,
669 Length.class, RelativePosition.TYPE.class, OTSDEVSSimulatorInterface.class });
670 Length position = LinkTag.parseBeginEndPosition(sensorTag.positionStr, lane);
671
672
673 sensorConstructor.newInstance(
674 new Object[] { sensorTag.name, lane, position, sensorTag.triggerPosition, simulator });
675 }
676 catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
677 | IllegalAccessException | IllegalArgumentException | InvocationTargetException
678 | NetworkException exception)
679 {
680 throw new NetworkException("SENSOR: CLASS NAME " + sensorTag.className + " for sensor "
681 + sensorTag.name + " on lane " + lane.toString()
682 + " -- class not found or constructor not right", exception);
683 }
684 }
685 }
686
687
688 if (linkTag.fillTags.containsKey(cseTag.name))
689 {
690 FillTag fillTag = linkTag.fillTags.get(cseTag.name);
691 FillTag.makeFill(fillTag, parser, linkTag, simulator);
692 }
693 break;
694 }
695
696 case NOTRAFFICLANE:
697 {
698 Lane lane = new NoTrafficLane(csl, cseTag.name, cseTag.offset, cseTag.offset, cseTag.width, cseTag.width);
699 cseList.add(lane);
700 if (simulator != null && simulator instanceof AnimatorInterface)
701 {
702 try
703 {
704 Color color = cseTag.color;
705 if (laneOverrideTag != null)
706 {
707 if (laneOverrideTag.color != null)
708 color = laneOverrideTag.color;
709 }
710 new LaneAnimation(lane, simulator, color, false);
711 }
712 catch (RemoteException exception)
713 {
714 exception.printStackTrace();
715 }
716 }
717 break;
718 }
719
720 case SHOULDER:
721 {
722 Shoulder shoulder = new Shoulder(csl, cseTag.name, cseTag.offset, cseTag.width);
723 cseList.add(shoulder);
724 if (simulator != null && simulator instanceof AnimatorInterface)
725 {
726 try
727 {
728 Color color = cseTag.color;
729 if (laneOverrideTag != null)
730 {
731 if (laneOverrideTag.color != null)
732 color = laneOverrideTag.color;
733 }
734 new ShoulderAnimation(shoulder, simulator, color);
735 }
736 catch (RemoteException exception)
737 {
738 exception.printStackTrace();
739 }
740 }
741 break;
742 }
743
744 default:
745 throw new SAXException("Unknown Element type: " + cseTag.elementType.toString());
746 }
747
748 }
749
750
751 csl.addDirectionality(GTUType.ALL, linkDirection);
752 }
753 }