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