OTSPoint3D.java

  1. package org.opentrafficsim.core.geometry;

  2. import java.awt.geom.Point2D;
  3. import java.io.Serializable;
  4. import java.util.ArrayList;
  5. import java.util.List;

  6. import javax.media.j3d.BoundingSphere;
  7. import javax.media.j3d.Bounds;
  8. import javax.vecmath.Point3d;

  9. import org.djunits.unit.LengthUnit;
  10. import org.djunits.value.vdouble.scalar.Length;

  11. import com.vividsolutions.jts.geom.Coordinate;
  12. import com.vividsolutions.jts.geom.Point;

  13. import nl.tudelft.simulation.dsol.animation.Locatable;
  14. import nl.tudelft.simulation.language.d3.CartesianPoint;
  15. import nl.tudelft.simulation.language.d3.DirectedPoint;

  16. /**
  17.  * 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
  18.  * units, i.e. in meters. A distance between two points is therefore also in meters.
  19.  * <p>
  20.  * Copyright (c) 2013-2018 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-07-16 10:20:53 +0200 (Thu, 16 Jul 2015) $, @version $Revision: 1124 $, by $Author: pknoppers $,
  24.  * initial version Jul 22, 2015 <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.  * @author <a href="http://www.citg.tudelft.nl">Guus Tamminga</a>
  28.  */
  29. public class OTSPoint3D implements Locatable, Serializable
  30. {
  31.     /** */
  32.     private static final long serialVersionUID = 20150722L;

  33.     /** The internal representation of the point; x-coordinate. */
  34.     @SuppressWarnings("checkstyle:visibilitymodifier")
  35.     public final double x;

  36.     /** The internal representation of the point; y-coordinate. */
  37.     @SuppressWarnings("checkstyle:visibilitymodifier")
  38.     public final double y;

  39.     /** The internal representation of the point; z-coordinate. */
  40.     @SuppressWarnings("checkstyle:visibilitymodifier")
  41.     public final double z;

  42.     /**
  43.      * The x, y and z in the point are assumed to be in meters relative to an origin.
  44.      * @param x x-coordinate
  45.      * @param y y-coordinate
  46.      * @param z z-coordinate
  47.      */
  48.     public OTSPoint3D(final double x, final double y, final double z)
  49.     {
  50.         this.x = x;
  51.         this.y = y;
  52.         this.z = z;
  53.     }

  54.     /**
  55.      * @param xyz array with three elements; x, y and z are assumed to be in meters relative to an origin.
  56.      */
  57.     public OTSPoint3D(final double[] xyz)
  58.     {
  59.         this(xyz[0], xyz[1], (xyz.length > 2) ? xyz[2] : 0.0);
  60.     }

  61.     /**
  62.      * @param point a point to "clone".
  63.      */
  64.     public OTSPoint3D(final OTSPoint3D point)
  65.     {
  66.         this(point.x, point.y, point.z);
  67.     }

  68.     /**
  69.      * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
  70.      *            origin.
  71.      */
  72.     public OTSPoint3D(final Point3d point)
  73.     {
  74.         this(point.x, point.y, point.z);
  75.     }

  76.     /**
  77.      * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
  78.      *            origin.
  79.      */
  80.     public OTSPoint3D(final CartesianPoint point)
  81.     {
  82.         this(point.x, point.y, point.z);
  83.     }

  84.     /**
  85.      * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
  86.      *            origin.
  87.      */
  88.     public OTSPoint3D(final DirectedPoint point)
  89.     {
  90.         this(point.x, point.y, point.z);
  91.     }

  92.     /**
  93.      * @param point2d java.awt 2D point, z-coordinate will be zero; the x and y in the point are assumed to be in meters
  94.      *            relative to an origin.
  95.      */
  96.     public OTSPoint3D(final Point2D point2d)
  97.     {
  98.         this(point2d.getX(), point2d.getY(), 0.0);
  99.     }

  100.     /**
  101.      * @param coordinate geotools coordinate; the x, y and z in the coordinate are assumed to be in meters relative to an
  102.      *            origin.
  103.      */
  104.     public OTSPoint3D(final Coordinate coordinate)
  105.     {
  106.         this(coordinate.x, coordinate.y, Double.isNaN(coordinate.z) ? 0.0 : coordinate.z);
  107.     }

  108.     /**
  109.      * @param point geotools point; z-coordinate will be zero; the x and y in the point are assumed to be in meters relative to
  110.      *            an origin.
  111.      */
  112.     public OTSPoint3D(final Point point)
  113.     {
  114.         this(point.getX(), point.getY(), 0.0);
  115.     }

  116.     /**
  117.      * The x and y in the point are assumed to be in meters relative to an origin. z will be set to 0.
  118.      * @param x x-coordinate
  119.      * @param y y-coordinate
  120.      */
  121.     public OTSPoint3D(final double x, final double y)
  122.     {
  123.         this(x, y, 0.0);
  124.     }

  125.     /**
  126.      * Interpolate (or extrapolate) between (outside) two given points.
  127.      * @param ratio double; 0 selects the zeroValue point, 1 selects the oneValue point, 0.5 selects a point halfway, etc.
  128.      * @param zeroValue OTSPoint3D; the point that is returned when ratio equals 0
  129.      * @param oneValue OTSPoint3D; the point that is returned when ratio equals 1
  130.      * @return OTSPoint3D
  131.      */
  132.     public static OTSPoint3D interpolate(final double ratio, final OTSPoint3D zeroValue, final OTSPoint3D oneValue)
  133.     {
  134.         double complement = 1 - ratio;
  135.         return new OTSPoint3D(complement * zeroValue.x + ratio * oneValue.x, complement * zeroValue.y + ratio * oneValue.y,
  136.                 complement * zeroValue.z + ratio * oneValue.z);
  137.     }

  138.     /**
  139.      * Compute the 2D intersection of two line segments. The Z-component of the lines is ignored. Both line segments are defined
  140.      * by two points (that should be distinct). This version suffers loss of precision when called with very large coordinate
  141.      * values.
  142.      * @param line1P1 OTSPoint3D; first point of line segment 1
  143.      * @param line1P2 OTSPoint3D; second point of line segment 1
  144.      * @param line2P1 OTSPoint3D; first point of line segment 2
  145.      * @param line2P2 OTSPoint3D; second point of line segment 2
  146.      * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel, or do not intersect
  147.      */
  148.     @Deprecated
  149.     public static OTSPoint3D intersectionOfLineSegmentsDumb(final OTSPoint3D line1P1, final OTSPoint3D line1P2,
  150.             final OTSPoint3D line2P1, final OTSPoint3D line2P2)
  151.     {
  152.         double denominator =
  153.                 (line2P2.y - line2P1.y) * (line1P2.x - line1P1.x) - (line2P2.x - line2P1.x) * (line1P2.y - line1P1.y);
  154.         if (denominator == 0f)
  155.         {
  156.             return null; // lines are parallel (they might even be on top of each other, but we don't check that)
  157.         }
  158.         double uA = ((line2P2.x - line2P1.x) * (line1P1.y - line2P1.y) - (line2P2.y - line2P1.y) * (line1P1.x - line2P1.x))
  159.                 / denominator;
  160.         if ((uA < 0f) || (uA > 1f))
  161.         {
  162.             return null; // intersection outside line 1
  163.         }
  164.         double uB = ((line1P2.x - line1P1.x) * (line1P1.y - line2P1.y) - (line1P2.y - line1P1.y) * (line1P1.x - line2P1.x))
  165.                 / denominator;
  166.         if (uB < 0 || uB > 1)
  167.         {
  168.             return null; // intersection outside line 2
  169.         }
  170.         return new OTSPoint3D(line1P1.x + uA * (line1P2.x - line1P1.x), line1P1.y + uA * (line1P2.y - line1P1.y), 0);
  171.     }

  172.     /**
  173.      * Compute the 2D intersection of two line segments. The Z-component of the lines is ignored. Both line segments are defined
  174.      * by two points (that should be distinct).
  175.      * @param line1P1 OTSPoint3D; first point of line segment 1
  176.      * @param line1P2 OTSPoint3D; second point of line segment 1
  177.      * @param line2P1 OTSPoint3D; first point of line segment 2
  178.      * @param line2P2 OTSPoint3D; second point of line segment 2
  179.      * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel, or do not intersect
  180.      */
  181.     public static OTSPoint3D intersectionOfLineSegments(final OTSPoint3D line1P1, final OTSPoint3D line1P2,
  182.             final OTSPoint3D line2P1, final OTSPoint3D line2P2)
  183.     {
  184.         double l1p1x = line1P1.x;
  185.         double l1p1y = line1P1.y;
  186.         double l1p2x = line1P2.x - l1p1x;
  187.         double l1p2y = line1P2.y - l1p1y;
  188.         double l2p1x = line2P1.x - l1p1x;
  189.         double l2p1y = line2P1.y - l1p1y;
  190.         double l2p2x = line2P2.x - l1p1x;
  191.         double l2p2y = line2P2.y - l1p1y;
  192.         double denominator = (l2p2y - l2p1y) * l1p2x - (l2p2x - l2p1x) * l1p2y;
  193.         if (denominator == 0f)
  194.         {
  195.             return null; // lines are parallel (they might even be on top of each other, but we don't check that)
  196.         }
  197.         double uA = ((l2p2x - l2p1x) * (-l2p1y) - (l2p2y - l2p1y) * (-l2p1x)) / denominator;
  198.         // System.out.println("uA is " + uA);
  199.         if ((uA < 0f) || (uA > 1f))
  200.         {
  201.             return null; // intersection outside line 1
  202.         }
  203.         double uB = (l1p2y * l2p1x - l1p2x * l2p1y) / denominator;
  204.         // System.out.println("uB is " + uB);
  205.         if (uB < 0 || uB > 1)
  206.         {
  207.             return null; // intersection outside line 2
  208.         }
  209.         return new OTSPoint3D(line1P1.x + uA * l1p2x, line1P1.y + uA * l1p2y, 0);
  210.     }

  211.     /**
  212.      * Compute the 2D intersection of two infinite lines. The Z-component of the lines is ignored. Both lines are defined by two
  213.      * points (that should be distinct). This version suffers loss of precision when called with very large coordinate values.
  214.      * @param line1P1 OTSPoint3D; first point of line 1
  215.      * @param line1P2 OTSPoint3D; second point of line 1
  216.      * @param line2P1 OTSPoint3D; first point of line 2
  217.      * @param line2P2 OTSPoint3D; second point of line 2
  218.      * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel
  219.      */
  220.     @Deprecated
  221.     public static OTSPoint3D intersectionOfLinesDumb(final OTSPoint3D line1P1, final OTSPoint3D line1P2,
  222.             final OTSPoint3D line2P1, final OTSPoint3D line2P2)
  223.     {
  224.         double determinant =
  225.                 (line1P1.x - line1P2.x) * (line2P1.y - line2P2.y) - (line1P1.y - line1P2.y) * (line2P1.x - line2P2.x);
  226.         if (Math.abs(determinant) < 0.0000001)
  227.         {
  228.             return null;
  229.         }
  230.         return new OTSPoint3D(
  231.                 ((line1P1.x * line1P2.y - line1P1.y * line1P2.x) * (line2P1.x - line2P2.x)
  232.                         - (line1P1.x - line1P2.x) * (line2P1.x * line2P2.y - line2P1.y * line2P2.x)) / determinant,
  233.                 ((line1P1.x * line1P2.y - line1P1.y * line1P2.x) * (line2P1.y - line2P2.y)
  234.                         - (line1P1.y - line1P2.y) * (line2P1.x * line2P2.y - line2P1.y * line2P2.x)) / determinant);
  235.     }

  236.     /**
  237.      * Compute the 2D intersection of two infinite lines. The Z-component of the lines is ignored. Both lines are defined by two
  238.      * points (that should be distinct).
  239.      * @param line1P1 OTSPoint3D; first point of line 1
  240.      * @param line1P2 OTSPoint3D; second point of line 1
  241.      * @param line2P1 OTSPoint3D; first point of line 2
  242.      * @param line2P2 OTSPoint3D; second point of line 2
  243.      * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel
  244.      */
  245.     public static OTSPoint3D intersectionOfLines(final OTSPoint3D line1P1, final OTSPoint3D line1P2, final OTSPoint3D line2P1,
  246.             final OTSPoint3D line2P2)
  247.     {
  248.         double l1p1x = line1P1.x;
  249.         double l1p1y = line1P1.y;
  250.         double l1p2x = line1P2.x - l1p1x;
  251.         double l1p2y = line1P2.y - l1p1y;
  252.         double l2p1x = line2P1.x - l1p1x;
  253.         double l2p1y = line2P1.y - l1p1y;
  254.         double l2p2x = line2P2.x - l1p1x;
  255.         double l2p2y = line2P2.y - l1p1y;
  256.         double determinant = (0 - l1p2x) * (l2p1y - l2p2y) - (0 - l1p2y) * (l2p1x - l2p2x);
  257.         if (Math.abs(determinant) < 0.0000001)
  258.         {
  259.             return null;
  260.         }
  261.         return new OTSPoint3D(l1p1x + (l1p2x * (l2p1x * l2p2y - l2p1y * l2p2x)) / determinant,
  262.                 l1p1y + (l1p2y * (l2p1x * l2p2y - l2p1y * l2p2x)) / determinant);
  263.     }

  264.     /**
  265.      * Project a point on a line segment (2D - Z-component is ignored). If the the projected points lies outside the line
  266.      * segment, the nearest end point of the line segment is returned. Otherwise the returned point lies between the end points
  267.      * of the line segment. <br>
  268.      * Adapted from <a href="http://paulbourke.net/geometry/pointlineplane/DistancePoint.java">example code provided by Paul
  269.      * Bourke</a>.
  270.      * @param segmentPoint1 OTSPoint3D; start of line segment
  271.      * @param segmentPoint2 OTSPoint3D; end of line segment
  272.      * @return Point2D.Double; either <cite>lineP1</cite>, or <cite>lineP2</cite> or a new OTSPoint3D that lies somewhere in
  273.      *         between those two. The Z-component of the result matches the Z-component of the line segment at that point
  274.      */
  275.     public final OTSPoint3D closestPointOnSegment(final OTSPoint3D segmentPoint1, final OTSPoint3D segmentPoint2)
  276.     {
  277.         double dX = segmentPoint2.x - segmentPoint1.x;
  278.         double dY = segmentPoint2.y - segmentPoint1.y;
  279.         if ((0 == dX) && (0 == dY))
  280.         {
  281.             return segmentPoint1;
  282.         }
  283.         final double u = ((this.x - segmentPoint1.x) * dX + (this.y - segmentPoint1.y) * dY) / (dX * dX + dY * dY);
  284.         if (u < 0)
  285.         {
  286.             return segmentPoint1;
  287.         }
  288.         else if (u > 1)
  289.         {
  290.             return segmentPoint2;
  291.         }
  292.         else
  293.         {
  294.             return interpolate(u, segmentPoint1, segmentPoint2);
  295.         }
  296.     }

  297.     /**
  298.      * Return the closest point on an OTSLine3D.
  299.      * @param line OTSLine3D; the line
  300.      * @param useHorizontalDistance boolean; if true; the horizontal distance is used to determine the closest point; if false;
  301.      *            the 3D distance is used to determine the closest point
  302.      * @return OTSPoint3D; the Z component of the returned point matches the Z-component of the line at that point
  303.      */
  304.     private OTSPoint3D internalClosestPointOnLine(final OTSLine3D line, final boolean useHorizontalDistance)
  305.     {
  306.         OTSPoint3D prevPoint = null;
  307.         double distance = Double.MAX_VALUE;
  308.         OTSPoint3D result = null;
  309.         for (OTSPoint3D nextPoint : line.getPoints())
  310.         {
  311.             if (null != prevPoint)
  312.             {
  313.                 OTSPoint3D closest = closestPointOnSegment(prevPoint, nextPoint);
  314.                 double thisDistance = useHorizontalDistance ? horizontalDistanceSI(closest) : distanceSI(closest);
  315.                 if (thisDistance < distance)
  316.                 {
  317.                     result = closest;
  318.                     distance = thisDistance;
  319.                 }
  320.             }
  321.             prevPoint = nextPoint;
  322.         }
  323.         return result;
  324.     }

  325.     /**
  326.      * Return the closest point on an OTSLine3D. This method takes the Z-component of this point and the line into account.
  327.      * @param line OTSLine3D; the line
  328.      * @return OTSPoint3D; the Z-component of the returned point matches the Z-component of the line at that point
  329.      */
  330.     public final OTSPoint3D closestPointOnLine(final OTSLine3D line)
  331.     {
  332.         return internalClosestPointOnLine(line, false);
  333.     }

  334.     /**
  335.      * Return the closest point on an OTSLine3D. This method ignores the Z-component of this point and the line when computing
  336.      * the distance.
  337.      * @param line OTSLine3D; the line
  338.      * @return OTSPoint3D; the Z-component of the returned point matches the Z-component of the line at that point
  339.      */
  340.     public final OTSPoint3D closestPointOnLine2D(final OTSLine3D line)
  341.     {
  342.         return internalClosestPointOnLine(line, true);
  343.     }

  344.     /**
  345.      * Return the point with a length of 1 to the origin.
  346.      * @return OTSPoint3D; the normalized point
  347.      */
  348.     public final OTSPoint3D normalize()
  349.     {
  350.         double length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
  351.         return this.translate(length);
  352.     }

  353.     /**
  354.      * Return this point translated by a factor from the origin.
  355.      * @param factor the translation factor
  356.      * @return OTSPoint3D; the translated point
  357.      */
  358.     public final OTSPoint3D translate(final double factor)
  359.     {
  360.         return new OTSPoint3D(this.x / factor, this.y / factor, this.z / factor);
  361.     }

  362.     /**
  363.      * Return the possible center points of a circle when two points and a radius are given.
  364.      * @param point1 OTSPoint3D; the first point
  365.      * @param point2 OTSPoint3D; the second point
  366.      * @param radius double; the radius
  367.      * @return List&lt;OTSPoint3D&gt; a list of zero, one or two points
  368.      */
  369.     public static final List<OTSPoint3D> circleCenter(final OTSPoint3D point1, final OTSPoint3D point2, final double radius)
  370.     {
  371.         List<OTSPoint3D> center = new ArrayList<>();
  372.         OTSPoint3D m = interpolate(0.5, point1, point2);
  373.         double h = point1.distanceSI(m);
  374.         if (radius < h) // no intersection
  375.         {
  376.             return center;
  377.         }
  378.         if (radius == h) // intersection at m
  379.         {
  380.             center.add(m);
  381.             return center;
  382.         }
  383.         OTSPoint3D p = new OTSPoint3D(point2.y - point1.y, point1.x - point2.x).normalize();
  384.         double d = Math.sqrt(radius * radius - h * h); // distance of center from m
  385.         center.add(new OTSPoint3D(m.x + d * p.x, m.y + d * p.y, m.z));
  386.         center.add(new OTSPoint3D(m.x - d * p.x, m.y - d * p.y, m.z));
  387.         return center;
  388.     }

  389.     /**
  390.      * Return the possible intersections between two circles.
  391.      * @param center1 OTSPoint3D; the center of circle 1
  392.      * @param radius1 double; the radius of circle 1
  393.      * @param center2 OTSPoint3D; the center of circle 2
  394.      * @param radius2 double; the radius of circle 2
  395.      * @return List&lt;OTSPoint3D&gt; a list of zero, one or two points
  396.      */
  397.     public static final List<OTSPoint3D> circleIntersections(final OTSPoint3D center1, final double radius1,
  398.             final OTSPoint3D center2, final double radius2)
  399.     {
  400.         List<OTSPoint3D> center = new ArrayList<>();
  401.         OTSPoint3D m = interpolate(radius1 / (radius1 + radius2), center1, center2);
  402.         double h = center1.distanceSI(m);
  403.         if (radius1 < h) // no intersection
  404.         {
  405.             return center;
  406.         }
  407.         if (radius1 == h) // intersection at m
  408.         {
  409.             center.add(m);
  410.             return center;
  411.         }
  412.         OTSPoint3D p = new OTSPoint3D(center2.y - center1.y, center1.x - center2.x).normalize();
  413.         double d = Math.sqrt(radius1 * radius1 - h * h); // distance of center from m
  414.         center.add(new OTSPoint3D(m.x + d * p.x, m.y + d * p.y, m.z));
  415.         center.add(new OTSPoint3D(m.x - d * p.x, m.y - d * p.y, m.z));
  416.         return center;
  417.     }

  418.     /**
  419.      * @param point the point to which the distance has to be calculated.
  420.      * @return the distance in 3D according to Pythagoras, expressed in the SI unit for length (meter)
  421.      */
  422.     public final double distanceSI(final OTSPoint3D point)
  423.     {
  424.         double dx = point.x - this.x;
  425.         double dy = point.y - this.y;
  426.         double dz = point.z - this.z;

  427.         return Math.sqrt(dx * dx + dy * dy + dz * dz);
  428.     }

  429.     /**
  430.      * @param point the point to which the distance has to be calculated.
  431.      * @return the distance in 3D according to Pythagoras, expressed in the SI unit for length (meter)
  432.      */
  433.     public final double horizontalDistanceSI(final OTSPoint3D point)
  434.     {
  435.         double dx = point.x - this.x;
  436.         double dy = point.y - this.y;

  437.         return Math.sqrt(dx * dx + dy * dy);
  438.     }

  439.     /**
  440.      * @param point the point to which the distance has to be calculated.
  441.      * @return the distance in 3D according to Pythagoras
  442.      */
  443.     public final Length horizontalDistance(final OTSPoint3D point)
  444.     {
  445.         return new Length(horizontalDistanceSI(point), LengthUnit.SI);
  446.     }

  447.     /**
  448.      * @param point the point to which the distance has to be calculated.
  449.      * @return the distance in 3D according to Pythagoras
  450.      */
  451.     public final Length distance(final OTSPoint3D point)
  452.     {
  453.         return new Length(distanceSI(point), LengthUnit.SI);
  454.     }

  455.     /**
  456.      * @return the equivalent geotools Coordinate of this point.
  457.      */
  458.     public final Coordinate getCoordinate()
  459.     {
  460.         return new Coordinate(this.x, this.y, this.z);
  461.     }

  462.     /**
  463.      * @return the equivalent DSOL DirectedPoint of this point. Should the result be cached?
  464.      */
  465.     public final DirectedPoint getDirectedPoint()
  466.     {
  467.         return new DirectedPoint(this.x, this.y, this.z);
  468.     }

  469.     /**
  470.      * @return a Point2D with the x and y structure.
  471.      */
  472.     public final Point2D getPoint2D()
  473.     {
  474.         return new Point2D.Double(this.x, this.y);
  475.     }

  476.     /** {@inheritDoc} */
  477.     @Override
  478.     public final DirectedPoint getLocation()
  479.     {
  480.         return getDirectedPoint();
  481.     }

  482.     /**
  483.      * This method returns a sphere with a diameter of half a meter as the default bounds for a point. {@inheritDoc}
  484.      */
  485.     @Override
  486.     public final Bounds getBounds()
  487.     {
  488.         return new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 0.5);
  489.     }

  490.     /** {@inheritDoc} */
  491.     @Override
  492.     @SuppressWarnings("checkstyle:designforextension")
  493.     public String toString()
  494.     {
  495.         return String.format("(%.3f,%.3f,%.3f)", this.x, this.y, this.z);
  496.     }

  497.     /** {@inheritDoc} */
  498.     @Override
  499.     @SuppressWarnings("checkstyle:designforextension")
  500.     public int hashCode()
  501.     {
  502.         final int prime = 31;
  503.         int result = 1;
  504.         long temp;
  505.         temp = Double.doubleToLongBits(this.x);
  506.         result = prime * result + (int) (temp ^ (temp >>> 32));
  507.         temp = Double.doubleToLongBits(this.y);
  508.         result = prime * result + (int) (temp ^ (temp >>> 32));
  509.         temp = Double.doubleToLongBits(this.z);
  510.         result = prime * result + (int) (temp ^ (temp >>> 32));
  511.         return result;
  512.     }

  513.     /** {@inheritDoc} */
  514.     @Override
  515.     @SuppressWarnings({ "checkstyle:designforextension", "checkstyle:needbraces" })
  516.     public boolean equals(final Object obj)
  517.     {
  518.         if (this == obj)
  519.             return true;
  520.         if (obj == null)
  521.             return false;
  522.         if (getClass() != obj.getClass())
  523.             return false;
  524.         OTSPoint3D other = (OTSPoint3D) obj;
  525.         if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x))
  526.             return false;
  527.         if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y))
  528.             return false;
  529.         if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z))
  530.             return false;
  531.         return true;
  532.     }

  533. }