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