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