LaneFactory.java

  1. package org.opentrafficsim.road.network.factory;

  2. import java.awt.Color;
  3. import java.rmi.RemoteException;
  4. import java.util.ArrayList;
  5. import java.util.Arrays;
  6. import java.util.LinkedHashMap;
  7. import java.util.List;
  8. import java.util.Map;

  9. import javax.naming.NamingException;

  10. import nl.tudelft.simulation.language.d3.DirectedPoint;

  11. import org.djunits.unit.LengthUnit;
  12. import org.djunits.value.vdouble.scalar.Length;
  13. import org.djunits.value.vdouble.scalar.Speed;
  14. import org.opentrafficsim.core.dsol.OTSAnimatorInterface;
  15. import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
  16. import org.opentrafficsim.core.geometry.Bezier;
  17. import org.opentrafficsim.core.geometry.OTSGeometryException;
  18. import org.opentrafficsim.core.geometry.OTSLine3D;
  19. import org.opentrafficsim.core.geometry.OTSPoint3D;
  20. import org.opentrafficsim.core.gtu.GTUType;
  21. import org.opentrafficsim.core.network.LinkType;
  22. import org.opentrafficsim.core.network.LongitudinalDirectionality;
  23. import org.opentrafficsim.core.network.NetworkException;
  24. import org.opentrafficsim.core.network.OTSNode;
  25. import org.opentrafficsim.road.network.animation.LaneAnimation;
  26. import org.opentrafficsim.road.network.lane.CrossSectionLink;
  27. import org.opentrafficsim.road.network.lane.Lane;
  28. import org.opentrafficsim.road.network.lane.LaneType;
  29. import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
  30. import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;

  31. /**
  32.  * <p>
  33.  * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  34.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  35.  * <p>
  36.  * $LastChangedDate: 2015-09-16 19:20:07 +0200 (Wed, 16 Sep 2015) $, @version $Revision: 1405 $, by $Author: averbraeck $,
  37.  * initial version 30 okt. 2014 <br>
  38.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  39.  */
  40. public final class LaneFactory
  41. {
  42.     /** Do not instantiate this class. */
  43.     private LaneFactory()
  44.     {
  45.         // Cannot be instantiated.
  46.     }

  47.     /**
  48.      * Create a Link along intermediate coordinates from one Node to another.
  49.      * @param name String; name of the new Link
  50.      * @param from Node; start Node of the new Link
  51.      * @param to Node; end Node of the new Link
  52.      * @param intermediatePoints OTSPoint3D[]; array of intermediate coordinates (may be null); the intermediate points may
  53.      *            contain the coordinates of the from node and to node
  54.      * @param direction the direction of the link
  55.      * @return Link; the newly constructed Link
  56.      * @throws OTSGeometryException when the design line is degenerate (only one point or duplicate point)
  57.      */
  58.     public static CrossSectionLink makeLink(final String name, final OTSNode from, final OTSNode to,
  59.         final OTSPoint3D[] intermediatePoints, final LongitudinalDirectionality direction) throws OTSGeometryException
  60.     {
  61.         List<OTSPoint3D> pointList =
  62.             intermediatePoints == null ? new ArrayList<OTSPoint3D>() : new ArrayList<OTSPoint3D>(
  63.                 Arrays.asList(intermediatePoints));
  64.         if (pointList.size() == 0 || !from.getPoint().equals(pointList.get(0)))
  65.         {
  66.             pointList.add(0, from.getPoint());
  67.         }
  68.         if (pointList.size() == 0 || !to.getPoint().equals(pointList.get(pointList.size() - 1)))
  69.         {
  70.             pointList.add(to.getPoint());
  71.         }

  72.         /*-
  73.         // see if an intermediate point needs to be created to the start of the link in the right direction
  74.         OTSPoint3D s1 = pointList.get(0);
  75.         OTSPoint3D s2 = pointList.get(1);
  76.         double dy = s2.y - s1.y;
  77.         double dx = s2.x - s1.x;
  78.         double a = from.getLocation().getRotZ();
  79.         if (Math.abs(a - Math.atan2(dy, dx)) > 1E-6)
  80.         {
  81.             double r = Math.min(1.0, Math.sqrt(dy * dy + dx * dx) / 4.0);
  82.             OTSPoint3D extra = new OTSPoint3D(s1.x + r * Math.cos(a), s1.y + r * Math.sin(a), s1.z);
  83.             pointList.add(1, extra);
  84.         }
  85.        
  86.         // see if an intermediate point needs to be created to the end of the link in the right direction
  87.         s1 = pointList.get(pointList.size() - 2);
  88.         s2 = pointList.get(pointList.size() - 1);
  89.         dy = s2.y - s1.y;
  90.         dx = s2.x - s1.x;
  91.         a = to.getLocation().getRotZ() - Math.PI;
  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(s2.x + r * Math.cos(a), s2.y + r * Math.sin(a), s2.z);
  96.             pointList.add(pointList.size() - 2, extra);
  97.         }
  98.          */

  99.         OTSLine3D designLine = new OTSLine3D(pointList);
  100.         CrossSectionLink link =
  101.             new CrossSectionLink(name, from, to, LinkType.ALL, designLine, direction, LaneKeepingPolicy.KEEP_RIGHT);
  102.         return link;
  103.     }

  104.     /**
  105.      * Create one Lane.
  106.      * @param link Link; the link that owns the new Lane
  107.      * @param id String; the id of this lane, should be unique within the link
  108.      * @param laneType LaneType&lt;String&gt;; the type of the new Lane
  109.      * @param latPosAtStart Length; the lateral position of the new Lane with respect to the design line of the link at the
  110.      *            start of the link
  111.      * @param latPosAtEnd Length; the lateral position of the new Lane with respect to the design line of the link at the
  112.      *            end of the link
  113.      * @param width Length; the width of the new Lane
  114.      * @param speedLimit Speed; the speed limit on the new Lane
  115.      * @param simulator OTSDEVSSimulatorInterface; the simulator
  116.      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
  117.      * @return Lane
  118.      * @throws NamingException when names cannot be registered for animation
  119.      * @throws NetworkException on network inconsistency
  120.      * @throws OTSGeometryException when creation of center line or contour fails
  121.      */
  122.     @SuppressWarnings("checkstyle:parameternumber")
  123.     private static Lane makeLane(final CrossSectionLink link, final String id, final LaneType laneType,
  124.         final Length latPosAtStart, final Length latPosAtEnd, final Length width, final Speed speedLimit,
  125.         final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction) throws NamingException,
  126.         NetworkException, OTSGeometryException
  127.     {
  128.         Map<GTUType, LongitudinalDirectionality> directionalityMap = new LinkedHashMap<>();
  129.         directionalityMap.put(GTUType.ALL, direction);
  130.         Map<GTUType, Speed> speedMap = new LinkedHashMap<>();
  131.         speedMap.put(GTUType.ALL, speedLimit);
  132.         Lane result =
  133.             new Lane(link, id, latPosAtStart, latPosAtEnd, width, width, laneType, directionalityMap, speedMap,
  134.                 new OvertakingConditions.LeftAndRight());
  135.         if (simulator instanceof OTSAnimatorInterface)
  136.         {
  137.             try
  138.             {
  139.                 new LaneAnimation(result, simulator, Color.LIGHT_GRAY, false);
  140.             }
  141.             catch (RemoteException exception)
  142.             {
  143.                 exception.printStackTrace();
  144.             }
  145.         }
  146.         return result;
  147.     }

  148.     /**
  149.      * Create a simple Lane.
  150.      * @param name String; name of the Lane (and also of the Link that owns it)
  151.      * @param from Node; starting node of the new Lane
  152.      * @param to Node; ending node of the new Lane
  153.      * @param intermediatePoints OTSPoint3D[]; intermediate coordinates or null to create a straight road; the intermediate
  154.      *            points may contain the coordinates of the from node and to node
  155.      * @param laneType LaneType; type of the new Lane
  156.      * @param speedLimit Speed; the speed limit on the new Lane
  157.      * @param simulator OTSDEVSSimulatorInterface; the simulator
  158.      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
  159.      * @return Lane; the new Lane
  160.      * @throws NamingException when names cannot be registered for animation
  161.      * @throws NetworkException on network inconsistency
  162.      * @throws OTSGeometryException when creation of center line or contour fails
  163.      */
  164.     public static Lane makeLane(final String name, final OTSNode from, final OTSNode to,
  165.         final OTSPoint3D[] intermediatePoints, final LaneType laneType, final Speed speedLimit,
  166.         final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction) throws NamingException,
  167.         NetworkException, OTSGeometryException
  168.     {
  169.         Length width = new Length(4.0, LengthUnit.METER);
  170.         final CrossSectionLink link = makeLink(name, from, to, intermediatePoints, direction);
  171.         Length latPos = new Length(0.0, LengthUnit.METER);
  172.         return makeLane(link, "lane", laneType, latPos, latPos, width, speedLimit, simulator, direction);
  173.     }

  174.     /**
  175.      * Create a simple road with the specified number of Lanes.<br>
  176.      * This method returns an array of Lane. These lanes are embedded in a Link that can be accessed through the getParentLink
  177.      * method of the Lane.
  178.      * @param name String; name of the Link
  179.      * @param from Node; starting node of the new Lane
  180.      * @param to Node; ending node of the new Lane
  181.      * @param intermediatePoints OTSPoint3D[]; intermediate coordinates or null to create a straight road; the intermediate
  182.      *            points may contain the coordinates of the from node and to node
  183.      * @param laneCount int; number of lanes in the road
  184.      * @param laneOffsetAtStart int; extra offset from design line in lane widths at start of link
  185.      * @param laneOffsetAtEnd int; extra offset from design line in lane widths at end of link
  186.      * @param laneType LaneType; type of the new Lanes
  187.      * @param speedLimit Speed; the speed limit on all lanes
  188.      * @param simulator OTSDEVSSimulatorInterface; the simulator
  189.      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
  190.      * @return Lane&lt;String, String&gt;[]; array containing the new Lanes
  191.      * @throws NamingException when names cannot be registered for animation
  192.      * @throws NetworkException on topological problems
  193.      * @throws OTSGeometryException when creation of center line or contour fails
  194.      */
  195.     @SuppressWarnings("checkstyle:parameternumber")
  196.     public static Lane[] makeMultiLane(final String name, final OTSNode from, final OTSNode to,
  197.         final OTSPoint3D[] intermediatePoints, final int laneCount, final int laneOffsetAtStart,
  198.         final int laneOffsetAtEnd, final LaneType laneType, final Speed speedLimit,
  199.         final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction) throws NamingException,
  200.         NetworkException, OTSGeometryException
  201.     {
  202.         final CrossSectionLink link = makeLink(name, from, to, intermediatePoints, direction);
  203.         Lane[] result = new Lane[laneCount];
  204.         Length width = new Length(4.0, LengthUnit.METER);
  205.         for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
  206.         {
  207.             // Be ware! LEFT is lateral positive, RIGHT is lateral negative.
  208.             Length latPosAtStart =
  209.                 new Length((-0.5 - laneIndex - laneOffsetAtStart) * width.getSI(), LengthUnit.SI);
  210.             Length latPosAtEnd =
  211.                 new Length((-0.5 - laneIndex - laneOffsetAtEnd) * width.getSI(), LengthUnit.SI);
  212.             result[laneIndex] =
  213.                 makeLane(link, "lane." + laneIndex, laneType, latPosAtStart, latPosAtEnd, width, speedLimit, simulator,
  214.                     direction);
  215.         }
  216.         return result;
  217.     }

  218.     /**
  219.      * Create a simple road with the specified number of Lanes.<br>
  220.      * This method returns an array of Lane. These lanes are embedded in a Link that can be accessed through the getParentLink
  221.      * method of the Lane.
  222.      * @param name String; name of the Link
  223.      * @param from Node; starting node of the new Lane
  224.      * @param to Node; ending node of the new Lane
  225.      * @param intermediatePoints OTSPoint3D[]; intermediate coordinates or null to create a straight road; the intermediate
  226.      *            points may contain the coordinates of the from node and to node
  227.      * @param laneCount int; number of lanes in the road
  228.      * @param laneType LaneType; type of the new Lanes
  229.      * @param speedLimit Speed the speed limit (applies to all generated lanes)
  230.      * @param simulator OTSDEVSSimulatorInterface; the simulator
  231.      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
  232.      * @return Lane&lt;String, String&gt;[]; array containing the new Lanes
  233.      * @throws NamingException when names cannot be registered for animation
  234.      * @throws NetworkException on topological problems
  235.      * @throws OTSGeometryException when creation of center line or contour fails
  236.      */
  237.     @SuppressWarnings("checkstyle:parameternumber")
  238.     public static Lane[] makeMultiLane(final String name, final OTSNode from, final OTSNode to,
  239.         final OTSPoint3D[] intermediatePoints, final int laneCount, final LaneType laneType, final Speed speedLimit,
  240.         final OTSDEVSSimulatorInterface simulator, final LongitudinalDirectionality direction) throws NamingException,
  241.         NetworkException, OTSGeometryException
  242.     {
  243.         return makeMultiLane(name, from, to, intermediatePoints, laneCount, 0, 0, laneType, speedLimit, simulator,
  244.             direction);
  245.     }

  246.     /**
  247.      * Create a simple road with the specified number of Lanes, based on a Bezier curve.<br>
  248.      * This method returns an array of Lane. These lanes are embedded in a Link that can be accessed through the getParentLink
  249.      * method of the Lane.
  250.      * @param name String; name of the Link
  251.      * @param n1 Node; control node for the start direction
  252.      * @param n2 Node; starting node of the new Lane
  253.      * @param n3 Node; ending node of the new Lane
  254.      * @param n4 Node; control node for the end direction
  255.      * @param laneCount int; number of lanes in the road
  256.      * @param laneOffsetAtStart int; extra offset from design line in lane widths at start of link
  257.      * @param laneOffsetAtEnd int; extra offset from design line in lane widths at end of link
  258.      * @param laneType LaneType; type of the new Lanes
  259.      * @param speedLimit Speed; the speed limit on all lanes
  260.      * @param simulator OTSDEVSSimulatorInterface; the simulator
  261.      * @param direction the direction of the underlying link, DIR_PLUS or DIR_MINUS (or DIR_BOTH)
  262.      * @return Lane&lt;String, String&gt;[]; array containing the new Lanes
  263.      * @throws NamingException when names cannot be registered for animation
  264.      * @throws NetworkException on topological problems
  265.      * @throws OTSGeometryException when creation of center line or contour fails
  266.      */
  267.     @SuppressWarnings("checkstyle:parameternumber")
  268.     public static Lane[] makeMultiLaneBezier(final String name, final OTSNode n1, final OTSNode n2, final OTSNode n3,
  269.         final OTSNode n4, final int laneCount, final int laneOffsetAtStart, final int laneOffsetAtEnd,
  270.         final LaneType laneType, final Speed speedLimit, final OTSDEVSSimulatorInterface simulator,
  271.         final LongitudinalDirectionality direction) throws NamingException, NetworkException, OTSGeometryException
  272.     {
  273.         OTSLine3D bezier = makeBezier(n1, n2, n3, n4);
  274.         final CrossSectionLink link = makeLink(name, n2, n3, bezier.getPoints(), direction);
  275.         Lane[] result = new Lane[laneCount];
  276.         Length width = new Length(4.0, LengthUnit.METER);
  277.         for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
  278.         {
  279.             // Be ware! LEFT is lateral positive, RIGHT is lateral negative.
  280.             Length latPosAtStart =
  281.                 new Length((-0.5 - laneIndex - laneOffsetAtStart) * width.getSI(), LengthUnit.SI);
  282.             Length latPosAtEnd =
  283.                 new Length((-0.5 - laneIndex - laneOffsetAtEnd) * width.getSI(), LengthUnit.SI);
  284.             result[laneIndex] =
  285.                 makeLane(link, "lane." + laneIndex, laneType, latPosAtStart, latPosAtEnd, width, speedLimit, simulator,
  286.                     direction);
  287.         }
  288.         return result;
  289.     }

  290.     /**
  291.      * @param n1 node 1
  292.      * @param n2 node 2
  293.      * @param n3 node 3
  294.      * @param n4 node 4
  295.      * @return line between n2 and n3 with start-direction n1--&gt;n2 and end-direction n3--&gt;n4
  296.      * @throws OTSGeometryException on failure of Bezier curve creation
  297.      */
  298.     public static OTSLine3D makeBezier(final OTSNode n1, final OTSNode n2, final OTSNode n3, final OTSNode n4)
  299.         throws OTSGeometryException
  300.     {
  301.         OTSPoint3D p1 = n1.getPoint();
  302.         OTSPoint3D p2 = n2.getPoint();
  303.         OTSPoint3D p3 = n3.getPoint();
  304.         OTSPoint3D p4 = n4.getPoint();
  305.         DirectedPoint dp1 = new DirectedPoint(p2.x, p2.y, p2.z, 0.0, 0.0, Math.atan2(p2.y - p1.y, p2.x - p1.x));
  306.         DirectedPoint dp2 = new DirectedPoint(p3.x, p3.y, p3.z, 0.0, 0.0, Math.atan2(p4.y - p3.y, p4.x - p3.x));
  307.         return Bezier.cubic(dp1, dp2);
  308.     }

  309. }