View Javadoc
1   package org.opentrafficsim.road.network.lane;
2   
3   import javax.media.j3d.Bounds;
4   import javax.vecmath.Point3d;
5   
6   import nl.tudelft.simulation.language.d3.BoundingBox;
7   import nl.tudelft.simulation.language.d3.DirectedPoint;
8   
9   import org.djunits.unit.LengthUnit;
10  import org.djunits.value.vdouble.scalar.Length;
11  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
12  import org.opentrafficsim.core.geometry.OTSGeometryException;
13  import org.opentrafficsim.core.gtu.RelativePosition;
14  
15  /**
16   * <p>
17   * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
18   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
19   * <p>
20   * $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, @version $Revision: 1401 $, by $Author: averbraeck $,
21   * initial version Dec 31, 2014 <br>
22   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
23   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
24   */
25  public abstract class AbstractSensor implements Sensor
26  {
27      /** */
28      private static final long serialVersionUID = 20141231L;
29  
30      /** The lane for which this is a sensor. */
31      private final Lane lane;
32  
33      /** The position (between 0.0 and the length of the Lane) of the sensor on the design line of the lane in SI units. */
34      private final double longitudinalPositionSI;
35  
36      /** The relative position of the vehicle that triggers the sensor. */
37      private final RelativePosition.TYPE positionType;
38  
39      /** The name of the sensor. */
40      private final String name;
41  
42      /** The cached location for animation. */
43      private DirectedPoint location = null;
44  
45      /** The cached bounds for animation. */
46      private Bounds bounds = null;
47  
48      /** The simulator for being able to generate an animation. */
49      private final OTSDEVSSimulatorInterface simulator;
50  
51      /**
52       * @param lane The lane for which this is a sensor.
53       * @param longitudinalPosition Length.Rel; the position (between 0.0 and the length of the Lane) of the sensor on the design
54       *            line of the lane.
55       * @param positionType RelativePosition.TYPE; the relative position type (e.g., FRONT, BACK) of the vehicle that triggers
56       *            the sensor.
57       * @param name the name of the sensor.
58       * @param simulator the simulator for being able to generate the animation.
59       */
60      public AbstractSensor(final Lane lane, final Length.Rel longitudinalPosition,
61          final RelativePosition.TYPE positionType, final String name, final OTSDEVSSimulatorInterface simulator)
62      {
63          this.lane = lane;
64          this.longitudinalPositionSI = longitudinalPosition.getSI();
65          this.positionType = positionType;
66          this.name = name;
67          this.simulator = simulator;
68      }
69  
70      /** {@inheritDoc} */
71      @Override
72      public final Lane getLane()
73      {
74          return this.lane;
75      }
76  
77      /** {@inheritDoc} */
78      @Override
79      public final Length.Rel getLongitudinalPosition()
80      {
81          return new Length.Rel(this.longitudinalPositionSI, LengthUnit.METER);
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public final RelativePosition.TYPE getPositionType()
87      {
88          return this.positionType;
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public final double getLongitudinalPositionSI()
94      {
95          return this.longitudinalPositionSI;
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public final DirectedPoint getLocation()
101     {
102         if (this.location == null)
103         {
104             try
105             {
106                 this.location = this.lane.getCenterLine().getLocationSI(this.longitudinalPositionSI);
107                 this.location.z = this.lane.getLocation().z + 0.01;
108             }
109             catch (OTSGeometryException exception)
110             {
111                 exception.printStackTrace();
112                 return null;
113             }
114         }
115         return this.location;
116     }
117 
118     /** {@inheritDoc} */
119     @Override
120     public final Bounds getBounds()
121     {
122         if (this.bounds == null)
123         {
124             this.bounds =
125                 new BoundingBox(new Point3d(-0.4, -this.lane.getWidth(0.0).getSI() * 0.4, 0.0), new Point3d(0.4,
126                     this.lane.getWidth(0.0).getSI() * 0.4, this.lane.getLocation().z + 0.01));
127         }
128         return this.bounds;
129     }
130 
131     /**
132      * @return name.
133      */
134     public final String getName()
135     {
136         return this.name;
137     }
138 
139     /**
140      * @return simulator
141      */
142     public final OTSDEVSSimulatorInterface getSimulator()
143     {
144         return this.simulator;
145     }
146 
147     /** {@inheritDoc} */
148     @SuppressWarnings("checkstyle:designforextension")
149     @Override
150     public int hashCode()
151     {
152         final int prime = 31;
153         int result = 1;
154         result = prime * result + ((this.lane == null) ? 0 : this.lane.hashCode());
155         long temp;
156         temp = Double.doubleToLongBits(this.longitudinalPositionSI);
157         result = prime * result + (int) (temp ^ (temp >>> 32));
158         result = prime * result + ((this.positionType == null) ? 0 : this.positionType.hashCode());
159         return result;
160     }
161 
162     /** {@inheritDoc} */
163     @SuppressWarnings({"checkstyle:needbraces", "checkstyle:designforextension"})
164     @Override
165     public boolean equals(final Object obj)
166     {
167         if (this == obj)
168             return true;
169         if (obj == null)
170             return false;
171         if (getClass() != obj.getClass())
172             return false;
173         AbstractSensor other = (AbstractSensor) obj;
174         if (this.lane == null)
175         {
176             if (other.lane != null)
177                 return false;
178         }
179         else if (!this.lane.equals(other.lane))
180             return false;
181         if (Double.doubleToLongBits(this.longitudinalPositionSI) != Double
182             .doubleToLongBits(other.longitudinalPositionSI))
183             return false;
184         if (this.positionType == null)
185         {
186             if (other.positionType != null)
187                 return false;
188         }
189         else if (!this.positionType.equals(other.positionType))
190             return false;
191         return true;
192     }
193 
194     /** {@inheritDoc} */
195     @SuppressWarnings("checkstyle:designforextension")
196     @Override
197     public int compareTo(final Sensor o)
198     {
199         if (this.lane != o.getLane())
200         {
201             return this.lane.hashCode() < o.getLane().hashCode() ? -1 : 1;
202         }
203         if (this.longitudinalPositionSI != o.getLongitudinalPositionSI())
204         {
205             return this.longitudinalPositionSI < o.getLongitudinalPositionSI() ? -1 : 1;
206         }
207         if (!this.positionType.equals(o.getPositionType()))
208         {
209             return this.positionType.hashCode() < o.getPositionType().hashCode() ? -1 : 1;
210         }
211         if (!this.equals(o))
212         {
213             return this.hashCode() < o.hashCode() ? -1 : 1;
214         }
215         return 0;
216     }
217 
218 }