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.djutils.reflection.ClassUtil;
21 import org.opentrafficsim.core.animation.DrawingInfoLine;
22 import org.opentrafficsim.core.animation.DrawingInfoStripe;
23 import org.opentrafficsim.core.animation.StripeType;
24 import org.opentrafficsim.core.compatibility.Compatible;
25 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
26 import org.opentrafficsim.core.geometry.Bezier;
27 import org.opentrafficsim.core.geometry.OTSGeometryException;
28 import org.opentrafficsim.core.geometry.OTSLine3D;
29 import org.opentrafficsim.core.geometry.OTSPoint3D;
30 import org.opentrafficsim.core.gtu.GTUException;
31 import org.opentrafficsim.core.gtu.GTUType;
32 import org.opentrafficsim.core.gtu.RelativePosition;
33 import org.opentrafficsim.core.network.LinkType;
34 import org.opentrafficsim.core.network.LongitudinalDirectionality;
35 import org.opentrafficsim.core.network.NetworkException;
36 import org.opentrafficsim.draw.road.LaneAnimation;
37 import org.opentrafficsim.draw.road.ShoulderAnimation;
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.xml.sax.SAXException;
50
51 import nl.tudelft.simulation.dsol.SimRuntimeException;
52 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
53 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
54 import nl.tudelft.simulation.language.d3.CartesianPoint;
55 import nl.tudelft.simulation.language.d3.DirectedPoint;
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), DirectionUnit.EAST_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), DirectionUnit.EAST_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), DirectionUnit.EAST_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), DirectionUnit.EAST_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().getInUnit();
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, DirectionUnit.EAST_RADIAN);
166 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
167 nodeTag.slope = new Angle(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().getInUnit();
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, DirectionUnit.EAST_RADIAN);
182 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
183 nodeTag.slope = new Angle(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.getInUnit();
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().getInUnit();
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 =
213 new Direction(AngleUtil.normalize(startAngle + angle), DirectionUnit.EAST_RADIAN);
214 }
215 else
216 {
217 linkTag.arcTag.center = new OTSPoint3D(
218 linkTag.nodeStartTag.node.getLocation().getX()
219 - radiusSI * Math.cos(startAngle + Math.PI / 2.0),
220 linkTag.nodeStartTag.node.getLocation().getY()
221 - radiusSI * Math.sin(startAngle + Math.PI / 2.0),
222 0.0);
223 linkTag.arcTag.startAngle = startAngle + Math.PI / 2.0;
224 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle - angle);
225 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle - angle);
226 nodeTag.angle =
227 new Direction(AngleUtil.normalize(startAngle - angle), DirectionUnit.EAST_RADIAN);
228 }
229 coordinate.z = linkTag.nodeStartTag.node.getLocation().getZ() + lengthSI * Math.sin(slope);
230 nodeTag.slope = new Angle(slope, AngleUnit.SI);
231 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
232 linkTag.nodeEndTag.node = NodeTag.makeOTSNode(nodeTag, parser);
233 nodeTags.remove(linkTag.nodeEndTag);
234 }
235
236 else if (linkTag.nodeStartTag.node == null)
237 {
238 CartesianPoint coordinate = new CartesianPoint(linkTag.nodeEndTag.node.getLocation().getX(),
239 linkTag.nodeEndTag.node.getLocation().getY(), linkTag.nodeEndTag.node.getLocation().getZ());
240 double endAngle = linkTag.nodeEndTag.node.getDirection().getInUnit();
241 double slope = linkTag.nodeEndTag.node.getSlope().getSI();
242 double lengthSI = radiusSI * angle;
243 NodeTag nodeTag = linkTag.nodeStartTag;
244 if (direction.equals(ArcDirection.LEFT))
245 {
246 linkTag.arcTag.center =
247 new OTSPoint3D(coordinate.x + radiusSI * Math.cos(endAngle + Math.PI / 2.0),
248 coordinate.y + radiusSI * Math.sin(endAngle + Math.PI / 2.0), 0.0);
249 linkTag.arcTag.startAngle = endAngle - Math.PI / 2.0 - angle;
250 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle);
251 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle);
252 nodeTag.angle = new Direction(AngleUtil.normalize(linkTag.arcTag.startAngle + Math.PI / 2.0),
253 DirectionUnit.EAST_RADIAN);
254 }
255 else
256 {
257 linkTag.arcTag.center =
258 new OTSPoint3D(coordinate.x + radiusSI * Math.cos(endAngle - Math.PI / 2.0),
259 coordinate.y + radiusSI * Math.sin(endAngle - Math.PI / 2.0), 0.0);
260 linkTag.arcTag.startAngle = endAngle + Math.PI / 2.0 + angle;
261 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle);
262 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle);
263 nodeTag.angle = new Direction(AngleUtil.normalize(linkTag.arcTag.startAngle - Math.PI / 2.0),
264 DirectionUnit.EAST_RADIAN);
265 }
266 coordinate.z -= lengthSI * Math.sin(slope);
267 nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
268 nodeTag.slope = new Angle(slope, AngleUnit.SI);
269 linkTag.nodeStartTag.node = NodeTag.makeOTSNode(nodeTag, parser);
270 nodeTags.remove(linkTag.nodeStartTag);
271 }
272 }
273 }
274 }
275 if (!found)
276 {
277 throw new NetworkException("Cannot find coordinates of one or more nodes");
278 }
279 }
280
281
282 for (LinkTag linkTag : parser.linkTags.values())
283 {
284 if (linkTag.straightTag != null && linkTag.nodeStartTag.coordinate != null && linkTag.nodeEndTag.coordinate != null)
285 {
286 if (linkTag.nodeStartTag.angle == null)
287 {
288 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
289 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
290 linkTag.nodeStartTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
291 }
292 if (linkTag.nodeEndTag.angle == null)
293 {
294 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
295 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
296 linkTag.nodeEndTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
297 }
298 }
299 }
300
301
302 for (NodeTag nodeTag : parser.nodeTags.values())
303 {
304 if (nodeTag.coordinate != null && nodeTag.node == null)
305 {
306 if (nodeTag.angle == null)
307 {
308 nodeTag.angle = Direction.ZERO;
309 }
310 if (nodeTag.slope == null)
311 {
312 nodeTag.slope = Angle.ZERO;
313 }
314 nodeTag.node = NodeTag.makeOTSNode(nodeTag, parser);
315 }
316 }
317
318 }
319
320
321
322
323
324
325
326
327
328
329 static void buildConnector(final ConnectorTag connectorTag, final XmlNetworkLaneParser parser,
330 final OTSSimulatorInterface simulator) throws OTSGeometryException, NamingException, NetworkException
331 {
332 OTSLine3D designLine =
333 new OTSLine3D(connectorTag.nodeStartTag.node.getPoint(), connectorTag.nodeEndTag.node.getPoint());
334 CrossSectionLink connector = new CrossSectionLink(parser.network, connectorTag.name, connectorTag.nodeStartTag.node,
335 connectorTag.nodeEndTag.node, LinkType.CONNECTOR, designLine, simulator, null);
336 if (connectorTag.demandWeight != null)
337 {
338 connector.setDemandWeight(connectorTag.demandWeight);
339 }
340 parser.networkAnimation.addDrawingInfoBase(connector, new DrawingInfoLine<CrossSectionLink>(Color.BLACK, 0.5f));
341 connectorTag.connector = connector;
342 }
343
344
345
346
347
348
349
350
351
352
353 static void buildLink(final LinkTag linkTag, final XmlNetworkLaneParser parser, final OTSSimulatorInterface simulator)
354 throws OTSGeometryException, NamingException, NetworkException
355 {
356 NodeTag from = linkTag.nodeStartTag;
357 OTSPoint3D startPoint = new OTSPoint3D(from.coordinate);
358 double startAngle = from.angle.getInUnit();
359 if (linkTag.offsetStart != null && linkTag.offsetStart.si != 0.0)
360 {
361
362 double offset = linkTag.offsetStart.si;
363 startPoint = new OTSPoint3D(startPoint.x + offset * Math.cos(startAngle + Math.PI / 2.0),
364 startPoint.y + offset * Math.sin(startAngle + Math.PI / 2.0), startPoint.z);
365 System.out
366 .println("fc = " + from.coordinate + ", sa = " + startAngle + ", so = " + offset + ", sp = " + startPoint);
367 }
368
369 NodeTag to = linkTag.nodeEndTag;
370 OTSPoint3D endPoint = new OTSPoint3D(to.coordinate);
371 double endAngle = to.angle.getInUnit();
372 if (linkTag.offsetEnd != null && linkTag.offsetEnd.si != 0.0)
373 {
374
375 double offset = linkTag.offsetEnd.si;
376 endPoint = new OTSPoint3D(endPoint.x + offset * Math.cos(endAngle + Math.PI / 2.0),
377 endPoint.y + offset * Math.sin(endAngle + Math.PI / 2.0), endPoint.z);
378 System.out.println("tc = " + to.coordinate + ", ea = " + endAngle + ", eo = " + offset + ", ep = " + endPoint);
379 }
380
381 OTSPoint3D[] coordinates = null;
382
383 if (linkTag.straightTag != null)
384 {
385 coordinates = new OTSPoint3D[2];
386 coordinates[0] = startPoint;
387 coordinates[1] = endPoint;
388 }
389
390 else if (linkTag.polyLineTag != null)
391 {
392 int intermediatePoints = linkTag.polyLineTag.coordinates.length;
393 coordinates = new OTSPoint3D[intermediatePoints + 2];
394 coordinates[0] = startPoint;
395 coordinates[intermediatePoints + 1] = endPoint;
396 for (int p = 0; p < intermediatePoints; p++)
397 {
398 coordinates[p + 1] = linkTag.polyLineTag.coordinates[p];
399 }
400
401 }
402 else if (linkTag.arcTag != null)
403 {
404
405 double radiusSI = linkTag.arcTag.radius.getSI();
406 double offsetStart = 0.0;
407 if (linkTag.offsetStart != null)
408 {
409 offsetStart = linkTag.offsetStart.si;
410 }
411 double offsetEnd = 0.0;
412 if (linkTag.offsetEnd != null)
413 {
414 offsetEnd = linkTag.offsetEnd.si;
415 }
416 List<OTSPoint3D> center = OTSPoint3D.circleIntersections(from.coordinate, radiusSI + offsetStart, to.coordinate,
417 radiusSI + offsetEnd);
418 OTSPoint3D c = linkTag.arcTag.center =
419 (linkTag.arcTag.direction.equals(ArcTag.ArcDirection.RIGHT)) ? center.get(0) : center.get(1);
420
421
422 double sa = linkTag.arcTag.startAngle = Math.atan2(from.coordinate.y - c.y, from.coordinate.x - c.x);
423 double ea = Math.atan2(to.coordinate.y - c.y, to.coordinate.x - c.x);
424 if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
425 {
426
427 ea = (sa < ea) ? ea + Math.PI * 2.0 : ea;
428 }
429 else
430 {
431
432 ea = (ea < sa) ? ea + Math.PI * 2.0 : ea;
433 }
434
435 int points = (AngleUtil.normalize(ea - sa) <= Math.PI / 2.0) ? 64 : 128;
436 coordinates = new OTSPoint3D[points];
437 coordinates[0] = new OTSPoint3D(from.coordinate.x + Math.cos(sa) * offsetStart,
438 from.coordinate.y + Math.sin(sa) * offsetStart, from.coordinate.z);
439 coordinates[coordinates.length - 1] = new OTSPoint3D(to.coordinate.x + Math.cos(ea) * offsetEnd,
440 to.coordinate.y + Math.sin(ea) * offsetEnd, to.coordinate.z);
441 double angleStep = linkTag.arcTag.angle.getInUnit() / points;
442 double slopeStep = (to.coordinate.z - from.coordinate.z) / points;
443
444 if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
445 {
446 for (int p = 1; p < points - 1; p++)
447 {
448 double dRad = offsetStart + (offsetEnd - offsetStart) * p / points;
449 coordinates[p] = new OTSPoint3D(
450 linkTag.arcTag.center.x + (radiusSI + dRad) * Math.cos(linkTag.arcTag.startAngle - angleStep * p),
451 linkTag.arcTag.center.y + (radiusSI + dRad) * Math.sin(linkTag.arcTag.startAngle - angleStep * p),
452 from.coordinate.z + slopeStep * p);
453 }
454 }
455 else
456 {
457 for (int p = 1; p < points - 1; p++)
458 {
459 double dRad = offsetStart + (offsetEnd - offsetStart) * p / points;
460 coordinates[p] = new OTSPoint3D(
461 linkTag.arcTag.center.x + (radiusSI + dRad) * Math.cos(linkTag.arcTag.startAngle + angleStep * p),
462 linkTag.arcTag.center.y + (radiusSI + dRad) * Math.sin(linkTag.arcTag.startAngle + angleStep * p),
463 from.coordinate.z + slopeStep * p);
464 }
465 }
466 }
467
468 else if (linkTag.bezierTag != null)
469 {
470 coordinates = Bezier.cubic(128, new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle),
471 new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle), linkTag.bezierTag.shape,
472 linkTag.bezierTag.weighted).getPoints();
473 }
474
475 else
476 {
477 throw new NetworkException(
478 "Making link, but link " + linkTag.name + " has no filled straight, arc, or bezier curve");
479 }
480
481 OTSLine3D designLine = OTSLine3D.createAndCleanOTSLine3D(coordinates);
482
483
484 CrossSectionLink link = new CrossSectionLink(parser.network, linkTag.name, linkTag.nodeStartTag.node,
485 linkTag.nodeEndTag.node, LinkType.FREEWAY, designLine, simulator, linkTag.laneKeepingPolicy);
486
487 if (linkTag.priority != null)
488 {
489 link.setPriority(linkTag.priority);
490 }
491
492 parser.networkAnimation.addDrawingInfoBase(link, new DrawingInfoLine<CrossSectionLink>(Color.BLACK, 0.5f));
493
494 linkTag.link = link;
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508 @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:methodlength" })
509 static void applyRoadTypeToLink(final LinkTag linkTag, final XmlNetworkLaneParser parser,
510 final OTSSimulatorInterface simulator)
511 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
512 {
513 CrossSectionLink csl = linkTag.link;
514 List<CrossSectionElement> cseList = new ArrayList<>();
515 List<Lane> lanes = new ArrayList<>();
516
517 LongitudinalDirectionality linkDirection = LongitudinalDirectionality.DIR_NONE;
518 for (CrossSectionElementTag cseTag : linkTag.roadLayoutTag.cseTags.values())
519 {
520 LaneOverrideTag laneOverrideTag = null;
521 if (linkTag.laneOverrideTags.containsKey(cseTag.name))
522 laneOverrideTag = linkTag.laneOverrideTags.get(cseTag.name);
523
524 Length startOffset = cseTag.offset != null ? cseTag.offset : cseTag.offSetStart;
525 Length endOffset = cseTag.offset != null ? cseTag.offset : cseTag.offSetEnd;
526 switch (cseTag.elementType)
527 {
528 case STRIPE:
529 switch (cseTag.stripeType)
530 {
531 case BLOCKED:
532 case DASHED:
533 Stripe dashedLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
534 dashedLine.addPermeability(GTUType.VEHICLE, Permeable.BOTH);
535 parser.networkAnimation.addDrawingInfoBase(dashedLine,
536 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.DASHED));
537 cseList.add(dashedLine);
538 break;
539
540 case DOUBLE:
541 Stripe doubleLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
542 parser.networkAnimation.addDrawingInfoBase(doubleLine,
543 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.DOUBLE));
544 cseList.add(doubleLine);
545 break;
546
547 case LEFTONLY:
548 Stripe leftOnlyLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
549 leftOnlyLine.addPermeability(GTUType.VEHICLE, Permeable.LEFT);
550 parser.networkAnimation.addDrawingInfoBase(leftOnlyLine,
551 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.LEFTONLY));
552 cseList.add(leftOnlyLine);
553 break;
554
555 case RIGHTONLY:
556 Stripe rightOnlyLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
557 rightOnlyLine.addPermeability(GTUType.VEHICLE, Permeable.RIGHT);
558 parser.networkAnimation.addDrawingInfoBase(rightOnlyLine,
559 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.RIGHTONLY));
560 cseList.add(rightOnlyLine);
561 break;
562
563 case SOLID:
564 Stripe solidLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
565 parser.networkAnimation.addDrawingInfoBase(solidLine,
566 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.SOLID));
567 cseList.add(solidLine);
568 break;
569
570 default:
571 throw new SAXException("Unknown Stripe type: " + cseTag.stripeType.toString());
572 }
573 break;
574
575 case LANE:
576 {
577 LongitudinalDirectionality direction = cseTag.direction;
578 Color color = cseTag.color;
579 OvertakingConditions overtakingConditions = cseTag.overtakingConditions;
580 if (laneOverrideTag != null)
581 {
582 if (laneOverrideTag.overtakingConditions != null)
583 overtakingConditions = laneOverrideTag.overtakingConditions;
584 if (laneOverrideTag.color != null)
585 color = laneOverrideTag.color;
586 if (laneOverrideTag.direction != null)
587 direction = laneOverrideTag.direction;
588 }
589 if (linkDirection.equals(LongitudinalDirectionality.DIR_NONE))
590 {
591 linkDirection = direction;
592 }
593 else if (linkDirection.isForward())
594 {
595 if (direction.isBackwardOrBoth())
596 {
597 linkDirection = LongitudinalDirectionality.DIR_BOTH;
598 }
599 }
600 else if (linkDirection.isBackward())
601 {
602 if (direction.isForwardOrBoth())
603 {
604 linkDirection = LongitudinalDirectionality.DIR_BOTH;
605 }
606 }
607
608
609 Lane lane = new Lane(csl, cseTag.name, startOffset, endOffset, cseTag.width, cseTag.width, LaneType.FREEWAY,
610 cseTag.legalSpeedLimits, overtakingConditions);
611
612
613
614
615
616
617 cseList.add(lane);
618 lanes.add(lane);
619 linkTag.lanes.put(cseTag.name, lane);
620 if (simulator != null && simulator instanceof AnimatorInterface)
621 {
622 try
623 {
624 new LaneAnimation(lane, simulator, color, false);
625 }
626 catch (RemoteException exception)
627 {
628 exception.printStackTrace();
629 }
630 }
631
632
633 if (linkTag.sinkTags.keySet().contains(cseTag.name))
634 {
635 SinkTag sinkTag = linkTag.sinkTags.get(cseTag.name);
636 Length position = LinkTag.parseBeginEndPosition(sinkTag.positionStr, lane);
637 new SinkSensor(lane, position, simulator);
638 }
639
640
641 if (linkTag.trafficLightTags.containsKey(cseTag.name))
642 {
643 for (TrafficLightTag trafficLightTag : linkTag.trafficLightTags.get(cseTag.name))
644 {
645 try
646 {
647 Class<?> clazz = Class.forName(trafficLightTag.className);
648 Constructor<?> trafficLightConstructor = ClassUtil.resolveConstructor(clazz, new Class[] {
649 String.class, Lane.class, Length.class, DEVSSimulatorInterface.TimeDoubleUnit.class });
650 Length position = LinkTag.parseBeginEndPosition(trafficLightTag.positionStr, lane);
651 trafficLightConstructor
652 .newInstance(new Object[] { trafficLightTag.name, lane, position, simulator });
653 }
654 catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
655 | IllegalAccessException | IllegalArgumentException | InvocationTargetException
656 | NetworkException exception)
657 {
658 throw new NetworkException("TRAFFICLIGHT: CLASS NAME " + trafficLightTag.className
659 + " for traffic light " + trafficLightTag.name + " on lane " + lane.toString()
660 + " -- class not found or constructor not right", exception);
661 }
662 }
663 }
664
665
666 if (linkTag.generatorTags.containsKey(cseTag.name))
667 {
668 GeneratorTag generatorTag = linkTag.generatorTags.get(cseTag.name);
669 GeneratorTag.makeGenerator(generatorTag, parser, linkTag, simulator);
670 }
671
672
673
674
675 if (linkTag.sensorTags.containsKey(cseTag.name))
676 {
677 for (SensorTag sensorTag : linkTag.sensorTags.get(cseTag.name))
678 {
679 try
680 {
681 Class<?> clazz = Class.forName(sensorTag.className);
682 Constructor<?> sensorConstructor = ClassUtil.resolveConstructor(clazz,
683 new Class[] { String.class, Lane.class, Length.class, RelativePosition.TYPE.class,
684 DEVSSimulatorInterface.TimeDoubleUnit.class, Compatible.class });
685 Length position = LinkTag.parseBeginEndPosition(sensorTag.positionStr, lane);
686
687
688 sensorConstructor.newInstance(new Object[] { sensorTag.name, lane, position,
689 sensorTag.triggerPosition, simulator, Compatible.EVERYTHING });
690 }
691 catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
692 | IllegalAccessException | IllegalArgumentException | InvocationTargetException
693 | NetworkException exception)
694 {
695 throw new NetworkException("SENSOR: CLASS NAME " + sensorTag.className + " for sensor "
696 + sensorTag.name + " on lane " + lane.toString()
697 + " -- class not found or constructor not right", exception);
698 }
699 }
700 }
701
702
703 if (linkTag.fillTags.containsKey(cseTag.name))
704 {
705 FillTag fillTag = linkTag.fillTags.get(cseTag.name);
706 FillTag.makeFill(fillTag, parser, linkTag, simulator);
707 }
708 break;
709 }
710
711 case NOTRAFFICLANE:
712 {
713 Lane lane = new NoTrafficLane(csl, cseTag.name, startOffset, endOffset, cseTag.width, cseTag.width);
714 cseList.add(lane);
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 LaneAnimation(lane, simulator, color, false);
726 }
727 catch (RemoteException exception)
728 {
729 exception.printStackTrace();
730 }
731 }
732 break;
733 }
734
735 case SHOULDER:
736 {
737 Shoulder shoulder = new Shoulder(csl, cseTag.name, startOffset, endOffset, cseTag.width, cseTag.width);
738 cseList.add(shoulder);
739 if (simulator != null && simulator instanceof AnimatorInterface)
740 {
741 try
742 {
743 Color color = cseTag.color;
744 if (laneOverrideTag != null)
745 {
746 if (laneOverrideTag.color != null)
747 color = laneOverrideTag.color;
748 }
749 new ShoulderAnimation(shoulder, simulator, color);
750 }
751 catch (RemoteException exception)
752 {
753 exception.printStackTrace();
754 }
755 }
756 break;
757 }
758
759 default:
760 throw new SAXException("Unknown Element type: " + cseTag.elementType.toString());
761 }
762
763 }
764 }
765
766 }