1 package org.opentrafficsim.road.network.factory.vissim;
2
3 import java.awt.Color;
4 import java.util.ArrayList;
5 import java.util.List;
6
7 import javax.naming.NamingException;
8
9 import org.djunits.unit.LengthUnit;
10 import org.djunits.unit.SpeedUnit;
11 import org.djunits.value.vdouble.scalar.Length;
12 import org.djunits.value.vdouble.scalar.Speed;
13 import org.opentrafficsim.core.compatibility.Compatible;
14 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
15 import org.opentrafficsim.core.geometry.Bezier;
16 import org.opentrafficsim.core.geometry.OTSGeometryException;
17 import org.opentrafficsim.core.geometry.OTSLine3D;
18 import org.opentrafficsim.core.geometry.OTSPoint3D;
19 import org.opentrafficsim.core.gtu.GTUException;
20 import org.opentrafficsim.core.gtu.RelativePosition;
21 import org.opentrafficsim.core.network.LateralDirectionality;
22 import org.opentrafficsim.core.network.LinkType;
23 import org.opentrafficsim.core.network.LongitudinalDirectionality;
24 import org.opentrafficsim.core.network.NetworkException;
25 import org.opentrafficsim.road.network.factory.vissim.ArcTag.ArcDirection;
26 import org.opentrafficsim.road.network.lane.CrossSectionElement;
27 import org.opentrafficsim.road.network.lane.CrossSectionLink;
28 import org.opentrafficsim.road.network.lane.Lane;
29 import org.opentrafficsim.road.network.lane.LaneType;
30 import org.opentrafficsim.road.network.lane.object.sensor.SimpleReportingSensor;
31 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
32 import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
33 import org.xml.sax.SAXException;
34
35 import nl.tudelft.simulation.dsol.SimRuntimeException;
36 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
37 import nl.tudelft.simulation.language.d3.DirectedPoint;
38
39
40
41
42
43
44
45
46
47
48 final class Links
49 {
50
51 private Links()
52 {
53
54 }
55
56
57
58
59
60
61
62
63
64
65 static void buildLink(final LinkTag linkTag, final VissimNetworkLaneParser parser, final OTSSimulatorInterface simulator)
66 throws OTSGeometryException, NamingException, NetworkException
67 {
68 NodeTag from = linkTag.nodeStartTag;
69 OTSPoint3D startPoint = new OTSPoint3D(from.coordinate);
70 double startAngle = 0.0;
71 if (linkTag.offsetStart != null && linkTag.offsetStart.si != 0.0)
72 {
73
74 double offset = linkTag.offsetStart.si;
75 startPoint = new OTSPoint3D(startPoint.x + offset * Math.cos(startAngle + Math.PI / 2.0),
76 startPoint.y + offset * Math.sin(startAngle + Math.PI / 2.0), startPoint.z);
77 System.out
78 .println("fc = " + from.coordinate + ", sa = " + startAngle + ", so = " + offset + ", sp = " + startPoint);
79 }
80
81 NodeTag to = linkTag.nodeEndTag;
82 OTSPoint3D endPoint = new OTSPoint3D(to.coordinate);
83 double endAngle = 0.0;
84 if (linkTag.offsetEnd != null && linkTag.offsetEnd.si != 0.0)
85 {
86
87 double offset = linkTag.offsetEnd.si;
88 endPoint = new OTSPoint3D(endPoint.x + offset * Math.cos(endAngle + Math.PI / 2.0),
89 endPoint.y + offset * Math.sin(endAngle + Math.PI / 2.0), endPoint.z);
90 System.out.println("tc = " + to.coordinate + ", ea = " + endAngle + ", eo = " + offset + ", ep = " + endPoint);
91 }
92
93 OTSPoint3D[] coordinates = null;
94
95 if (linkTag.straightTag != null)
96 {
97 coordinates = new OTSPoint3D[2];
98 coordinates[0] = startPoint;
99 coordinates[1] = endPoint;
100 }
101
102 else if (linkTag.polyLineTag != null)
103 {
104 int intermediatePoints = linkTag.polyLineTag.vertices.length;
105 coordinates = new OTSPoint3D[intermediatePoints + 2];
106 coordinates[0] = startPoint;
107 coordinates[intermediatePoints + 1] = endPoint;
108 for (int p = 0; p < intermediatePoints; p++)
109 {
110 coordinates[p + 1] = linkTag.polyLineTag.vertices[p];
111 }
112
113 }
114 else if (linkTag.arcTag != null)
115 {
116
117 int points = (Math.abs(linkTag.arcTag.angle.getInUnit()) <= Math.PI / 2.0) ? 64 : 128;
118 coordinates = new OTSPoint3D[points];
119 coordinates[0] = new OTSPoint3D(from.coordinate.x, from.coordinate.y, from.coordinate.z);
120 coordinates[coordinates.length - 1] = new OTSPoint3D(to.coordinate.x, to.coordinate.y, to.coordinate.z);
121 double angleStep = linkTag.arcTag.angle.getInUnit() / points;
122 double slopeStep = (to.coordinate.z - from.coordinate.z) / points;
123 double radiusSI = linkTag.arcTag.radius.getSI();
124 if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
125 {
126 for (int p = 1; p < points - 1; p++)
127 {
128 coordinates[p] = new OTSPoint3D(
129 linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle - angleStep * p),
130 linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle - angleStep * p),
131 from.coordinate.z + slopeStep * p);
132 }
133 }
134 else
135 {
136 for (int p = 1; p < points - 1; p++)
137 {
138 try
139 {
140 System.err.println("linkTag.arcTag.center = " + linkTag.arcTag.center);
141 System.err.println("linkTag.arcTag.startAngle = " + linkTag.arcTag.startAngle);
142 coordinates[p] = new OTSPoint3D(
143 linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle + angleStep * p),
144 linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle + angleStep * p),
145 from.coordinate.z + slopeStep * p);
146 }
147 catch (NullPointerException npe)
148 {
149 npe.printStackTrace();
150 System.err.println(npe.getMessage());
151 }
152 }
153 }
154 }
155
156 else if (linkTag.bezierTag != null)
157 {
158 if (new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle)
159 .equals(new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle)))
160 {
161 System.out.println(" ");
162 }
163
164 coordinates = Bezier.cubic(128, new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle),
165 new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle)).getPoints();
166 }
167
168 else
169 {
170 throw new NetworkException(
171 "Making link, but link " + linkTag.name + " has no filled straight, arc, or bezier curve");
172 }
173 if (coordinates.length < 2)
174 {
175 throw new OTSGeometryException(
176 "Degenerate OTSLine3D; has " + coordinates.length + " point" + (coordinates.length != 1 ? "s" : ""));
177 }
178 OTSLine3D designLine = OTSLine3D.createAndCleanOTSLine3D(coordinates);
179
180
181 CrossSectionLink link = new CrossSectionLink(parser.getNetwork(), linkTag.name, linkTag.nodeStartTag.node,
182 linkTag.nodeEndTag.node, LinkType.ROAD, designLine, simulator, linkTag.laneKeepingPolicy);
183 linkTag.link = link;
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197 @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:methodlength" })
198 static void applyRoadTypeToLink(final LinkTag linkTag, final VissimNetworkLaneParser parser,
199 final DEVSSimulatorInterface.TimeDoubleUnit simulator)
200 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
201 {
202 CrossSectionLink csl = linkTag.link;
203
204 List<CrossSectionElement> cseList = new ArrayList<>();
205 List<Lane> lanes = new ArrayList<>();
206
207 LongitudinalDirectionality linkDirection = LongitudinalDirectionality.DIR_NONE;
208
209
210
211
212 Double roadWidth = 0.0;
213 for (LaneTag laneTag : linkTag.laneTags.values())
214 {
215 roadWidth += Double.parseDouble(laneTag.width);
216 }
217
218 Color color;
219 if (linkTag.connector)
220 {
221 color = Color.LIGHT_GRAY;
222 }
223 else
224 {
225 color = Color.DARK_GRAY;
226
227 }
228
229
230 Double totalLaneWidth = 0.0;
231
232 if (!linkTag.connector)
233 {
234 for (LaneTag laneTag : linkTag.laneTags.values())
235 {
236 String name = laneTag.laneNo;
237 Double laneWidth = Double.parseDouble(laneTag.width);
238 Length thisLaneWidth = new Length(laneWidth, LengthUnit.METER);
239
240
241
242
243 Double negativeOffset = -(0.5 * roadWidth - totalLaneWidth - laneWidth / 2);
244 Length lateralOffset = new Length(negativeOffset, LengthUnit.METER);
245
246 LaneType laneType = LaneType.FREEWAY;
247 Speed speedLimit = new Speed(Double.parseDouble(linkTag.legalSpeed), SpeedUnit.KM_PER_HOUR);
248
249 Lane lane = new Lane(csl, name, lateralOffset, thisLaneWidth, laneType, speedLimit, null);
250 if (!linkTag.sensors.isEmpty())
251 {
252 for (SensorTag sensorTag : linkTag.sensors)
253 {
254 if (sensorTag.laneName.equals(laneTag.laneNo))
255 {
256 Length pos = new Length(Double.parseDouble(sensorTag.positionStr), LengthUnit.METER);
257 if (pos.lt(lane.getLength()))
258 {
259 try
260 {
261 new SimpleReportingSensor(sensorTag.laneName + ".S" + sensorTag.name, lane, pos,
262 RelativePosition.FRONT, simulator, Compatible.EVERYTHING);
263 }
264 catch (Exception exception)
265 {
266 System.err.println(exception.getMessage());
267 }
268 }
269 }
270 }
271 }
272
273 if (!linkTag.signalHeads.isEmpty())
274 {
275 for (SignalHeadTag signalHeadTag : linkTag.signalHeads)
276 {
277 if (signalHeadTag.laneName.equals(laneTag.laneNo))
278 {
279 Length pos = new Length(Double.parseDouble(signalHeadTag.positionStr), LengthUnit.METER);
280 if (pos.lt(lane.getLength()))
281 {
282 new SimpleTrafficLight(signalHeadTag.no, lane, pos, simulator);
283 }
284 }
285 }
286 }
287
288 cseList.add(lane);
289
290 lanes.add(lane);
291 linkTag.lanes.put(name, lane);
292
293 totalLaneWidth += Double.parseDouble(laneTag.width);
294
295
296 }
297 }
298
299 }
300
301
302
303
304
305
306
307
308
309
310
311
312 @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:methodlength" })
313 static void applyRoadTypeToConnector(final LinkTag linkTag, final VissimNetworkLaneParser parser,
314 final DEVSSimulatorInterface.TimeDoubleUnit simulator)
315 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
316 {
317 CrossSectionLink csl = linkTag.link;
318
319 List<CrossSectionElement> cseList = new ArrayList<>();
320 List<Lane> lanes = new ArrayList<>();
321
322
323
324
325 Double roadWidth = 0.0;
326 for (LaneTag laneTag : linkTag.laneTags.values())
327 {
328 roadWidth += Double.parseDouble(laneTag.width);
329 }
330
331 Color color;
332 if (linkTag.connector)
333 {
334 color = Color.LIGHT_GRAY;
335 }
336 else
337 {
338 color = Color.DARK_GRAY;
339
340 }
341
342
343 LaneType laneType = LaneType.FREEWAY;
344 Speed speedLimit = new Speed(Double.parseDouble(linkTag.legalSpeed), SpeedUnit.KM_PER_HOUR);
345
346
347
348 if (linkTag.connector)
349 {
350 Double totalFromLaneWidth = -1.75;
351 Double totalToLaneWidth = -1.75;
352
353 LinkTag linkToTag = parser.getRealLinkTags().get(linkTag.connectorTag.toLinkNo);
354 Lane laneTo = linkToTag.lanes.get(linkTag.connectorTag.toLaneNo);
355
356
357 LinkTag linkFromTag = parser.getRealLinkTags().get(linkTag.connectorTag.fromLinkNo);
358 Lane laneFrom = linkFromTag.lanes.get(linkTag.connectorTag.fromLaneNo);
359
360
361 for (LaneTag connectLaneTag : linkTag.laneTags.values())
362 {
363
364 String name = connectLaneTag.laneNo;
365
366 Length thisLaneWidth = new Length(Double.parseDouble(connectLaneTag.width), LengthUnit.METER);
367
368 Length totfromLaneWidth = new Length(totalFromLaneWidth, LengthUnit.METER);
369 Length totToLaneWidth = new Length(totalToLaneWidth, LengthUnit.METER);
370
371 Length lateralOffsetStart;
372 Length lateralOffsetEnd =
373 laneTo.getLateralBoundaryPosition(LateralDirectionality.RIGHT, 0).plus(totToLaneWidth);
374
375 if (laneFrom != null)
376 {
377 lateralOffsetStart =
378 laneFrom.getLateralBoundaryPosition(LateralDirectionality.RIGHT, 0).plus(totfromLaneWidth);
379 }
380 else
381 {
382 lateralOffsetStart = lateralOffsetEnd;
383 }
384
385
386
387 Lane lane = new Lane(csl, name, lateralOffsetStart, lateralOffsetEnd, thisLaneWidth, thisLaneWidth, laneType,
388 speedLimit, null);
389 cseList.add(lane);
390 lanes.add(lane);
391 linkTag.lanes.put(name, lane);
392
393
394 totalFromLaneWidth += Double.parseDouble(connectLaneTag.width);
395 totalToLaneWidth += Double.parseDouble(connectLaneTag.width);
396
397
398
399 }
400 }
401
402 }
403
404
405
406
407
408
409
410 public static void createSinkSensor(LinkTag realLinkTag, VissimNetworkLaneParser vissimNetworkLaneParser,
411 DEVSSimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
412 {
413 if (!realLinkTag.connector)
414 {
415 boolean deadLink = true;
416 for (LinkTag linkTag : vissimNetworkLaneParser.getLinkTags().values())
417 {
418 if (realLinkTag.nodeEndTag.name.equals(linkTag.nodeStartTag.name) && !realLinkTag.equals(linkTag))
419 {
420 deadLink = false;
421 }
422 }
423
424 if (deadLink)
425 {
426 for (Lane lane : realLinkTag.lanes.values())
427 {
428 Double smallest = Math.min(10, lane.getLength().getInUnit(LengthUnit.METER) - 1);
429 Length beforeEnd = new Length(smallest, LengthUnit.METER);
430 Length pos = lane.getLength().minus(beforeEnd);
431 SinkSensor sensor = new SinkSensor(lane, pos, simulator);
432 lane.getSensors().add(sensor);
433 }
434 }
435 }
436
437 }
438
439 }