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 =
182 new CrossSectionLink(parser.getNetwork(), linkTag.name, linkTag.nodeStartTag.node, linkTag.nodeEndTag.node,
183 parser.network.getLinkType(LinkType.DEFAULTS.ROAD), designLine, linkTag.laneKeepingPolicy);
184 linkTag.link = link;
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198 @SuppressWarnings({"checkstyle:needbraces", "checkstyle:methodlength"})
199 static void applyRoadTypeToLink(final LinkTag linkTag, final VissimNetworkLaneParser parser,
200 final DEVSSimulatorInterface.TimeDoubleUnit simulator)
201 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
202 {
203 CrossSectionLink csl = linkTag.link;
204
205 List<CrossSectionElement> cseList = new ArrayList<>();
206 List<Lane> lanes = new ArrayList<>();
207
208 LongitudinalDirectionality linkDirection = LongitudinalDirectionality.DIR_NONE;
209
210
211
212
213 Double roadWidth = 0.0;
214 for (LaneTag laneTag : linkTag.laneTags.values())
215 {
216 roadWidth += Double.parseDouble(laneTag.width);
217 }
218
219 Color color;
220 if (linkTag.connector)
221 {
222 color = Color.LIGHT_GRAY;
223 }
224 else
225 {
226 color = Color.DARK_GRAY;
227
228 }
229
230
231 Double totalLaneWidth = 0.0;
232
233 if (!linkTag.connector)
234 {
235 for (LaneTag laneTag : linkTag.laneTags.values())
236 {
237 String name = laneTag.laneNo;
238 Double laneWidth = Double.parseDouble(laneTag.width);
239 Length thisLaneWidth = new Length(laneWidth, LengthUnit.METER);
240
241
242
243
244 Double negativeOffset = -(0.5 * roadWidth - totalLaneWidth - laneWidth / 2);
245 Length lateralOffset = new Length(negativeOffset, LengthUnit.METER);
246
247 LaneType laneType = parser.network.getLaneType(LaneType.DEFAULTS.FREEWAY);
248 Speed speedLimit = new Speed(Double.parseDouble(linkTag.legalSpeed), SpeedUnit.KM_PER_HOUR);
249
250 Lane lane = new Lane(csl, name, lateralOffset, thisLaneWidth, laneType, speedLimit);
251 if (!linkTag.sensors.isEmpty())
252 {
253 for (SensorTag sensorTag : linkTag.sensors)
254 {
255 if (sensorTag.laneName.equals(laneTag.laneNo))
256 {
257 Length pos = new Length(Double.parseDouble(sensorTag.positionStr), LengthUnit.METER);
258 if (pos.lt(lane.getLength()))
259 {
260 try
261 {
262 new SimpleReportingSensor(sensorTag.laneName + ".S" + sensorTag.name, lane, pos,
263 RelativePosition.FRONT, simulator, Compatible.EVERYTHING);
264 }
265 catch (Exception exception)
266 {
267 System.err.println(exception.getMessage());
268 }
269 }
270 }
271 }
272 }
273
274 if (!linkTag.signalHeads.isEmpty())
275 {
276 for (SignalHeadTag signalHeadTag : linkTag.signalHeads)
277 {
278 if (signalHeadTag.laneName.equals(laneTag.laneNo))
279 {
280 Length pos = new Length(Double.parseDouble(signalHeadTag.positionStr), LengthUnit.METER);
281 if (pos.lt(lane.getLength()))
282 {
283 new SimpleTrafficLight(signalHeadTag.no, lane, pos, simulator);
284 }
285 }
286 }
287 }
288
289 cseList.add(lane);
290
291 lanes.add(lane);
292 linkTag.lanes.put(name, lane);
293
294 totalLaneWidth += Double.parseDouble(laneTag.width);
295
296
297 }
298 }
299
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313 @SuppressWarnings({"checkstyle:needbraces", "checkstyle:methodlength"})
314 static void applyRoadTypeToConnector(final LinkTag linkTag, final VissimNetworkLaneParser parser,
315 final DEVSSimulatorInterface.TimeDoubleUnit simulator)
316 throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
317 {
318 CrossSectionLink csl = linkTag.link;
319
320 List<CrossSectionElement> cseList = new ArrayList<>();
321 List<Lane> lanes = new ArrayList<>();
322
323
324
325
326 Double roadWidth = 0.0;
327 for (LaneTag laneTag : linkTag.laneTags.values())
328 {
329 roadWidth += Double.parseDouble(laneTag.width);
330 }
331
332 Color color;
333 if (linkTag.connector)
334 {
335 color = Color.LIGHT_GRAY;
336 }
337 else
338 {
339 color = Color.DARK_GRAY;
340
341 }
342
343
344 LaneType laneType = parser.network.getLaneType(LaneType.DEFAULTS.FREEWAY);
345 Speed speedLimit = new Speed(Double.parseDouble(linkTag.legalSpeed), SpeedUnit.KM_PER_HOUR);
346
347
348
349 if (linkTag.connector)
350 {
351 Double totalFromLaneWidth = -1.75;
352 Double totalToLaneWidth = -1.75;
353
354 LinkTag linkToTag = parser.getRealLinkTags().get(linkTag.connectorTag.toLinkNo);
355 Lane laneTo = linkToTag.lanes.get(linkTag.connectorTag.toLaneNo);
356
357
358 LinkTag linkFromTag = parser.getRealLinkTags().get(linkTag.connectorTag.fromLinkNo);
359 Lane laneFrom = linkFromTag.lanes.get(linkTag.connectorTag.fromLaneNo);
360
361
362 for (LaneTag connectLaneTag : linkTag.laneTags.values())
363 {
364
365 String name = connectLaneTag.laneNo;
366
367 Length thisLaneWidth = new Length(Double.parseDouble(connectLaneTag.width), LengthUnit.METER);
368
369 Length totfromLaneWidth = new Length(totalFromLaneWidth, LengthUnit.METER);
370 Length totToLaneWidth = new Length(totalToLaneWidth, LengthUnit.METER);
371
372 Length lateralOffsetStart;
373 Length lateralOffsetEnd =
374 laneTo.getLateralBoundaryPosition(LateralDirectionality.RIGHT, 0).plus(totToLaneWidth);
375
376 if (laneFrom != null)
377 {
378 lateralOffsetStart =
379 laneFrom.getLateralBoundaryPosition(LateralDirectionality.RIGHT, 0).plus(totfromLaneWidth);
380 }
381 else
382 {
383 lateralOffsetStart = lateralOffsetEnd;
384 }
385
386
387
388 Lane lane = new Lane(csl, name, lateralOffsetStart, lateralOffsetEnd, thisLaneWidth, thisLaneWidth, laneType,
389 speedLimit);
390 cseList.add(lane);
391 lanes.add(lane);
392 linkTag.lanes.put(name, lane);
393
394
395 totalFromLaneWidth += Double.parseDouble(connectLaneTag.width);
396 totalToLaneWidth += Double.parseDouble(connectLaneTag.width);
397
398
399
400 }
401 }
402
403 }
404
405
406
407
408
409
410
411 public static void createSinkSensor(LinkTag realLinkTag, VissimNetworkLaneParser vissimNetworkLaneParser,
412 DEVSSimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
413 {
414 if (!realLinkTag.connector)
415 {
416 boolean deadLink = true;
417 for (LinkTag linkTag : vissimNetworkLaneParser.getLinkTags().values())
418 {
419 if (realLinkTag.nodeEndTag.name.equals(linkTag.nodeStartTag.name) && !realLinkTag.equals(linkTag))
420 {
421 deadLink = false;
422 }
423 }
424
425 if (deadLink)
426 {
427 for (Lane lane : realLinkTag.lanes.values())
428 {
429 Double smallest = Math.min(10, lane.getLength().getInUnit(LengthUnit.METER) - 1);
430 Length beforeEnd = new Length(smallest, LengthUnit.METER);
431 Length pos = lane.getLength().minus(beforeEnd);
432 SinkSensor sensor = new SinkSensor(lane, pos, Compatible.EVERYTHING, simulator);
433 lane.getSensors().add(sensor);
434 }
435 }
436 }
437
438 }
439
440 }