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