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