1 package org.opentrafficsim.road.network.lane;
2
3 import java.rmi.RemoteException;
4 import java.util.List;
5 import java.util.Set;
6
7 import javax.naming.NamingException;
8
9 import org.djunits.value.vdouble.scalar.Length;
10 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
11 import org.opentrafficsim.core.geometry.OTSGeometryException;
12 import org.opentrafficsim.core.gtu.GTUType;
13 import org.opentrafficsim.core.network.LateralDirectionality;
14 import org.opentrafficsim.core.network.NetworkException;
15 import org.opentrafficsim.road.network.animation.StripeAnimation;
16
17 /**
18 * Longitudinal road stripes; simple constructors.
19 * <p>
20 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
21 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
22 * <p>
23 * $LastChangedDate: 2015-09-03 13:38:01 +0200 (Thu, 03 Sep 2015) $, @version $Revision: 1378 $, by $Author: averbraeck $,
24 * initial version Oct 25, 2014 <br>
25 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
26 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
27 */
28 public class Stripe extends RoadMarkerAlong
29 {
30 /** */
31 private static final long serialVersionUID = 20151025L;
32
33 /**
34 * <b>Note:</b> LEFT is seen as a positive lateral direction, RIGHT as a negative lateral direction, with the direction from
35 * the StartNode towards the EndNode as the longitudinal direction.
36 * @param parentLink Cross Section Link to which the element belongs
37 * @param lateralCenterPosition the lateral start position compared to the linear geometry of the Cross Section Link
38 * @param width positioned <i>symmetrically around</i> the center line given by the lateralCenterPosition.
39 * @throws OTSGeometryException when creation of the center line or contour geometry fails
40 * @throws NetworkException when id equal to null or not unique
41 */
42 public Stripe(final CrossSectionLink parentLink, final Length lateralCenterPosition, final Length width)
43 throws OTSGeometryException, NetworkException
44 {
45 super(parentLink, lateralCenterPosition, width);
46 }
47
48 /**
49 * Helper constructor that immediately provides permeability for a number of GTU classes.<br>
50 * <b>Note:</b> LEFT is seen as a positive lateral direction, RIGHT as a negative lateral direction, with the direction from
51 * the StartNode towards the EndNode as the longitudinal direction.
52 * @param parentLink Cross Section Link to which the element belongs
53 * @param lateralCenterPosition the lateral start position compared to the linear geometry of the Cross Section Link
54 * @param width positioned <i>symmetrically around</i> the center line given by the lateralCenterPosition
55 * @param gtuTypes the GTU types for which the permeability is defined
56 * @param permeable one of the enums of Stripe.Permeable to define the permeability
57 * @throws OTSGeometryException when creation of the center line or contour geometry fails
58 * @throws NetworkException when id equal to null or not unique
59 */
60 public Stripe(final CrossSectionLink parentLink, final Length lateralCenterPosition, final Length width,
61 final Set<GTUType> gtuTypes, final Permeable permeable) throws OTSGeometryException, NetworkException
62 {
63 super(parentLink, lateralCenterPosition, width);
64 for (GTUType gtuType : gtuTypes)
65 {
66 addPermeability(gtuType, permeable);
67 }
68 }
69
70 /**
71 * Helper constructor that immediately provides permeability for all GTU classes.<br>
72 * <b>Note:</b> LEFT is seen as a positive lateral direction, RIGHT as a negative lateral direction, with the direction from
73 * the StartNode towards the EndNode as the longitudinal direction.
74 * @param parentLink Cross Section Link to which the element belongs
75 * @param crossSectionSlices The offsets and widths at positions along the line, relative to the design line of the parent
76 * link. If there is just one with and offset, there should just be one element in the list with Length = 0. If
77 * there are more slices, the last one should be at the length of the design line. If not, a NetworkException is
78 * thrown.
79 * @param permeable one of the enums of Stripe.Permeable to define the permeability
80 * @throws OTSGeometryException when creation of the center line or contour geometry fails
81 * @throws NetworkException when id equal to null or not unique
82 */
83 public Stripe(final CrossSectionLink parentLink, final List<CrossSectionSlice> crossSectionSlices,
84 final Permeable permeable) throws OTSGeometryException, NetworkException
85 {
86 super(parentLink, crossSectionSlices);
87 addPermeability(GTUType.ALL, permeable);
88 }
89
90 /**
91 * Clone a Stripe for a new network.
92 * @param newParentLink the new link to which the clone belongs
93 * @param newSimulator the new simulator for this network
94 * @param animation whether to (re)create animation or not
95 * @param cse the element to clone from
96 * @throws NetworkException if link already exists in the network, if name of the link is not unique, or if the start node
97 * or the end node of the link are not registered in the network.
98 */
99 protected Stripe(final CrossSectionLink newParentLink, final OTSSimulatorInterface newSimulator,
100 final boolean animation, final Stripe cse) throws NetworkException
101 {
102 super(newParentLink, newSimulator, animation, cse);
103 }
104
105 /**
106 * @param gtuType GTU type to add permeability for.
107 * @param permeable direction(s) to add compared to the direction of the design line.
108 */
109 public final void addPermeability(final GTUType gtuType, final Permeable permeable)
110 {
111 if (permeable.equals(Permeable.LEFT) || permeable.equals(Permeable.BOTH))
112 {
113 addPermeability(gtuType, LateralDirectionality.LEFT);
114 }
115 if (permeable.equals(Permeable.RIGHT) || permeable.equals(Permeable.BOTH))
116 {
117 addPermeability(gtuType, LateralDirectionality.RIGHT);
118 }
119 }
120
121 /** The types of permeability of a stripe. */
122 public enum Permeable
123 {
124 /** Permeable in the positive lateral direction compared to the design line direction. */
125 LEFT,
126 /** Permeable in the negative lateral direction compared to the design line direction. */
127 RIGHT,
128 /** Permeable in both directions. */
129 BOTH;
130 }
131
132 /** {@inheritDoc} */
133 @Override
134 @SuppressWarnings("checkstyle:designforextension")
135 public String toString()
136 {
137 return String.format("Stripe offset %.2fm..%.2fm, width %.2fm..%.2fm", getDesignLineOffsetAtBegin().getSI(),
138 getDesignLineOffsetAtEnd().getSI(), getBeginWidth().getSI(), getEndWidth().getSI());
139 }
140
141 /** {@inheritDoc} */
142 @Override
143 @SuppressWarnings("checkstyle:designforextension")
144 public Stripe clone(final CrossSectionLink newParentLink, final OTSSimulatorInterface newSimulator,
145 final boolean animation) throws NetworkException
146 {
147 try
148 {
149 Stripe newStripe = new Stripe(newParentLink, newSimulator, animation, this);
150
151 if (animation)
152 {
153 // estimate the animation...
154 Permeable permeable = null;
155 for (GTUType gtuType : newStripe.getPermeabilityMap().keySet())
156 {
157 for (LateralDirectionality dir : newStripe.getPermeabilityMap().get(gtuType))
158 {
159 if (dir.isLeft())
160 {
161 if (permeable == null)
162 {
163 permeable = Permeable.LEFT;
164 }
165 if (permeable.equals(Permeable.RIGHT))
166 {
167 permeable = Permeable.BOTH;
168 }
169 }
170 if (dir.isRight())
171 {
172 if (permeable == null)
173 {
174 permeable = Permeable.RIGHT;
175 }
176 if (permeable.equals(Permeable.LEFT))
177 {
178 permeable = Permeable.BOTH;
179 }
180 }
181 }
182 }
183 if (permeable == null)
184 {
185 new StripeAnimation(newStripe, newSimulator, StripeAnimation.TYPE.SOLID);
186 }
187 else
188 {
189 switch (permeable)
190 {
191 case BOTH:
192 new StripeAnimation(newStripe, newSimulator, StripeAnimation.TYPE.DASHED);
193 break;
194
195 case LEFT:
196 new StripeAnimation(newStripe, newSimulator, StripeAnimation.TYPE.LEFTONLY);
197 break;
198
199 case RIGHT:
200 new StripeAnimation(newStripe, newSimulator, StripeAnimation.TYPE.RIGHTONLY);
201 break;
202
203 default:
204 break;
205 }
206 }
207 }
208
209 return newStripe;
210 }
211 catch (NamingException | RemoteException | OTSGeometryException exception)
212 {
213 throw new NetworkException(exception);
214 }
215 }
216
217 }