View Javadoc
1   package org.opentrafficsim.core.geometry;
2   
3   import java.awt.geom.Point2D;
4   import java.io.Serializable;
5   
6   import javax.media.j3d.BoundingSphere;
7   import javax.media.j3d.Bounds;
8   import javax.vecmath.Point3d;
9   
10  import nl.tudelft.simulation.dsol.animation.LocatableInterface;
11  import nl.tudelft.simulation.language.d3.CartesianPoint;
12  import nl.tudelft.simulation.language.d3.DirectedPoint;
13  
14  import org.djunits.unit.LengthUnit;
15  import org.opentrafficsim.core.OTS_SCALAR;
16  
17  import com.vividsolutions.jts.geom.Coordinate;
18  import com.vividsolutions.jts.geom.Point;
19  
20  /**
21   * An OTSPoint3D implements a 3D-coordinate for OTS. X, y and z are stored as doubles, but it is assumed that the scale is in SI
22   * units, i.e. in meters. A distance between two points is therefore also in meters.
23   * <p>
24   * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
25   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
26   * <p>
27   * $LastChangedDate: 2015-07-16 10:20:53 +0200 (Thu, 16 Jul 2015) $, @version $Revision: 1124 $, by $Author: pknoppers $,
28   * initial version Jul 22, 2015 <br>
29   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
30   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
31   * @author <a href="http://www.citg.tudelft.nl">Guus Tamminga</a>
32   */
33  public class OTSPoint3D implements LocatableInterface, Serializable, OTS_SCALAR
34  {
35      /** */
36      private static final long serialVersionUID = 20150722L;
37  
38      /** the internal representation of the point; x-coordinate. */
39      @SuppressWarnings("checkstyle:visibilitymodifier")
40      public final double x;
41  
42      /** the internal representation of the point; y-coordinate. */
43      @SuppressWarnings("checkstyle:visibilitymodifier")
44      public final double y;
45  
46      /** the internal representation of the point; z-coordinate. */
47      @SuppressWarnings("checkstyle:visibilitymodifier")
48      public final double z;
49  
50      /**
51       * The x, y and z in the point are assumed to be in meters relative to an origin.
52       * @param x x-coordinate
53       * @param y y-coordinate
54       * @param z z-coordinate
55       */
56      public OTSPoint3D(final double x, final double y, final double z)
57      {
58          this.x = x;
59          this.y = y;
60          this.z = z;
61      }
62  
63      /**
64       * @param xyz array with three elements; x, y and z are assumed to be in meters relative to an origin.
65       */
66      public OTSPoint3D(final double[] xyz)
67      {
68          this(xyz[0], xyz[1], (xyz.length > 2) ? xyz[2] : 0.0);
69      }
70  
71      /**
72       * @param point a point to "clone".
73       */
74      public OTSPoint3D(final OTSPoint3D point)
75      {
76          this(point.x, point.y, point.z);
77      }
78  
79      /**
80       * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
81       *            origin.
82       */
83      public OTSPoint3D(final Point3d point)
84      {
85          this(point.x, point.y, point.z);
86      }
87  
88      /**
89       * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
90       *            origin.
91       */
92      public OTSPoint3D(final CartesianPoint point)
93      {
94          this(point.x, point.y, point.z);
95      }
96  
97      /**
98       * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
99       *            origin.
100      */
101     public OTSPoint3D(final DirectedPoint point)
102     {
103         this(point.x, point.y, point.z);
104     }
105 
106     /**
107      * @param point2d java.awt 2D point, z-coordinate will be zero; the x and y in the point are assumed to be in meters
108      *            relative to an origin.
109      */
110     public OTSPoint3D(final Point2D point2d)
111     {
112         this(point2d.getX(), point2d.getY(), 0.0);
113     }
114 
115     /**
116      * @param coordinate geotools coordinate; the x, y and z in the coordinate are assumed to be in meters relative to an
117      *            origin.
118      */
119     public OTSPoint3D(final Coordinate coordinate)
120     {
121         this(coordinate.x, coordinate.y, (Double.isNaN(coordinate.z)) ? 0.0 : coordinate.z);
122     }
123 
124     /**
125      * @param point geotools point; z-coordinate will be zero; the x and y in the point are assumed to be in meters relative to
126      *            an origin.
127      */
128     public OTSPoint3D(final Point point)
129     {
130         this(point.getX(), point.getY(), 0.0);
131     }
132 
133     /**
134      * The x and y in the point are assumed to be in meters relative to an origin. z will be set to 0.
135      * @param x x-coordinate
136      * @param y y-coordinate
137      */
138     public OTSPoint3D(final double x, final double y)
139     {
140         this(x, y, 0.0);
141     }
142 
143     /**
144      * @param point the point to which the distance has to be calculated.
145      * @return the distance in 3D according to Pythagoras, expressed in SI units
146      */
147     public final double distanceSI(final OTSPoint3D point)
148     {
149         double dx = point.x - this.x;
150         double dy = point.y - this.y;
151         double dz = point.z - this.z;
152 
153         return Math.sqrt(dx * dx + dy * dy + dz * dz);
154     }
155 
156     /**
157      * @param point the point to which the distance has to be calculated.
158      * @return the distance in 3D according to Pythagoras
159      */
160     public final Length.Rel distance(final OTSPoint3D point)
161     {
162         return new Length.Rel(distanceSI(point), LengthUnit.SI);
163     }
164 
165     /**
166      * @return the equivalent geotools Coordinate of this point.
167      */
168     public final Coordinate getCoordinate()
169     {
170         return new Coordinate(this.x, this.y, this.z);
171     }
172 
173     /**
174      * @return the equivalent DSOL DirectedPoint of this point.
175      */
176     public final DirectedPoint getDirectedPoint()
177     {
178         return new DirectedPoint(this.x, this.y, this.z);
179     }
180 
181     /** {@inheritDoc} */
182     @Override
183     public final DirectedPoint getLocation() 
184     {
185         return getDirectedPoint();
186     }
187 
188     /**
189      * This method returns a sphere with a diameter of half a meter as the default bounds for a point.
190      * {@inheritDoc}
191      */
192     @Override
193     public final Bounds getBounds() 
194     {
195         return new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 0.5);
196     }
197 
198     /** {@inheritDoc} */
199     @Override
200     @SuppressWarnings("checkstyle:designforextension")
201     public String toString()
202     {
203         return String.format("(%.2f,%.2f,%.2f)", this.x, this.y, this.z);
204     }
205 
206     /** {@inheritDoc} */
207     @Override
208     @SuppressWarnings("checkstyle:designforextension")
209     public int hashCode()
210     {
211         final int prime = 31;
212         int result = 1;
213         long temp;
214         temp = Double.doubleToLongBits(this.x);
215         result = prime * result + (int) (temp ^ (temp >>> 32));
216         temp = Double.doubleToLongBits(this.y);
217         result = prime * result + (int) (temp ^ (temp >>> 32));
218         temp = Double.doubleToLongBits(this.z);
219         result = prime * result + (int) (temp ^ (temp >>> 32));
220         return result;
221     }
222 
223     /** {@inheritDoc} */
224     @Override
225     @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces"})
226     public boolean equals(final Object obj)
227     {
228         if (this == obj)
229             return true;
230         if (obj == null)
231             return false;
232         if (getClass() != obj.getClass())
233             return false;
234         OTSPoint3D other = (OTSPoint3D) obj;
235         if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x))
236             return false;
237         if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y))
238             return false;
239         if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z))
240             return false;
241         return true;
242     }
243 
244 }