1   package org.opentrafficsim.road.network.factory.vissim;
2   
3   import java.awt.Color;
4   import java.util.ArrayList;
5   import java.util.HashSet;
6   import java.util.List;
7   import java.util.Set;
8   
9   import javax.naming.NamingException;
10  
11  import org.djunits.unit.AngleUnit;
12  import org.djunits.unit.DirectionUnit;
13  import org.djunits.unit.LengthUnit;
14  import org.djunits.unit.SpeedUnit;
15  import org.djunits.value.AngleUtil;
16  import org.djunits.value.vdouble.scalar.Angle;
17  import org.djunits.value.vdouble.scalar.Direction;
18  import org.djunits.value.vdouble.scalar.Length;
19  import org.djunits.value.vdouble.scalar.Speed;
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.RelativePosition;
28  import org.opentrafficsim.core.network.LateralDirectionality;
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.road.network.factory.vissim.ArcTag.ArcDirection;
33  import org.opentrafficsim.road.network.lane.CrossSectionElement;
34  import org.opentrafficsim.road.network.lane.CrossSectionLink;
35  import org.opentrafficsim.road.network.lane.Lane;
36  import org.opentrafficsim.road.network.lane.LaneType;
37  import org.opentrafficsim.road.network.lane.object.sensor.SimpleReportingSensor;
38  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
39  import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
40  import org.xml.sax.SAXException;
41  
42  import nl.tudelft.simulation.dsol.SimRuntimeException;
43  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
44  import nl.tudelft.simulation.language.d3.CartesianPoint;
45  import nl.tudelft.simulation.language.d3.DirectedPoint;
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  final class Links
57  {
58      
59      private Links()
60      {
61          
62      }
63  
64      
65  
66  
67  
68  
69  
70      @SuppressWarnings("methodlength")
71      static void calculateNodeCoordinates(final VissimNetworkLaneParser parser) throws NetworkException, NamingException
72      {
73          
74          for (LinkTag linkTag : parser.getLinkTags().values())
75          {
76              if (linkTag.straightTag != null && linkTag.nodeStartTag.coordinate != null && linkTag.nodeEndTag.coordinate != null)
77              {
78                  if (linkTag.nodeStartTag.angle == null)
79                  {
80                      double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
81                      double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
82                      linkTag.nodeStartTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
83                  }
84                  if (linkTag.nodeEndTag.angle == null)
85                  {
86                      double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
87                      double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
88                      linkTag.nodeEndTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
89                  }
90              }
91          }
92  
93          
94          Set<NodeTag> nodeTags = new HashSet<>();
95          for (LinkTag linkTag : parser.getLinkTags().values())
96          {
97  
98              if (linkTag.nodeStartTag.coordinate == null)
99              {
100                 nodeTags.add(linkTag.nodeStartTag);
101             }
102             if (linkTag.nodeEndTag.coordinate == null)
103             {
104                 nodeTags.add(linkTag.nodeEndTag);
105             }
106         }
107 
108         while (nodeTags.size() > 0)
109         {
110             boolean found = false;
111             for (LinkTag linkTag : parser.getLinkTags().values())
112             {
113                 if (linkTag.straightTag != null || linkTag.polyLineTag != null || linkTag.arcTag != null)
114                 {
115                     if (nodeTags.contains(linkTag.nodeStartTag) == nodeTags.contains(linkTag.nodeEndTag))
116                     {
117                         continue;
118                     }
119 
120                     if (linkTag.straightTag != null)
121                     {
122                         double lengthSI = linkTag.straightTag.length.getSI();
123                         if (linkTag.nodeEndTag.node == null)
124                         {
125                             CartesianPoint coordinate = new CartesianPoint(linkTag.nodeStartTag.node.getLocation().getX(),
126                                     linkTag.nodeStartTag.node.getLocation().getY(),
127                                     linkTag.nodeStartTag.node.getLocation().getZ());
128                             double angle = linkTag.nodeStartTag.node.getDirection().getInUnit();
129                             double slope = linkTag.nodeStartTag.node.getSlope().getSI();
130                             coordinate.x += lengthSI * Math.cos(angle);
131                             coordinate.y += lengthSI * Math.sin(angle);
132                             coordinate.z += lengthSI * Math.sin(slope);
133                             NodeTag nodeTag = linkTag.nodeEndTag;
134                             nodeTag.angle = new Direction(angle, DirectionUnit.EAST_RADIAN);
135                             nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
136                             nodeTag.slope = new Angle(slope, AngleUnit.SI);
137                             linkTag.nodeEndTag.node = NodeTag.makeOTSNode(nodeTag, parser);
138                             nodeTags.remove(linkTag.nodeEndTag);
139                         }
140                         else if (linkTag.nodeStartTag.node == null)
141                         {
142                             CartesianPoint coordinate = new CartesianPoint(linkTag.nodeEndTag.node.getLocation().getX(),
143                                     linkTag.nodeEndTag.node.getLocation().getY(), linkTag.nodeEndTag.node.getLocation().getZ());
144                             double angle = linkTag.nodeEndTag.node.getDirection().getInUnit();
145                             double slope = linkTag.nodeEndTag.node.getSlope().getSI();
146                             coordinate.x -= lengthSI * Math.cos(angle);
147                             coordinate.y -= lengthSI * Math.sin(angle);
148                             coordinate.z -= lengthSI * Math.sin(slope);
149                             NodeTag nodeTag = linkTag.nodeStartTag;
150                             nodeTag.angle = new Direction(angle, DirectionUnit.EAST_RADIAN);
151                             nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
152                             nodeTag.slope = new Angle(slope, AngleUnit.SI);
153                             linkTag.nodeStartTag.node = NodeTag.makeOTSNode(nodeTag, parser);
154                             nodeTags.remove(linkTag.nodeStartTag);
155                         }
156                     }
157                     else if (linkTag.polyLineTag != null)
158                     {
159                         double lengthSI = linkTag.polyLineTag.length.getSI();
160                         
161                         
162                         
163                         
164                         
165                         
166                         
167                         
168                         
169                         
170                         
171                         
172                         
173                         
174                         
175                         
176                         
177                         
178                         
179                         
180                         
181                         
182                         
183                         
184                         
185                         
186                         
187                         
188                         
189                         
190                         
191                     }
192                     else if (linkTag.arcTag != null)
193                     {
194                         double radiusSI = linkTag.arcTag.radius.getSI();
195                         double angle = linkTag.arcTag.angle.getInUnit();
196                         ArcDirection direction = linkTag.arcTag.direction;
197 
198                         if (linkTag.nodeEndTag.node == null)
199                         {
200                             CartesianPoint coordinate = new CartesianPoint(0.0, 0.0, 0.0);
201                             double startAngle = linkTag.nodeStartTag.node.getDirection().getInUnit();
202                             double slope = linkTag.nodeStartTag.node.getSlope().getSI();
203                             double lengthSI = radiusSI * angle;
204                             NodeTag nodeTag = linkTag.nodeEndTag;
205                             if (direction.equals(ArcDirection.LEFT))
206                             {
207                                 linkTag.arcTag.center = new OTSPoint3D(
208                                         linkTag.nodeStartTag.node.getLocation().getX()
209                                                 + radiusSI * Math.cos(startAngle + Math.PI / 2.0),
210                                         linkTag.nodeStartTag.node.getLocation().getY()
211                                                 + radiusSI * Math.sin(startAngle + Math.PI / 2.0),
212                                         0.0);
213                                 linkTag.arcTag.startAngle = startAngle - Math.PI / 2.0;
214                                 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle + angle);
215                                 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle + angle);
216                                 nodeTag.angle =
217                                         new Direction(AngleUtil.normalize(startAngle + angle), DirectionUnit.EAST_RADIAN);
218                             }
219                             else
220                             {
221                                 linkTag.arcTag.center = new OTSPoint3D(
222                                         linkTag.nodeStartTag.node.getLocation().getX()
223                                                 - radiusSI * Math.cos(startAngle + Math.PI / 2.0),
224                                         linkTag.nodeStartTag.node.getLocation().getY()
225                                                 - radiusSI * Math.sin(startAngle + Math.PI / 2.0),
226                                         0.0);
227                                 linkTag.arcTag.startAngle = startAngle + Math.PI / 2.0;
228                                 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle - angle);
229                                 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle - angle);
230                                 nodeTag.angle =
231                                         new Direction(AngleUtil.normalize(startAngle - angle), DirectionUnit.EAST_RADIAN);
232                             }
233                             coordinate.z = linkTag.nodeStartTag.node.getLocation().getZ() + lengthSI * Math.sin(slope);
234                             nodeTag.slope = new Angle(slope, AngleUnit.SI);
235                             nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
236                             linkTag.nodeEndTag.node = NodeTag.makeOTSNode(nodeTag, parser);
237                             nodeTags.remove(linkTag.nodeEndTag);
238                         }
239 
240                         else if (linkTag.nodeStartTag.node == null)
241                         {
242                             CartesianPoint coordinate = new CartesianPoint(linkTag.nodeEndTag.node.getLocation().getX(),
243                                     linkTag.nodeEndTag.node.getLocation().getY(), linkTag.nodeEndTag.node.getLocation().getZ());
244                             double endAngle = linkTag.nodeEndTag.node.getDirection().getInUnit();
245                             double slope = linkTag.nodeEndTag.node.getSlope().getSI();
246                             double lengthSI = radiusSI * angle;
247                             NodeTag nodeTag = linkTag.nodeStartTag;
248                             if (direction.equals(ArcDirection.LEFT))
249                             {
250                                 linkTag.arcTag.center =
251                                         new OTSPoint3D(coordinate.x + radiusSI * Math.cos(endAngle + Math.PI / 2.0),
252                                                 coordinate.y + radiusSI * Math.sin(endAngle + Math.PI / 2.0), 0.0);
253                                 linkTag.arcTag.startAngle = endAngle - Math.PI / 2.0 - angle;
254                                 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle);
255                                 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle);
256                                 nodeTag.angle = new Direction(AngleUtil.normalize(linkTag.arcTag.startAngle + Math.PI / 2.0),
257                                         DirectionUnit.EAST_RADIAN);
258                             }
259                             else
260                             {
261                                 linkTag.arcTag.center =
262                                         new OTSPoint3D(coordinate.x + radiusSI * Math.cos(endAngle - Math.PI / 2.0),
263                                                 coordinate.y + radiusSI * Math.sin(endAngle - Math.PI / 2.0), 0.0);
264                                 linkTag.arcTag.startAngle = endAngle + Math.PI / 2.0 + angle;
265                                 coordinate.x = linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle);
266                                 coordinate.y = linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle);
267                                 nodeTag.angle = new Direction(AngleUtil.normalize(linkTag.arcTag.startAngle - Math.PI / 2.0),
268                                         DirectionUnit.EAST_RADIAN);
269                             }
270                             coordinate.z -= lengthSI * Math.sin(slope);
271                             nodeTag.coordinate = new OTSPoint3D(coordinate.x, coordinate.y, coordinate.z);
272                             nodeTag.slope = new Angle(slope, AngleUnit.SI);
273                             linkTag.nodeStartTag.node = NodeTag.makeOTSNode(nodeTag, parser);
274                             nodeTags.remove(linkTag.nodeStartTag);
275                         }
276                     }
277                 }
278             }
279             if (!found)
280             {
281                 throw new NetworkException("Cannot find coordinates of one or more nodes");
282             }
283         }
284 
285         
286         for (LinkTag linkTag : parser.getLinkTags().values())
287         {
288             if (linkTag.straightTag != null && linkTag.nodeStartTag.coordinate != null && linkTag.nodeEndTag.coordinate != null)
289             {
290                 double dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
291                 double dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
292                 linkTag.nodeStartTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
293                 dx = linkTag.nodeEndTag.coordinate.x - linkTag.nodeStartTag.coordinate.x;
294                 dy = linkTag.nodeEndTag.coordinate.y - linkTag.nodeStartTag.coordinate.y;
295                 linkTag.nodeEndTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
296             }
297         }
298 
299         
300 
301         for (LinkTag linkTag : parser.getLinkTags().values())
302         {
303             if (linkTag.polyLineTag != null && linkTag.nodeStartTag.coordinate != null && linkTag.nodeEndTag.coordinate != null)
304             {
305                 double dx = linkTag.polyLineTag.vertices[0].x - linkTag.nodeStartTag.coordinate.x;
306                 double dy = linkTag.polyLineTag.vertices[0].y - linkTag.nodeStartTag.coordinate.y;
307                 linkTag.nodeStartTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
308                 int arrayLength = linkTag.polyLineTag.vertices.length;
309                 dx = linkTag.nodeEndTag.coordinate.x - linkTag.polyLineTag.vertices[arrayLength - 1].x;
310                 dy = linkTag.nodeEndTag.coordinate.y - linkTag.polyLineTag.vertices[arrayLength - 1].y;
311                 linkTag.nodeEndTag.angle = new Direction(Math.atan2(dy, dx), DirectionUnit.EAST_RADIAN);
312             }
313         }
314 
315         
316         for (NodeTag nodeTag : parser.getNodeTags().values())
317         {
318             if (nodeTag.coordinate != null && nodeTag.node == null)
319             {
320                 if (nodeTag.angle == null)
321                 {
322                     nodeTag.angle = Direction.ZERO;
323                 }
324                 if (nodeTag.slope == null)
325                 {
326                     nodeTag.slope = Angle.ZERO;
327                 }
328                 nodeTag.node = NodeTag.makeOTSNode(nodeTag, parser);
329             }
330         }
331 
332     }
333 
334     
335 
336 
337 
338 
339 
340 
341 
342 
343     static void buildLink(final LinkTag linkTag, final VissimNetworkLaneParser parser, final OTSSimulatorInterface simulator)
344             throws OTSGeometryException, NamingException, NetworkException
345     {
346         NodeTag from = linkTag.nodeStartTag;
347         OTSPoint3D startPoint = new OTSPoint3D(from.coordinate);
348         double startAngle = 0.0;
349         if (from.angle != null)
350         {
351             startAngle = from.angle.getInUnit();
352         }
353         if (linkTag.offsetStart != null && linkTag.offsetStart.si != 0.0)
354         {
355             
356             double offset = linkTag.offsetStart.si;
357             startPoint = new OTSPoint3D(startPoint.x + offset * Math.cos(startAngle + Math.PI / 2.0),
358                     startPoint.y + offset * Math.sin(startAngle + Math.PI / 2.0), startPoint.z);
359             System.out
360                     .println("fc = " + from.coordinate + ", sa = " + startAngle + ", so = " + offset + ", sp = " + startPoint);
361         }
362 
363         NodeTag to = linkTag.nodeEndTag;
364         OTSPoint3D endPoint = new OTSPoint3D(to.coordinate);
365         double endAngle = to.angle.getInUnit();
366         if (linkTag.offsetEnd != null && linkTag.offsetEnd.si != 0.0)
367         {
368             
369             double offset = linkTag.offsetEnd.si;
370             endPoint = new OTSPoint3D(endPoint.x + offset * Math.cos(endAngle + Math.PI / 2.0),
371                     endPoint.y + offset * Math.sin(endAngle + Math.PI / 2.0), endPoint.z);
372             System.out.println("tc = " + to.coordinate + ", ea = " + endAngle + ", eo = " + offset + ", ep = " + endPoint);
373         }
374 
375         OTSPoint3D[] coordinates = null;
376 
377         if (linkTag.straightTag != null)
378         {
379             coordinates = new OTSPoint3D[2];
380             coordinates[0] = startPoint;
381             coordinates[1] = endPoint;
382         }
383 
384         else if (linkTag.polyLineTag != null)
385         {
386             int intermediatePoints = linkTag.polyLineTag.vertices.length;
387             coordinates = new OTSPoint3D[intermediatePoints + 2];
388             coordinates[0] = startPoint;
389             coordinates[intermediatePoints + 1] = endPoint;
390             for (int p = 0; p < intermediatePoints; p++)
391             {
392                 coordinates[p + 1] = linkTag.polyLineTag.vertices[p];
393             }
394 
395         }
396         else if (linkTag.arcTag != null)
397         {
398             
399             int points = (Math.abs(linkTag.arcTag.angle.getInUnit()) <= Math.PI / 2.0) ? 64 : 128;
400             coordinates = new OTSPoint3D[points];
401             coordinates[0] = new OTSPoint3D(from.coordinate.x, from.coordinate.y, from.coordinate.z);
402             coordinates[coordinates.length - 1] = new OTSPoint3D(to.coordinate.x, to.coordinate.y, to.coordinate.z);
403             double angleStep = linkTag.arcTag.angle.getInUnit() / points;
404             double slopeStep = (to.coordinate.z - from.coordinate.z) / points;
405             double radiusSI = linkTag.arcTag.radius.getSI();
406             if (linkTag.arcTag.direction.equals(ArcDirection.RIGHT))
407             {
408                 for (int p = 1; p < points - 1; p++)
409                 {
410                     coordinates[p] = new OTSPoint3D(
411                             linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle - angleStep * p),
412                             linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle - angleStep * p),
413                             from.coordinate.z + slopeStep * p);
414                 }
415             }
416             else
417             {
418                 for (int p = 1; p < points - 1; p++)
419                 {
420                     try
421                     {
422                         System.err.println("linkTag.arcTag.center = " + linkTag.arcTag.center);
423                         System.err.println("linkTag.arcTag.startAngle = " + linkTag.arcTag.startAngle);
424                         coordinates[p] = new OTSPoint3D(
425                                 linkTag.arcTag.center.x + radiusSI * Math.cos(linkTag.arcTag.startAngle + angleStep * p),
426                                 linkTag.arcTag.center.y + radiusSI * Math.sin(linkTag.arcTag.startAngle + angleStep * p),
427                                 from.coordinate.z + slopeStep * p);
428                     }
429                     catch (NullPointerException npe)
430                     {
431                         npe.printStackTrace();
432                         System.err.println(npe.getMessage());
433                     }
434                 }
435             }
436         }
437 
438         else if (linkTag.bezierTag != null)
439         {
440             if (new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle)
441                     .equals(new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle)))
442             {
443                 System.out.println("   ");
444             }
445 
446             coordinates = Bezier.cubic(128, new DirectedPoint(startPoint.x, startPoint.y, startPoint.z, 0, 0, startAngle),
447                     new DirectedPoint(endPoint.x, endPoint.y, endPoint.z, 0, 0, endAngle)).getPoints();
448         }
449 
450         else
451         {
452             throw new NetworkException(
453                     "Making link, but link " + linkTag.name + " has no filled straight, arc, or bezier curve");
454         }
455         if (coordinates.length < 2)
456         {
457             throw new OTSGeometryException(
458                     "Degenerate OTSLine3D; has " + coordinates.length + " point" + (coordinates.length != 1 ? "s" : ""));
459         }
460         OTSLine3D designLine = OTSLine3D.createAndCleanOTSLine3D(coordinates);
461 
462         
463         CrossSectionLink link = new CrossSectionLink(parser.getNetwork(), linkTag.name, linkTag.nodeStartTag.node,
464                 linkTag.nodeEndTag.node, LinkType.ROAD, designLine, simulator, linkTag.laneKeepingPolicy);
465         linkTag.link = link;
466     }
467 
468     
469 
470 
471 
472 
473 
474 
475 
476 
477 
478 
479     @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:methodlength" })
480     static void applyRoadTypeToLink(final LinkTag linkTag, final VissimNetworkLaneParser parser,
481             final DEVSSimulatorInterface.TimeDoubleUnit simulator)
482             throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
483     {
484         CrossSectionLink csl = linkTag.link;
485 
486         List<CrossSectionElement> cseList = new ArrayList<>();
487         List<Lane> lanes = new ArrayList<>();
488         
489         LongitudinalDirectionality linkDirection = LongitudinalDirectionality.DIR_NONE;
490 
491         
492         
493         
494         Double roadWidth = 0.0;
495         for (LaneTag laneTag : linkTag.laneTags.values())
496         {
497             roadWidth += Double.parseDouble(laneTag.width);
498         }
499 
500         Color color;
501         if (linkTag.connector)
502         {
503             color = Color.LIGHT_GRAY;
504         }
505         else
506         {
507             color = Color.DARK_GRAY;
508 
509         }
510 
511         
512         Double totalLaneWidth = 0.0;
513 
514         if (!linkTag.connector)
515         {
516             for (LaneTag laneTag : linkTag.laneTags.values())
517             {
518                 String name = laneTag.laneNo;
519                 Double laneWidth = Double.parseDouble(laneTag.width);
520                 Length thisLaneWidth = new Length(laneWidth, LengthUnit.METER);
521 
522                 
523                 
524                 
525                 Double negativeOffset = -(0.5 * roadWidth - totalLaneWidth - laneWidth / 2);
526                 Length lateralOffset = new Length(negativeOffset, LengthUnit.METER);
527 
528                 LaneType laneType = LaneType.FREEWAY;
529                 Speed speedLimit = new Speed(Double.parseDouble(linkTag.legalSpeed), SpeedUnit.KM_PER_HOUR);
530                 
531                 Lane lane = new Lane(csl, name, lateralOffset, thisLaneWidth, laneType, speedLimit, null);
532                 if (!linkTag.sensors.isEmpty())
533                 {
534                     for (SensorTag sensorTag : linkTag.sensors)
535                     {
536                         if (sensorTag.laneName.equals(laneTag.laneNo))
537                         {
538                             Length pos = new Length(Double.parseDouble(sensorTag.positionStr), LengthUnit.METER);
539                             if (pos.lt(lane.getLength()))
540                             {
541                                 try
542                                 {
543                                     new SimpleReportingSensor(sensorTag.laneName + ".S" + sensorTag.name, lane, pos,
544                                             RelativePosition.FRONT, simulator, Compatible.EVERYTHING);
545                                 }
546                                 catch (Exception exception)
547                                 {
548                                     System.err.println(exception.getMessage());
549                                 }
550                             }
551                         }
552                     }
553                 }
554 
555                 if (!linkTag.signalHeads.isEmpty())
556                 {
557                     for (SignalHeadTag signalHeadTag : linkTag.signalHeads)
558                     {
559                         if (signalHeadTag.laneName.equals(laneTag.laneNo))
560                         {
561                             Length pos = new Length(Double.parseDouble(signalHeadTag.positionStr), LengthUnit.METER);
562                             if (pos.lt(lane.getLength()))
563                             {
564                                 new SimpleTrafficLight(signalHeadTag.no, lane, pos, simulator);
565                             }
566                         }
567                     }
568                 }
569 
570                 cseList.add(lane);
571 
572                 lanes.add(lane);
573                 linkTag.lanes.put(name, lane);
574                 
575                 totalLaneWidth += Double.parseDouble(laneTag.width);
576 
577                 
578             }
579         }
580 
581     }
582 
583     
584 
585 
586 
587 
588 
589 
590 
591 
592 
593 
594     @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:methodlength" })
595     static void applyRoadTypeToConnector(final LinkTag linkTag, final VissimNetworkLaneParser parser,
596             final DEVSSimulatorInterface.TimeDoubleUnit simulator)
597             throws NetworkException, NamingException, SAXException, GTUException, OTSGeometryException, SimRuntimeException
598     {
599         CrossSectionLink csl = linkTag.link;
600 
601         List<CrossSectionElement> cseList = new ArrayList<>();
602         List<Lane> lanes = new ArrayList<>();
603 
604         
605         
606         
607         Double roadWidth = 0.0;
608         for (LaneTag laneTag : linkTag.laneTags.values())
609         {
610             roadWidth += Double.parseDouble(laneTag.width);
611         }
612 
613         Color color;
614         if (linkTag.connector)
615         {
616             color = Color.LIGHT_GRAY;
617         }
618         else
619         {
620             color = Color.DARK_GRAY;
621 
622         }
623 
624         
625         LaneType laneType = LaneType.FREEWAY;
626         Speed speedLimit = new Speed(Double.parseDouble(linkTag.legalSpeed), SpeedUnit.KM_PER_HOUR);
627 
628         
629         
630         if (linkTag.connector)
631         {
632             Double totalFromLaneWidth = -1.75;
633             Double totalToLaneWidth = -1.75;
634             
635             LinkTag linkToTag = parser.getRealLinkTags().get(linkTag.connectorTag.toLinkNo);
636             Lane laneTo = linkToTag.lanes.get(linkTag.connectorTag.toLaneNo);
637 
638             
639             LinkTag linkFromTag = parser.getRealLinkTags().get(linkTag.connectorTag.fromLinkNo);
640             Lane laneFrom = linkFromTag.lanes.get(linkTag.connectorTag.fromLaneNo);
641 
642             
643             for (LaneTag connectLaneTag : linkTag.laneTags.values())
644             {
645                 
646                 String name = connectLaneTag.laneNo;
647                 
648                 Length thisLaneWidth = new Length(Double.parseDouble(connectLaneTag.width), LengthUnit.METER);
649                 
650                 Length totfromLaneWidth = new Length(totalFromLaneWidth, LengthUnit.METER);
651                 Length totToLaneWidth = new Length(totalToLaneWidth, LengthUnit.METER);
652 
653                 Length lateralOffsetStart;
654                 Length lateralOffsetEnd =
655                         laneTo.getLateralBoundaryPosition(LateralDirectionality.RIGHT, 0).plus(totToLaneWidth);
656                 
657                 if (laneFrom != null)
658                 {
659                     lateralOffsetStart =
660                             laneFrom.getLateralBoundaryPosition(LateralDirectionality.RIGHT, 0).plus(totfromLaneWidth);
661                 }
662                 else
663                 {
664                     lateralOffsetStart = lateralOffsetEnd;
665                 }
666 
667                 
668                 
669                 Lane lane = new Lane(csl, name, lateralOffsetStart, lateralOffsetEnd, thisLaneWidth, thisLaneWidth, laneType,
670                         speedLimit, null);
671                 cseList.add(lane);
672                 lanes.add(lane);
673                 linkTag.lanes.put(name, lane);
674 
675                 
676                 totalFromLaneWidth += Double.parseDouble(connectLaneTag.width);
677                 totalToLaneWidth += Double.parseDouble(connectLaneTag.width);
678 
679                 
680 
681             }
682         }
683 
684     }
685 
686     
687 
688 
689 
690 
691 
692     public static void createSinkSensor(LinkTag realLinkTag, VissimNetworkLaneParser vissimNetworkLaneParser,
693             DEVSSimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
694     {
695         if (!realLinkTag.connector)
696         {
697             boolean deadLink = true;
698             for (LinkTag linkTag : vissimNetworkLaneParser.getLinkTags().values())
699             {
700                 if (realLinkTag.nodeEndTag.name.equals(linkTag.nodeStartTag.name) && !realLinkTag.equals(linkTag))
701                 {
702                     deadLink = false;
703                 }
704             }
705 
706             if (deadLink)
707             {
708                 for (Lane lane : realLinkTag.lanes.values())
709                 {
710                     Double smallest = Math.min(10, lane.getLength().getInUnit(LengthUnit.METER) - 1);
711                     Length beforeEnd = new Length(smallest, LengthUnit.METER);
712                     Length pos = lane.getLength().minus(beforeEnd);
713                     SinkSensor sensor = new SinkSensor(lane, pos, simulator);
714                     lane.getSensors().add(sensor);
715                 }
716             }
717         }
718 
719     }
720 
721 }