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