View Javadoc
1   package org.opentrafficsim.road.network.factory;
2   
3   import java.awt.Color;
4   import java.rmi.RemoteException;
5   import java.util.ArrayList;
6   import java.util.Arrays;
7   import java.util.LinkedHashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  import javax.naming.NamingException;
12  
13  import nl.tudelft.simulation.language.d3.DirectedPoint;
14  
15  import org.djunits.unit.LengthUnit;
16  import org.djunits.value.vdouble.scalar.Length;
17  import org.djunits.value.vdouble.scalar.Speed;
18  import org.opentrafficsim.core.dsol.OTSAnimatorInterface;
19  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
20  import org.opentrafficsim.core.geometry.Bezier;
21  import org.opentrafficsim.core.geometry.OTSGeometryException;
22  import org.opentrafficsim.core.geometry.OTSLine3D;
23  import org.opentrafficsim.core.geometry.OTSPoint3D;
24  import org.opentrafficsim.core.gtu.GTUType;
25  import org.opentrafficsim.core.network.LinkType;
26  import org.opentrafficsim.core.network.LongitudinalDirectionality;
27  import org.opentrafficsim.core.network.Network;
28  import org.opentrafficsim.core.network.NetworkException;
29  import org.opentrafficsim.core.network.Node;
30  import org.opentrafficsim.core.network.OTSNode;
31  import org.opentrafficsim.road.network.animation.LaneAnimation;
32  import org.opentrafficsim.road.network.lane.CrossSectionLink;
33  import org.opentrafficsim.road.network.lane.Lane;
34  import org.opentrafficsim.road.network.lane.LaneType;
35  import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
36  import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
37  
38  /**
39   * <p>
40   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
41   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
42   * <p>
43   * $LastChangedDate: 2015-09-16 19:20:07 +0200 (Wed, 16 Sep 2015) $, @version $Revision: 1405 $, by $Author: averbraeck $,
44   * initial version 30 okt. 2014 <br>
45   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
46   */
47  public final class LaneFactory
48  {
49      /** Do not instantiate this class. */
50      private LaneFactory()
51      {
52          // Cannot be instantiated.
53      }
54  
55      /**
56       * Create a Link along intermediate coordinates from one Node to another.
57       * @param network the network
58       * @param name String; name of the new Link
59       * @param from Node; start Node of the new Link
60       * @param to Node; end Node of the new Link
61       * @param intermediatePoints OTSPoint3D[]; array of intermediate coordinates (may be null); the intermediate points may
62       *            contain the coordinates of the from node and to node
63       * @param direction the direction of the link
64       * @return Link; the newly constructed Link
65       * @throws OTSGeometryException when the design line is degenerate (only one point or duplicate point)
66       * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
67       *             or the end node of the link are not registered in the network.
68       */
69      public static CrossSectionLink makeLink(final Network network, final String name, final Node from, final Node to,
70              final OTSPoint3D[] intermediatePoints, final LongitudinalDirectionality direction)
71              throws OTSGeometryException, NetworkException
72      {
73          List<OTSPoint3D> pointList = intermediatePoints == null ? new ArrayList<OTSPoint3D>()
74                  : new ArrayList<OTSPoint3D>(Arrays.asList(intermediatePoints));
75          if (pointList.size() == 0 || !from.getPoint().equals(pointList.get(0)))
76          {
77              pointList.add(0, from.getPoint());
78          }
79          if (pointList.size() == 0 || !to.getPoint().equals(pointList.get(pointList.size() - 1)))
80          {
81              pointList.add(to.getPoint());
82          }
83  
84          /*-
85          // see if an intermediate point needs to be created to the start of the link in the right direction
86          OTSPoint3D s1 = pointList.get(0);
87          OTSPoint3D s2 = pointList.get(1);
88          double dy = s2.y - s1.y;
89          double dx = s2.x - s1.x;
90          double a = from.getLocation().getRotZ();
91          if (Math.abs(a - Math.atan2(dy, dx)) > 1E-6)
92          {
93              double r = Math.min(1.0, Math.sqrt(dy * dy + dx * dx) / 4.0); 
94              OTSPoint3D extra = new OTSPoint3D(s1.x + r * Math.cos(a), s1.y + r * Math.sin(a), s1.z);
95              pointList.add(1, extra);
96          }
97          
98          // see if an intermediate point needs to be created to the end of the link in the right direction
99          s1 = pointList.get(pointList.size() - 2);
100         s2 = pointList.get(pointList.size() - 1);
101         dy = s2.y - s1.y;
102         dx = s2.x - s1.x;
103         a = to.getLocation().getRotZ() - Math.PI;
104         if (Math.abs(a - Math.atan2(dy, dx)) > 1E-6)
105         {
106             double r = Math.min(1.0, Math.sqrt(dy * dy + dx * dx) / 4.0); 
107             OTSPoint3D extra = new OTSPoint3D(s2.x + r * Math.cos(a), s2.y + r * Math.sin(a), s2.z);
108             pointList.add(pointList.size() - 2, extra);
109         }
110          */
111 
112         OTSLine3D designLine = new OTSLine3D(pointList);
113         CrossSectionLink link = new CrossSectionLink(network, name, from, to, LinkType.ALL, designLine, direction,
114                 LaneKeepingPolicy.KEEP_RIGHT);
115         return link;
116     }
117 
118     /**
119      * Create one Lane.
120      * @param link Link; the link that owns the new Lane
121      * @param id String; the id of this lane, should be unique within the link
122      * @param laneType LaneType&lt;String&gt;; the type of the new Lane
123      * @param latPosAtStart Length; the lateral position of the new Lane with respect to the design line of the link at the
124      *            start of the link
125      * @param latPosAtEnd Length; the lateral position of the new Lane with respect to the design line of the link at the end of
126      *            the link
127      * @param width Length; the width of the new Lane
128      * @param speedLimit Speed; the speed limit on the new Lane
129      * @param simulator OTSDEVSSimulatorInterface; the simulator
130      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
131      * @return Lane
132      * @throws NamingException when names cannot be registered for animation
133      * @throws NetworkException on network inconsistency
134      * @throws OTSGeometryException when creation of center line or contour fails
135      */
136     @SuppressWarnings("checkstyle:parameternumber")
137     private static Lane makeLane(final CrossSectionLink link, final String id, final LaneType laneType,
138             final Length latPosAtStart, final Length latPosAtEnd, final Length width, final Speed speedLimit,
139             final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction)
140             throws NamingException, NetworkException, OTSGeometryException
141     {
142         Map<GTUType, LongitudinalDirectionality> directionalityMap = new LinkedHashMap<>();
143         directionalityMap.put(GTUType.ALL, direction);
144         Map<GTUType, Speed> speedMap = new LinkedHashMap<>();
145         speedMap.put(GTUType.ALL, speedLimit);
146         Lane result = new Lane(link, id, latPosAtStart, latPosAtEnd, width, width, laneType, directionalityMap, speedMap,
147                 new OvertakingConditions.LeftAndRight());
148         if (simulator instanceof OTSAnimatorInterface)
149         {
150             try
151             {
152                 new LaneAnimation(result, simulator, Color.LIGHT_GRAY, false);
153             }
154             catch (RemoteException exception)
155             {
156                 exception.printStackTrace();
157             }
158         }
159         return result;
160     }
161 
162     /**
163      * Create a simple Lane.
164      * @param network the network
165      * @param name String; name of the Lane (and also of the Link that owns it)
166      * @param from Node; starting node of the new Lane
167      * @param to Node; ending node of the new Lane
168      * @param intermediatePoints OTSPoint3D[]; intermediate coordinates or null to create a straight road; the intermediate
169      *            points may contain the coordinates of the from node and to node
170      * @param laneType LaneType; type of the new Lane
171      * @param speedLimit Speed; the speed limit on the new Lane
172      * @param simulator OTSDEVSSimulatorInterface; the simulator
173      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
174      * @return Lane; the new Lane
175      * @throws NamingException when names cannot be registered for animation
176      * @throws NetworkException on network inconsistency
177      * @throws OTSGeometryException when creation of center line or contour fails
178      */
179     public static Lane makeLane(final Network network, final String name, final OTSNode from, final OTSNode to,
180             final OTSPoint3D[] intermediatePoints, final LaneType laneType, final Speed speedLimit,
181             final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction)
182             throws NamingException, NetworkException, OTSGeometryException
183     {
184         Length width = new Length(4.0, LengthUnit.METER);
185         final CrossSectionLink link = makeLink(network, name, from, to, intermediatePoints, direction);
186         Length latPos = new Length(0.0, LengthUnit.METER);
187         return makeLane(link, "lane", laneType, latPos, latPos, width, speedLimit, simulator, direction);
188     }
189 
190     /**
191      * Create a simple road with the specified number of Lanes.<br>
192      * This method returns an array of Lane. These lanes are embedded in a Link that can be accessed through the getParentLink
193      * method of the Lane.
194      * @param network the network
195      * @param name String; name of the Link
196      * @param from Node; starting node of the new Lane
197      * @param to Node; ending node of the new Lane
198      * @param intermediatePoints OTSPoint3D[]; intermediate coordinates or null to create a straight road; the intermediate
199      *            points may contain the coordinates of the from node and to node
200      * @param laneCount int; number of lanes in the road
201      * @param laneOffsetAtStart int; extra offset from design line in lane widths at start of link
202      * @param laneOffsetAtEnd int; extra offset from design line in lane widths at end of link
203      * @param laneType LaneType; type of the new Lanes
204      * @param speedLimit Speed; the speed limit on all lanes
205      * @param simulator OTSDEVSSimulatorInterface; the simulator
206      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
207      * @return Lane&lt;String, String&gt;[]; array containing the new Lanes
208      * @throws NamingException when names cannot be registered for animation
209      * @throws NetworkException on topological problems
210      * @throws OTSGeometryException when creation of center line or contour fails
211      */
212     @SuppressWarnings("checkstyle:parameternumber")
213     public static Lane[] makeMultiLane(final Network network, final String name, final OTSNode from, final OTSNode to,
214             final OTSPoint3D[] intermediatePoints, final int laneCount, final int laneOffsetAtStart, final int laneOffsetAtEnd,
215             final LaneType laneType, final Speed speedLimit, final OTSDEVSSimulatorInterface simulator,
216             final LongitudinalDirectionality direction) throws NamingException, NetworkException, OTSGeometryException
217     {
218         final CrossSectionLink link = makeLink(network, name, from, to, intermediatePoints, direction);
219         Lane[] result = new Lane[laneCount];
220         Length width = new Length(4.0, LengthUnit.METER);
221         for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
222         {
223             // Be ware! LEFT is lateral positive, RIGHT is lateral negative.
224             Length latPosAtStart = new Length((-0.5 - laneIndex - laneOffsetAtStart) * width.getSI(), LengthUnit.SI);
225             Length latPosAtEnd = new Length((-0.5 - laneIndex - laneOffsetAtEnd) * width.getSI(), LengthUnit.SI);
226             result[laneIndex] = makeLane(link, "lane." + laneIndex, laneType, latPosAtStart, latPosAtEnd, width, speedLimit,
227                     simulator, direction);
228         }
229         return result;
230     }
231 
232     /**
233      * Create a simple road with the specified number of Lanes.<br>
234      * This method returns an array of Lane. These lanes are embedded in a Link that can be accessed through the getParentLink
235      * method of the Lane.
236      * @param network the network
237      * @param name String; name of the Link
238      * @param from Node; starting node of the new Lane
239      * @param to Node; ending node of the new Lane
240      * @param intermediatePoints OTSPoint3D[]; intermediate coordinates or null to create a straight road; the intermediate
241      *            points may contain the coordinates of the from node and to node
242      * @param laneCount int; number of lanes in the road
243      * @param laneType LaneType; type of the new Lanes
244      * @param speedLimit Speed the speed limit (applies to all generated lanes)
245      * @param simulator OTSDEVSSimulatorInterface; the simulator
246      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
247      * @return Lane&lt;String, String&gt;[]; array containing the new Lanes
248      * @throws NamingException when names cannot be registered for animation
249      * @throws NetworkException on topological problems
250      * @throws OTSGeometryException when creation of center line or contour fails
251      */
252     @SuppressWarnings("checkstyle:parameternumber")
253     public static Lane[] makeMultiLane(final Network network, final String name, final OTSNode from, final OTSNode to,
254             final OTSPoint3D[] intermediatePoints, final int laneCount, final LaneType laneType, final Speed speedLimit,
255             final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction)
256             throws NamingException, NetworkException, OTSGeometryException
257     {
258         return makeMultiLane(network, name, from, to, intermediatePoints, laneCount, 0, 0, laneType, speedLimit, simulator,
259                 direction);
260     }
261 
262     /**
263      * Create a simple road with the specified number of Lanes, based on a Bezier curve.<br>
264      * This method returns an array of Lane. These lanes are embedded in a Link that can be accessed through the getParentLink
265      * method of the Lane.
266      * @param network the network
267      * @param name String; name of the Link
268      * @param n1 Node; control node for the start direction
269      * @param n2 Node; starting node of the new Lane
270      * @param n3 Node; ending node of the new Lane
271      * @param n4 Node; control node for the end direction
272      * @param laneCount int; number of lanes in the road
273      * @param laneOffsetAtStart int; extra offset from design line in lane widths at start of link
274      * @param laneOffsetAtEnd int; extra offset from design line in lane widths at end of link
275      * @param laneType LaneType; type of the new Lanes
276      * @param speedLimit Speed; the speed limit on all lanes
277      * @param simulator OTSDEVSSimulatorInterface; the simulator
278      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
279      * @return Lane&lt;String, String&gt;[]; array containing the new Lanes
280      * @throws NamingException when names cannot be registered for animation
281      * @throws NetworkException on topological problems
282      * @throws OTSGeometryException when creation of center line or contour fails
283      */
284     @SuppressWarnings("checkstyle:parameternumber")
285     public static Lane[] makeMultiLaneBezier(final Network network, final String name, final OTSNode n1, final OTSNode n2,
286             final OTSNode n3, final OTSNode n4, final int laneCount, final int laneOffsetAtStart, final int laneOffsetAtEnd,
287             final LaneType laneType, final Speed speedLimit, final OTSDEVSSimulatorInterface simulator,
288             final LongitudinalDirectionality direction) throws NamingException, NetworkException, OTSGeometryException
289     {
290         OTSLine3D bezier = makeBezier(n1, n2, n3, n4);
291         final CrossSectionLink link = makeLink(network, name, n2, n3, bezier.getPoints(), direction);
292         Lane[] result = new Lane[laneCount];
293         Length width = new Length(4.0, LengthUnit.METER);
294         for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
295         {
296             // Be ware! LEFT is lateral positive, RIGHT is lateral negative.
297             Length latPosAtStart = new Length((-0.5 - laneIndex - laneOffsetAtStart) * width.getSI(), LengthUnit.SI);
298             Length latPosAtEnd = new Length((-0.5 - laneIndex - laneOffsetAtEnd) * width.getSI(), LengthUnit.SI);
299             result[laneIndex] = makeLane(link, "lane." + laneIndex, laneType, latPosAtStart, latPosAtEnd, width, speedLimit,
300                     simulator, direction);
301         }
302         return result;
303     }
304 
305     /**
306      * @param n1 node 1
307      * @param n2 node 2
308      * @param n3 node 3
309      * @param n4 node 4
310      * @return line between n2 and n3 with start-direction n1--&gt;n2 and end-direction n3--&gt;n4
311      * @throws OTSGeometryException on failure of Bezier curve creation
312      */
313     public static OTSLine3D makeBezier(final OTSNode n1, final OTSNode n2, final OTSNode n3, final OTSNode n4)
314             throws OTSGeometryException
315     {
316         OTSPoint3D p1 = n1.getPoint();
317         OTSPoint3D p2 = n2.getPoint();
318         OTSPoint3D p3 = n3.getPoint();
319         OTSPoint3D p4 = n4.getPoint();
320         DirectedPoint dp1 = new DirectedPoint(p2.x, p2.y, p2.z, 0.0, 0.0, Math.atan2(p2.y - p1.y, p2.x - p1.x));
321         DirectedPoint dp2 = new DirectedPoint(p3.x, p3.y, p3.z, 0.0, 0.0, Math.atan2(p4.y - p3.y, p4.x - p3.x));
322         return Bezier.cubic(dp1, dp2);
323     }
324 
325 }