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