1 package org.opentrafficsim.road.network.factory.xml.old;
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.List;
9
10 import javax.naming.NamingException;
11
12 import org.djunits.unit.DirectionUnit;
13 import org.djunits.value.AngleUtil;
14 import org.djunits.value.vdouble.scalar.Direction;
15 import org.djunits.value.vdouble.scalar.Length;
16 import org.djutils.reflection.ClassUtil;
17 import org.opentrafficsim.core.animation.DrawingInfoLine;
18 import org.opentrafficsim.core.animation.DrawingInfoStripe;
19 import org.opentrafficsim.core.animation.StripeType;
20 import org.opentrafficsim.core.compatibility.Compatible;
21 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
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.draw.road.LaneAnimation;
33 import org.opentrafficsim.draw.road.ShoulderAnimation;
34 import org.opentrafficsim.road.network.factory.xml.old.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.DirectedPoint;
51
52
53
54
55
56
57
58
59
60
61 final class Links
62 {
63
64 private Links()
65 {
66
67 }
68
69
70
71
72
73
74
75
76
77
78 static void buildConnector(final ConnectorTag connectorTag, final XmlNetworkLaneParserOld parser,
79 final OTSSimulatorInterface simulator) throws OTSGeometryException, NamingException, NetworkException
80 {
81 OTSLine3D designLine =
82 new OTSLine3D(connectorTag.nodeStartTag.node.getPoint(), connectorTag.nodeEndTag.node.getPoint());
83 CrossSectionLink connector = new CrossSectionLink(parser.network, connectorTag.name, connectorTag.nodeStartTag.node,
84 connectorTag.nodeEndTag.node, parser.network.getLinkType(LinkType.DEFAULTS.CONNECTOR), designLine, simulator,
85 null);
86 if (connectorTag.demandWeight != null)
87 {
88 connector.setDemandWeight(connectorTag.demandWeight);
89 }
90 parser.networkAnimation.addDrawingInfoBase(connector, new DrawingInfoLine<CrossSectionLink>(Color.BLACK, 0.5f));
91 connectorTag.connector = connector;
92 }
93
94
95
96
97
98 static void calculateNodeAngles(final LinkTag linkTag)
99 {
100 if (linkTag.straightTag != null)
101 {
102 double direction = Math.atan2(linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y,
103 linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x);
104 if (linkTag.nodeStartTag.direction == null)
105 {
106 linkTag.nodeStartTag.direction = new Direction(direction, DirectionUnit.EAST_RADIAN);
107 }
108 if (linkTag.nodeEndTag.direction == null)
109 {
110 linkTag.nodeEndTag.direction = new Direction(direction, DirectionUnit.EAST_RADIAN);
111 }
112 }
113 }
114
115
116
117
118
119
120
121
122
123
124 static void buildLink(final LinkTag linkTag, final XmlNetworkLaneParserOld parser, final OTSSimulatorInterface simulator)
125 throws OTSGeometryException, NamingException, NetworkException
126 {
127 NodeTag from = linkTag.nodeStartTag;
128 OTSPoint3D startPoint = new OTSPoint3D(from.coordinate);
129 double startAngle = linkTag.nodeStartTag.direction == null ? 0.0 : linkTag.nodeStartTag.direction.getInUnit();
130 if (linkTag.offsetStart != null && linkTag.offsetStart.si != 0.0)
131 {
132
133 double offset = linkTag.offsetStart.getInUnit();
134 startPoint = new OTSPoint3D(startPoint.x + offset * Math.cos(startAngle + Math.PI / 2.0),
135 startPoint.y + offset * Math.sin(startAngle + Math.PI / 2.0), startPoint.z);
136 System.out
137 .println("fc = " + from.coordinate + ", sa = " + startAngle + ", so = " + offset + ", sp = " + startPoint);
138 }
139
140 NodeTag to = linkTag.nodeEndTag;
141 OTSPoint3D endPoint = new OTSPoint3D(to.coordinate);
142 double endAngle = linkTag.nodeEndTag.direction == null ? 0.0 : linkTag.nodeEndTag.direction.getInUnit();
143 if (linkTag.offsetEnd != null && linkTag.offsetEnd.si != 0.0)
144 {
145
146 double offset = linkTag.offsetEnd.si;
147 endPoint = new OTSPoint3D(endPoint.x + offset * Math.cos(endAngle + Math.PI / 2.0),
148 endPoint.y + offset * Math.sin(endAngle + Math.PI / 2.0), endPoint.z);
149 System.out.println("tc = " + to.coordinate + ", ea = " + endAngle + ", eo = " + offset + ", ep = " + endPoint);
150 }
151
152 OTSPoint3D[] coordinates = null;
153
154 if (linkTag.straightTag != null)
155 {
156 coordinates = new OTSPoint3D[2];
157 coordinates[0] = startPoint;
158 coordinates[1] = endPoint;
159 }
160
161 else if (linkTag.polyLineTag != null)
162 {
163 int intermediatePoints = linkTag.polyLineTag.coordinates.length;
164 coordinates = new OTSPoint3D[intermediatePoints + 2];
165 coordinates[0] = startPoint;
166 coordinates[intermediatePoints + 1] = endPoint;
167 for (int p = 0; p < intermediatePoints; p++)
168 {
169 coordinates[p + 1] = linkTag.polyLineTag.coordinates[p];
170 }
171
172 }
173 else if (linkTag.arcTag != null)
174 {
175
176 double radiusSI = linkTag.arcTag.radius.getSI();
177 double offsetStart = 0.0;
178 if (linkTag.offsetStart != null)
179 {
180 offsetStart = linkTag.offsetStart.si;
181 }
182 double offsetEnd = 0.0;
183 if (linkTag.offsetEnd != null)
184 {
185 offsetEnd = linkTag.offsetEnd.si;
186 }
187 List<OTSPoint3D> center = OTSPoint3D.circleIntersections(from.coordinate, radiusSI + offsetStart, to.coordinate,
188 radiusSI + offsetEnd);
189 OTSPoint3D c = linkTag.arcTag.center =
190 (linkTag.arcTag.direction.equals(ArcTag.ArcDirection.RIGHT)) ? center.get(0) : center.get(1);
191
192
193 double sa = linkTag.arcTag.startAngle = Math.atan2(from.coordinate.y - c.y, from.coordinate.x - c.x);
194 double ea = Math.atan2(to.coordinate.y - c.y, to.coordinate.x - c.x);
195 if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
196 {
197
198 ea = (sa < ea) ? ea + Math.PI * 2.0 : ea;
199 }
200 else
201 {
202
203 ea = (ea < sa) ? ea + Math.PI * 2.0 : ea;
204 }
205
206 int points = (AngleUtil.normalize(ea - sa) <= Math.PI / 2.0) ? 64 : 128;
207 coordinates = new OTSPoint3D[points];
208 coordinates[0] = new OTSPoint3D(from.coordinate.x + Math.cos(sa) * offsetStart,
209 from.coordinate.y + Math.sin(sa) * offsetStart, from.coordinate.z);
210 coordinates[coordinates.length - 1] = new OTSPoint3D(to.coordinate.x + Math.cos(ea) * offsetEnd,
211 to.coordinate.y + Math.sin(ea) * offsetEnd, to.coordinate.z);
212 double angleStep = linkTag.arcTag.angle.getInUnit() / points;
213 double slopeStep = (to.coordinate.z - from.coordinate.z) / points;
214
215 if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
216 {
217 for (int p = 1; p < points - 1; p++)
218 {
219 double dRad = offsetStart + (offsetEnd - offsetStart) * p / points;
220 coordinates[p] = new OTSPoint3D(
221 linkTag.arcTag.center.x + (radiusSI + dRad) * Math.cos(linkTag.arcTag.startAngle - angleStep * p),
222 linkTag.arcTag.center.y + (radiusSI + dRad) * Math.sin(linkTag.arcTag.startAngle - angleStep * p),
223 from.coordinate.z + slopeStep * p);
224 }
225 }
226 else
227 {
228 for (int p = 1; p < points - 1; p++)
229 {
230 double dRad = offsetStart + (offsetEnd - offsetStart) * p / points;
231 coordinates[p] = new OTSPoint3D(
232 linkTag.arcTag.center.x + (radiusSI + dRad) * Math.cos(linkTag.arcTag.startAngle + angleStep * p),
233 linkTag.arcTag.center.y + (radiusSI + dRad) * Math.sin(linkTag.arcTag.startAngle + angleStep * p),
234 from.coordinate.z + slopeStep * p);
235 }
236 }
237 }
238
239 else if (linkTag.bezierTag != null)
240 {
241 coordinates = Bezier.cubic(128, new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle),
242 new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle), linkTag.bezierTag.shape,
243 linkTag.bezierTag.weighted).getPoints();
244 }
245
246 else
247 {
248 throw new NetworkException(
249 "Making link, but link " + linkTag.name + " has no filled straight, arc, or bezier curve");
250 }
251
252 OTSLine3D designLine = OTSLine3D.createAndCleanOTSLine3D(coordinates);
253
254
255 CrossSectionLink link = new CrossSectionLink(parser.network, linkTag.name, linkTag.nodeStartTag.node,
256 linkTag.nodeEndTag.node, parser.network.getLinkType(LinkType.DEFAULTS.FREEWAY), designLine, simulator,
257 linkTag.laneKeepingPolicy);
258
259 if (linkTag.priority != null)
260 {
261 link.setPriority(linkTag.priority);
262 }
263
264 parser.networkAnimation.addDrawingInfoBase(link, new DrawingInfoLine<CrossSectionLink>(Color.BLACK, 0.5f));
265
266 linkTag.link = link;
267 }
268
269
270
271
272
273
274
275
276
277
278
279
280 @SuppressWarnings({"checkstyle:needbraces", "checkstyle:methodlength"})
281 static void applyRoadTypeToLink(final LinkTag linkTag, final XmlNetworkLaneParserOld parser,
282 final OTSSimulatorInterface simulator)
283 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
284 {
285 CrossSectionLink csl = linkTag.link;
286 List<CrossSectionElement> cseList = new ArrayList<>();
287 List<Lane> lanes = new ArrayList<>();
288
289 LongitudinalDirectionality linkDirection = LongitudinalDirectionality.DIR_NONE;
290 for (CrossSectionElementTag cseTag : linkTag.roadLayoutTag.cseTags.values())
291 {
292 LaneOverrideTag laneOverrideTag = null;
293 if (linkTag.laneOverrideTags.containsKey(cseTag.name))
294 laneOverrideTag = linkTag.laneOverrideTags.get(cseTag.name);
295
296 Length startOffset = cseTag.offset != null ? cseTag.offset : cseTag.offSetStart;
297 Length endOffset = cseTag.offset != null ? cseTag.offset : cseTag.offSetEnd;
298 switch (cseTag.elementType)
299 {
300 case STRIPE:
301 switch (cseTag.stripeType)
302 {
303 case BLOCKED:
304 case DASHED:
305 Stripe dashedLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
306 dashedLine.addPermeability(csl.getNetwork().getGtuType(GTUType.DEFAULTS.VEHICLE), Permeable.BOTH);
307 parser.networkAnimation.addDrawingInfoBase(dashedLine,
308 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.DASHED));
309 cseList.add(dashedLine);
310 break;
311
312 case DOUBLE:
313 Stripe doubleLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
314 parser.networkAnimation.addDrawingInfoBase(doubleLine,
315 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.DOUBLE));
316 cseList.add(doubleLine);
317 break;
318
319 case LEFTONLY:
320 Stripe leftOnlyLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
321 leftOnlyLine.addPermeability(csl.getNetwork().getGtuType(GTUType.DEFAULTS.VEHICLE), Permeable.LEFT);
322
323 parser.networkAnimation.addDrawingInfoBase(leftOnlyLine,
324 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.LEFTONLY));
325 cseList.add(leftOnlyLine);
326 break;
327
328 case RIGHTONLY:
329 Stripe rightOnlyLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
330 rightOnlyLine.addPermeability(csl.getNetwork().getGtuType(GTUType.DEFAULTS.VEHICLE),
331 Permeable.RIGHT);
332
333 parser.networkAnimation.addDrawingInfoBase(rightOnlyLine,
334 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.RIGHTONLY));
335 cseList.add(rightOnlyLine);
336 break;
337
338 case SOLID:
339 Stripe solidLine = new Stripe(csl, startOffset, endOffset, cseTag.width);
340 parser.networkAnimation.addDrawingInfoBase(solidLine,
341 new DrawingInfoStripe<Stripe>(Color.BLACK, 0.5f, StripeType.SOLID));
342 cseList.add(solidLine);
343 break;
344
345 default:
346 throw new SAXException("Unknown Stripe type: " + cseTag.stripeType.toString());
347 }
348 break;
349
350 case LANE:
351 {
352 LongitudinalDirectionality direction = cseTag.direction;
353 Color color = cseTag.color;
354 OvertakingConditions overtakingConditions = cseTag.overtakingConditions;
355 if (laneOverrideTag != null)
356 {
357 if (laneOverrideTag.color != null)
358 color = laneOverrideTag.color;
359 if (laneOverrideTag.direction != null)
360 direction = laneOverrideTag.direction;
361 }
362 if (linkDirection.equals(LongitudinalDirectionality.DIR_NONE))
363 {
364 linkDirection = direction;
365 }
366 else if (linkDirection.isForward())
367 {
368 if (direction.isBackwardOrBoth())
369 {
370 linkDirection = LongitudinalDirectionality.DIR_BOTH;
371 }
372 }
373 else if (linkDirection.isBackward())
374 {
375 if (direction.isForwardOrBoth())
376 {
377 linkDirection = LongitudinalDirectionality.DIR_BOTH;
378 }
379 }
380
381
382 Lane lane = new Lane(csl, cseTag.name, startOffset, endOffset, cseTag.width, cseTag.width,
383 csl.getNetwork().getLaneType(LaneType.DEFAULTS.FREEWAY), cseTag.legalSpeedLimits);
384
385
386
387
388
389
390 cseList.add(lane);
391 lanes.add(lane);
392 linkTag.lanes.put(cseTag.name, lane);
393 if (simulator != null && simulator instanceof AnimatorInterface)
394 {
395 try
396 {
397 new LaneAnimation(lane, simulator, color, false);
398 }
399 catch (RemoteException exception)
400 {
401 exception.printStackTrace();
402 }
403 }
404
405
406 if (linkTag.sinkTags.keySet().contains(cseTag.name))
407 {
408 SinkTag sinkTag = linkTag.sinkTags.get(cseTag.name);
409 Length position = LinkTag.parseBeginEndPosition(sinkTag.positionStr, lane);
410 new SinkSensor(lane, position, simulator);
411 }
412
413
414 if (linkTag.trafficLightTags.containsKey(cseTag.name))
415 {
416 for (TrafficLightTag trafficLightTag : linkTag.trafficLightTags.get(cseTag.name))
417 {
418 try
419 {
420 Class<?> clazz = Class.forName(trafficLightTag.className);
421 Constructor<?> trafficLightConstructor = ClassUtil.resolveConstructor(clazz, new Class[] {
422 String.class, Lane.class, Length.class, DEVSSimulatorInterface.TimeDoubleUnit.class});
423 Length position = LinkTag.parseBeginEndPosition(trafficLightTag.positionStr, lane);
424 trafficLightConstructor
425 .newInstance(new Object[] {trafficLightTag.name, lane, position, simulator});
426 }
427 catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
428 | IllegalAccessException | IllegalArgumentException | InvocationTargetException
429 | NetworkException exception)
430 {
431 throw new NetworkException("TRAFFICLIGHT: CLASS NAME " + trafficLightTag.className
432 + " for traffic light " + trafficLightTag.name + " on lane " + lane.toString()
433 + " -- class not found or constructor not right", exception);
434 }
435 }
436 }
437
438
439 if (linkTag.generatorTags.containsKey(cseTag.name))
440 {
441 GeneratorTag generatorTag = linkTag.generatorTags.get(cseTag.name);
442 GeneratorTag.makeGenerator(generatorTag, parser, linkTag, simulator);
443 }
444
445
446
447
448 if (linkTag.sensorTags.containsKey(cseTag.name))
449 {
450 for (SensorTag sensorTag : linkTag.sensorTags.get(cseTag.name))
451 {
452 try
453 {
454 Class<?> clazz = Class.forName(sensorTag.className);
455 Constructor<?> sensorConstructor = ClassUtil.resolveConstructor(clazz,
456 new Class[] {String.class, Lane.class, Length.class, RelativePosition.TYPE.class,
457 DEVSSimulatorInterface.TimeDoubleUnit.class, Compatible.class});
458 Length position = LinkTag.parseBeginEndPosition(sensorTag.positionStr, lane);
459
460
461 sensorConstructor.newInstance(new Object[] {sensorTag.name, lane, position,
462 sensorTag.triggerPosition, simulator, Compatible.EVERYTHING});
463 }
464 catch (ClassNotFoundException | NoSuchMethodException | InstantiationException
465 | IllegalAccessException | IllegalArgumentException | InvocationTargetException
466 | NetworkException exception)
467 {
468 throw new NetworkException("SENSOR: CLASS NAME " + sensorTag.className + " for sensor "
469 + sensorTag.name + " on lane " + lane.toString()
470 + " -- class not found or constructor not right", exception);
471 }
472 }
473 }
474
475
476 if (linkTag.fillTags.containsKey(cseTag.name))
477 {
478 FillTag fillTag = linkTag.fillTags.get(cseTag.name);
479 FillTag.makeFill(fillTag, parser, linkTag, simulator);
480 }
481 break;
482 }
483
484 case NOTRAFFICLANE:
485 {
486 Lane lane = new NoTrafficLane(csl, cseTag.name, startOffset, endOffset, cseTag.width, cseTag.width);
487 cseList.add(lane);
488 if (simulator != null && simulator instanceof AnimatorInterface)
489 {
490 try
491 {
492 Color color = cseTag.color;
493 if (laneOverrideTag != null)
494 {
495 if (laneOverrideTag.color != null)
496 color = laneOverrideTag.color;
497 }
498 new LaneAnimation(lane, simulator, color, false);
499 }
500 catch (RemoteException exception)
501 {
502 exception.printStackTrace();
503 }
504 }
505 break;
506 }
507
508 case SHOULDER:
509 {
510 Shoulder shoulder = new Shoulder(csl, cseTag.name, startOffset, endOffset, cseTag.width, cseTag.width);
511 cseList.add(shoulder);
512 if (simulator != null && simulator instanceof AnimatorInterface)
513 {
514 try
515 {
516 Color color = cseTag.color;
517 if (laneOverrideTag != null)
518 {
519 if (laneOverrideTag.color != null)
520 color = laneOverrideTag.color;
521 }
522 new ShoulderAnimation(shoulder, simulator, color);
523 }
524 catch (RemoteException exception)
525 {
526 exception.printStackTrace();
527 }
528 }
529 break;
530 }
531
532 default:
533 throw new SAXException("Unknown Element type: " + cseTag.elementType.toString());
534 }
535
536 }
537 }
538
539 }