1 package org.opentrafficsim.core.geometry;
2
3 import java.awt.geom.Point2D;
4 import java.io.Serializable;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import org.djunits.unit.DirectionUnit;
9 import org.djunits.unit.LengthUnit;
10 import org.djunits.unit.Unit;
11 import org.djunits.value.storage.StorageType;
12 import org.djunits.value.vdouble.scalar.Direction;
13 import org.djunits.value.vdouble.scalar.Length;
14 import org.djunits.value.vdouble.scalar.base.DoubleScalarInterface;
15 import org.djunits.value.vdouble.vector.base.DoubleVector;
16 import org.djunits.value.vdouble.vector.base.DoubleVectorInterface;
17 import org.djutils.draw.point.Point3d;
18 import org.locationtech.jts.geom.Coordinate;
19 import org.locationtech.jts.geom.Point;
20
21 import nl.tudelft.simulation.dsol.animation.Locatable;
22 import nl.tudelft.simulation.language.d3.CartesianPoint;
23
24 /**
25 * 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
26 * units, i.e. in meters. A distance between two points is therefore also in meters.
27 * <p>
28 * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
29 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
30 * <p>
31 * $LastChangedDate: 2015-07-16 10:20:53 +0200 (Thu, 16 Jul 2015) $, @version $Revision: 1124 $, by $Author: pknoppers $,
32 * initial version Jul 22, 2015 <br>
33 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
34 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
35 * @author <a href="http://www.citg.tudelft.nl">Guus Tamminga</a>
36 */
37 public class OTSPoint3D implements Locatable, Serializable
38 {
39 /** */
40 private static final long serialVersionUID = 20150722L;
41
42 /** The internal representation of the point; x-coordinate. */
43 @SuppressWarnings("checkstyle:visibilitymodifier")
44 public final double x;
45
46 /** The internal representation of the point; y-coordinate. */
47 @SuppressWarnings("checkstyle:visibilitymodifier")
48 public final double y;
49
50 /** The internal representation of the point; z-coordinate. */
51 @SuppressWarnings("checkstyle:visibilitymodifier")
52 public final double z;
53
54 /**
55 * The x, y and z in the point are assumed to be in meters relative to an origin.
56 * @param x double; x-coordinate
57 * @param y double; y-coordinate
58 * @param z double; z-coordinate
59 */
60 public OTSPoint3D(final double x, final double y, final double z)
61 {
62 this.x = x;
63 this.y = y;
64 this.z = z;
65 }
66
67 /**
68 * @param xyz array with three elements; x, y and z are assumed to be in meters relative to an origin.
69 */
70 public OTSPoint3D(final double[] xyz)
71 {
72 this(xyz[0], xyz[1], (xyz.length > 2) ? xyz[2] : 0.0);
73 }
74
75 /**
76 * @param point OTSPoint3D; a point to "clone".
77 */
78 public OTSPoint3Deometry/OTSPoint3D.html#OTSPoint3D">OTSPoint3D(final OTSPoint3D point)
79 {
80 this(point.x, point.y, point.z);
81 }
82
83 /**
84 * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
85 * origin.
86 */
87 public OTSPoint3D(final Point3d point)
88 {
89 this(point.x, point.y, point.z);
90 }
91
92 /**
93 * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
94 * origin.
95 */
96 public OTSPoint3D(final CartesianPoint point)
97 {
98 this(point.x, point.y, point.z);
99 }
100
101 /**
102 * @param point javax.vecmath 3D double point; the x, y and z in the point are assumed to be in meters relative to an
103 * origin.
104 */
105 public OTSPoint3D(final DirectedPoint point)
106 {
107 this(point.x, point.y, point.z);
108 }
109
110 /**
111 * @param point2d java.awt 2D point, z-coordinate will be zero; the x and y in the point are assumed to be in meters
112 * relative to an origin.
113 */
114 public OTSPoint3D(final Point2D point2d)
115 {
116 this(point2d.getX(), point2d.getY(), 0.0);
117 }
118
119 /**
120 * @param coordinate geotools coordinate; the x, y and z in the coordinate are assumed to be in meters relative to an
121 * origin.
122 */
123 public OTSPoint3D(final Coordinate coordinate)
124 {
125 this(coordinate.x, coordinate.y, Double.isNaN(coordinate.getZ()) ? 0.0 : coordinate.getZ());
126 }
127
128 /**
129 * @param point geotools point; z-coordinate will be zero; the x and y in the point are assumed to be in meters relative to
130 * an origin.
131 */
132 public OTSPoint3D(final Point point)
133 {
134 this(point.getX(), point.getY(), 0.0);
135 }
136
137 /**
138 * The x and y in the point are assumed to be in meters relative to an origin. z will be set to 0.
139 * @param x double; x-coordinate
140 * @param y double; y-coordinate
141 */
142 public OTSPoint3D(final double x, final double y)
143 {
144 this(x, y, 0.0);
145 }
146
147 /**
148 * Interpolate (or extrapolate) between (outside) two given points.
149 * @param ratio double; 0 selects the zeroValue point, 1 selects the oneValue point, 0.5 selects a point halfway, etc.
150 * @param zeroValue OTSPoint3D; the point that is returned when ratio equals 0
151 * @param oneValue OTSPoint3D; the point that is returned when ratio equals 1
152 * @return OTSPoint3D
153 */
154 public static OTSPoint3D interpolate(finalOTSPoint3DPoint3D.html#OTSPoint3D">OTSPoint3Ddouble ratio, final OTSPoint3DPoint3D.html#OTSPoint3D">OTSPoint3D zeroValue, final OTSPoint3D oneValue)
155 {
156 double complement = 1 - ratio;
157 return new OTSPoint3D(complement * zeroValue.x + ratio * oneValue.x, complement * zeroValue.y + ratio * oneValue.y,
158 complement * zeroValue.z + ratio * oneValue.z);
159 }
160
161 /**
162 * Compute the 2D intersection of two line segments. The Z-component of the lines is ignored. Both line segments are defined
163 * by two points (that should be distinct). This version suffers loss of precision when called with very large coordinate
164 * values.
165 * @param line1P1 OTSPoint3D; first point of line segment 1
166 * @param line1P2 OTSPoint3D; second point of line segment 1
167 * @param line2P1 OTSPoint3D; first point of line segment 2
168 * @param line2P2 OTSPoint3D; second point of line segment 2
169 * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel, or do not intersect
170 */
171 @Deprecated
172 public static OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3Dt3D">OTSPoint3D intersectionOfLineSegmentsDumb(final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line1P1, final OTSPoint3D line1P2,
173 final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line2P1, final OTSPoint3D line2P2)
174 {
175 double denominator =
176 (line2P2.y - line2P1.y) * (line1P2.x - line1P1.x) - (line2P2.x - line2P1.x) * (line1P2.y - line1P1.y);
177 if (denominator == 0f)
178 {
179 return null; // lines are parallel (they might even be on top of each other, but we don't check that)
180 }
181 double uA = ((line2P2.x - line2P1.x) * (line1P1.y - line2P1.y) - (line2P2.y - line2P1.y) * (line1P1.x - line2P1.x))
182 / denominator;
183 if ((uA < 0f) || (uA > 1f))
184 {
185 return null; // intersection outside line 1
186 }
187 double uB = ((line1P2.x - line1P1.x) * (line1P1.y - line2P1.y) - (line1P2.y - line1P1.y) * (line1P1.x - line2P1.x))
188 / denominator;
189 if (uB < 0 || uB > 1)
190 {
191 return null; // intersection outside line 2
192 }
193 return new OTSPoint3D(line1P1.x + uA * (line1P2.x - line1P1.x), line1P1.y + uA * (line1P2.y - line1P1.y), 0);
194 }
195
196 /**
197 * Compute the 2D intersection of two line segments. The Z-component of the lines is ignored. Both line segments are defined
198 * by two points (that should be distinct).
199 * @param line1P1 OTSPoint3D; first point of line segment 1
200 * @param line1P2 OTSPoint3D; second point of line segment 1
201 * @param line2P1 OTSPoint3D; first point of line segment 2
202 * @param line2P2 OTSPoint3D; second point of line segment 2
203 * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel, or do not intersect
204 */
205 public static OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3DPoint3D">OTSPoint3D intersectionOfLineSegments(final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line1P1, final OTSPoint3D line1P2,
206 final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line2P1, final OTSPoint3D line2P2)
207 {
208 double l1p1x = line1P1.x;
209 double l1p1y = line1P1.y;
210 double l1p2x = line1P2.x - l1p1x;
211 double l1p2y = line1P2.y - l1p1y;
212 double l2p1x = line2P1.x - l1p1x;
213 double l2p1y = line2P1.y - l1p1y;
214 double l2p2x = line2P2.x - l1p1x;
215 double l2p2y = line2P2.y - l1p1y;
216 double denominator = (l2p2y - l2p1y) * l1p2x - (l2p2x - l2p1x) * l1p2y;
217 if (denominator == 0.0)
218 {
219 return null; // lines are parallel (they might even be on top of each other, but we don't check that)
220 }
221 double uA = ((l2p2x - l2p1x) * (-l2p1y) - (l2p2y - l2p1y) * (-l2p1x)) / denominator;
222 // System.out.println("uA is " + uA);
223 if ((uA < 0.0) || (uA > 1.0))
224 {
225 return null; // intersection outside line 1
226 }
227 double uB = (l1p2y * l2p1x - l1p2x * l2p1y) / denominator;
228 // System.out.println("uB is " + uB);
229 if (uB < 0.0 || uB > 1.0)
230 {
231 return null; // intersection outside line 2
232 }
233 return new OTSPoint3D(line1P1.x + uA * l1p2x, line1P1.y + uA * l1p2y, 0);
234 }
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). This version suffers loss of precision when called with very large coordinate values.
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 @Deprecated
246 public static OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3DOTSPoint3D">OTSPoint3D intersectionOfLinesDumb(final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line1P1, final OTSPoint3D line1P2,
247 final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line2P1, final OTSPoint3D line2P2)
248 {
249 double determinant =
250 (line1P1.x - line1P2.x) * (line2P1.y - line2P2.y) - (line1P1.y - line1P2.y) * (line2P1.x - line2P2.x);
251 if (Math.abs(determinant) < 0.0000001)
252 {
253 return null;
254 }
255 return new OTSPoint3D(
256 ((line1P1.x * line1P2.y - line1P1.y * line1P2.x) * (line2P1.x - line2P2.x)
257 - (line1P1.x - line1P2.x) * (line2P1.x * line2P2.y - line2P1.y * line2P2.x)) / determinant,
258 ((line1P1.x * line1P2.y - line1P1.y * line1P2.x) * (line2P1.y - line2P2.y)
259 - (line1P1.y - line1P2.y) * (line2P1.x * line2P2.y - line2P1.y * line2P2.x)) / determinant);
260 }
261
262 /**
263 * Compute the 2D intersection of two infinite lines. The Z-component of the lines is ignored. Both lines are defined by two
264 * points (that should be distinct).
265 * @param line1P1 OTSPoint3D; first point of line 1
266 * @param line1P2 OTSPoint3D; second point of line 1
267 * @param line2P1 OTSPoint3D; first point of line 2
268 * @param line2P2 OTSPoint3D; second point of line 2
269 * @return OTSPoint3D; the intersection of the two lines, or null if the lines are (almost) parallel
270 */
271 public static OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3Dtml#OTSPoint3D">OTSPoint3D intersectionOfLines(final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line1P1, final OTSPoint3DTSPoint3D.html#OTSPoint3D">OTSPoint3D line1P2, final OTSPoint3D line2P1,
272 final OTSPoint3D line2P2)
273 {
274 double l1p1x = line1P1.x;
275 double l1p1y = line1P1.y;
276 double l1p2x = line1P2.x - l1p1x;
277 double l1p2y = line1P2.y - l1p1y;
278 double l2p1x = line2P1.x - l1p1x;
279 double l2p1y = line2P1.y - l1p1y;
280 double l2p2x = line2P2.x - l1p1x;
281 double l2p2y = line2P2.y - l1p1y;
282 double determinant = (0 - l1p2x) * (l2p1y - l2p2y) - (0 - l1p2y) * (l2p1x - l2p2x);
283 if (Math.abs(determinant) < 0.0000001)
284 {
285 return null;
286 }
287 return new OTSPoint3D(l1p1x + (l1p2x * (l2p1x * l2p2y - l2p1y * l2p2x)) / determinant,
288 l1p1y + (l1p2y * (l2p1x * l2p2y - l2p1y * l2p2x)) / determinant);
289 }
290
291 /**
292 * Project a point on a line segment (2D - Z-component is ignored). If the the projected points lies outside the line
293 * segment, the nearest end point of the line segment is returned. Otherwise the returned point lies between the end points
294 * of the line segment. <br>
295 * Adapted from <a href="http://paulbourke.net/geometry/pointlineplane/DistancePoint.java">example code provided by Paul
296 * Bourke</a>.
297 * @param segmentPoint1 OTSPoint3D; start of line segment
298 * @param segmentPoint2 OTSPoint3D; end of line segment
299 * @return Point2D.Double; either <cite>lineP1</cite>, or <cite>lineP2</cite> or a new OTSPoint3D that lies somewhere in
300 * between those two. The Z-component of the result matches the Z-component of the line segment at that point
301 */
302 public final OTSPoint3Dt3D.html#OTSPoint3D">OTSPoint3Dl#OTSPoint3D">OTSPoint3D closestPointOnSegment(final OTSPoint3Dt3D.html#OTSPoint3D">OTSPoint3D segmentPoint1, final OTSPoint3D segmentPoint2)
303 {
304 double dX = segmentPoint2.x - segmentPoint1.x;
305 double dY = segmentPoint2.y - segmentPoint1.y;
306 if ((0 == dX) && (0 == dY))
307 {
308 return segmentPoint1;
309 }
310 final double u = ((this.x - segmentPoint1.x) * dX + (this.y - segmentPoint1.y) * dY) / (dX * dX + dY * dY);
311 if (u < 0)
312 {
313 return segmentPoint1;
314 }
315 else if (u > 1)
316 {
317 return segmentPoint2;
318 }
319 else
320 {
321 return interpolate(u, segmentPoint1, segmentPoint2);
322 }
323 }
324
325 /**
326 * Return the closest point on an OTSLine3D.
327 * @param line OTSLine3D; the line
328 * @param useHorizontalDistance boolean; if true; the horizontal distance is used to determine the closest point; if false;
329 * the 3D distance is used to determine the closest point
330 * @return OTSPoint3D; the Z component of the returned point matches the Z-component of the line at that point
331 */
332 private OTSPoint3D internalClosestPointOnLine(final OTSLine3D line, final boolean useHorizontalDistance)
333 {
334 OTSPoint3D prevPoint = null;
335 double distance = Double.MAX_VALUE;
336 OTSPoint3D result = null;
337 for (OTSPoint3D nextPoint : line.getPoints())
338 {
339 if (null != prevPoint)
340 {
341 OTSPoint3D closest = closestPointOnSegment(prevPoint, nextPoint);
342 double thisDistance = useHorizontalDistance ? horizontalDistanceSI(closest) : distanceSI(closest);
343 if (thisDistance < distance)
344 {
345 result = closest;
346 distance = thisDistance;
347 }
348 }
349 prevPoint = nextPoint;
350 }
351 return result;
352 }
353
354 /**
355 * Return the closest point on an OTSLine3D. This method takes the Z-component of this point and the line into account.
356 * @param line OTSLine3D; the line
357 * @return OTSPoint3D; the Z-component of the returned point matches the Z-component of the line at that point
358 */
359 public final OTSPoint3D closestPointOnLine(final OTSLine3D line)
360 {
361 return internalClosestPointOnLine(line, false);
362 }
363
364 /**
365 * Return the closest point on an OTSLine3D. This method ignores the Z-component of this point and the line when computing
366 * the distance.
367 * @param line OTSLine3D; the line
368 * @return OTSPoint3D; the Z-component of the returned point matches the Z-component of the line at that point
369 */
370 public final OTSPoint3D closestPointOnLine2D(final OTSLine3D line)
371 {
372 return internalClosestPointOnLine(line, true);
373 }
374
375 /**
376 * Return the point with a length of 1 to the origin.
377 * @return OTSPoint3D; the normalized point
378 */
379 public final OTSPoint3D normalize()
380 {
381 double length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
382 return this.translate(length);
383 }
384
385 /**
386 * Return this point translated by a factor from the origin.
387 * @param factor double; the translation factor
388 * @return OTSPoint3D; the translated point
389 */
390 public final OTSPoint3D translate(final double factor)
391 {
392 return new OTSPoint3D(this.x / factor, this.y / factor, this.z / factor);
393 }
394
395 /**
396 * Return the possible center points of a circle (sphere), given two points and a radius. Only points with Z-coordinate
397 * equal to the mean of the given points are returned. (Without this restriction on the Z-coordinate, the result set would
398 * be either empty, a single point, or all points on a circle.)
399 * @param point1 OTSPoint3D; the first point
400 * @param point2 OTSPoint3D; the second point
401 * @param radius double; the radius
402 * @return List<OTSPoint3D> a list of zero, one or two points
403 */
404 public static final List<OTSPoint3D> circleCenter(final OTSPoint3DOTSPoint3D.html#OTSPoint3D">OTSPoint3D point1, final OTSPoint3D point2, final double radius)
405 {
406 List<OTSPoint3D> result = new ArrayList<>();
407 OTSPoint3D m = interpolate(0.5, point1, point2);
408 double h = point1.distanceSI(m);
409 if (radius < h) // no intersection
410 {
411 return result;
412 }
413 if (radius == h) // intersection at m
414 {
415 result.add(m);
416 return result;
417 }
418 OTSPoint3Dmetry/OTSPoint3D.html#OTSPoint3D">OTSPoint3D p = new OTSPoint3D(point2.y - point1.y, point1.x - point2.x).normalize();
419 double d = Math.sqrt(radius * radius - h * h); // distance of center from m
420 d = Math.sqrt(radius * radius - h * h);
421 result.add(new OTSPoint3D(m.x + d * p.x, m.y + d * p.y, m.z));
422 result.add(new OTSPoint3D(m.x - d * p.x, m.y - d * p.y, m.z));
423 return result;
424 }
425
426 /**
427 * Return the possible intersections between two circles.
428 * @param center1 OTSPoint3D; the center of circle 1
429 * @param radius1 double; the radius of circle 1
430 * @param center2 OTSPoint3D; the center of circle 2
431 * @param radius2 double; the radius of circle 2
432 * @return List<OTSPoint3D> a list of zero, one or two points
433 */
434 public static final List<OTSPoint3D> circleIntersections(final OTSPoint3D center1, final double radius1,
435 final OTSPoint3D center2, final double radius2)
436 {
437 List<OTSPoint3D> center = new ArrayList<>();
438 OTSPoint3D m = interpolate(radius1 / (radius1 + radius2), center1, center2);
439 double h = center1.distanceSI(m);
440 if (radius1 < h) // no intersection
441 {
442 return center;
443 }
444 if (radius1 == h) // intersection at m
445 {
446 center.add(m);
447 return center;
448 }
449 OTSPoint3Dmetry/OTSPoint3D.html#OTSPoint3D">OTSPoint3D p = new OTSPoint3D(center2.y - center1.y, center1.x - center2.x).normalize();
450 double d = Math.sqrt(radius1 * radius1 - h * h); // distance of center from m
451 center.add(new OTSPoint3D(m.x + d * p.x, m.y + d * p.y, m.z));
452 center.add(new OTSPoint3D(m.x - d * p.x, m.y - d * p.y, m.z));
453 return center;
454 }
455
456 /**
457 * @param point OTSPoint3D; the point to which the distance has to be calculated.
458 * @return the distance in 3D according to Pythagoras, expressed in the SI unit for length (meter)
459 */
460 public final double distanceSI(final OTSPoint3D point)
461 {
462 double dx = point.x - this.x;
463 double dy = point.y - this.y;
464 double dz = point.z - this.z;
465
466 return Math.sqrt(dx * dx + dy * dy + dz * dz);
467 }
468
469 /**
470 * @param point OTSPoint3D; the point to which the distance has to be calculated.
471 * @return the distance in 3D according to Pythagoras, expressed in the SI unit for length (meter)
472 */
473 public final double horizontalDistanceSI(final OTSPoint3D point)
474 {
475 double dx = point.x - this.x;
476 double dy = point.y - this.y;
477
478 return Math.sqrt(dx * dx + dy * dy);
479 }
480
481 /**
482 * @param point OTSPoint3D; the point to which the distance has to be calculated.
483 * @return the distance in 3D according to Pythagoras
484 */
485 public final Length horizontalDistance(final OTSPoint3D point)
486 {
487 return new Length(horizontalDistanceSI(point), LengthUnit.SI);
488 }
489
490 /**
491 * Compute the distance to another point.
492 * @param point OTSPoint3D; the point to which the distance has to be calculated.
493 * @return the distance in 3D according to Pythagoras
494 */
495 public final Length distance(final OTSPoint3D point)
496 {
497 return new Length(distanceSI(point), LengthUnit.SI);
498 }
499
500 /**
501 * Compute the horizontal direction to another point.
502 * @param point OTSPoint3D; the other point
503 * @return double; the direction in radians
504 */
505 public final double horizontalDirectionSI(final OTSPoint3D point)
506 {
507 return Math.atan2(point.y - this.y, point.x - this.x);
508 }
509
510 /**
511 * Compute the horizontal direction to another point.
512 * @param point OTSPoint3D; the other point
513 * @return double; the direction in radians
514 */
515 public final Direction horizontalDirection(final OTSPoint3D point)
516 {
517 return Direction.instantiateSI(Math.atan2(point.y - this.y, point.x - this.x));
518 }
519
520 /**
521 * @return the equivalent geotools Coordinate of this point.
522 */
523 public final Coordinate getCoordinate()
524 {
525 return new Coordinate(this.x, this.y, this.z);
526 }
527
528 /**
529 * @return the equivalent DSOL DirectedPoint of this point. Should the result be cached?
530 */
531 public final DirectedPoint getDirectedPoint()
532 {
533 return new DirectedPoint(this.x, this.y, this.z);
534 }
535
536 /**
537 * @return a Point2D with the x and y structure.
538 */
539 public final Point2D getPoint2D()
540 {
541 return new Point2D.Double(this.x, this.y);
542 }
543
544 /** {@inheritDoc} */
545 @Override
546 public final DirectedPoint getLocation()
547 {
548 return getDirectedPoint();
549 }
550
551 /**
552 * This method returns a sphere with a diameter of half a meter as the default bounds for a point. {@inheritDoc}
553 */
554 @Override
555 public final Bounds getBounds()
556 {
557 return new Bounds();
558 }
559
560 /**
561 * Create a DENSE DoubleVector with the x, y and z values of this OTSPoint3D.
562 * @param unit U; unit of the values in this OTSPoint3D (and also the display unit of the returned DoubleVector)
563 * @return DoubleVector; the constructed DoubleVector, size is 3; first value is x, second is y, third is z
564 * @param <U> the unit type
565 * @param <S> the corresponding scalar type
566 * @param <V> the corresponding vector type
567 */
568 public <U extends Unit<U>, S extends DoubleScalarInterface<U, S>,
569 V extends DoubleVectorInterface<U, S, V>> V doubleVector(final U unit)
570 {
571 return DoubleVector.instantiate(new double[] { this.x, this.y, this.z }, unit, StorageType.DENSE);
572 }
573
574 /**
575 * Construct a Direction from the rotZ component of a DirectedPoint.
576 * @param directedPoint DirectedPoint; the DirectedPoint
577 * @param directionUnit DirectionUnit; the unit in which the rotZ of <code>directedPoint</code> is expressed and which is
578 * also the display unit of the returned Direction
579 * @return Direction; the horizontal direction (rotZ) of the <code>directedPoint</code> with display unit
580 * <code>directionUnit</code>
581 */
582 public static Direction direction(final DirectedPoint directedPoint, final DirectionUnit directionUnit)
583 {
584 return new Direction(directedPoint.getRotZ(), directionUnit);
585 }
586
587 /** {@inheritDoc} */
588 @Override
589 @SuppressWarnings("checkstyle:designforextension")
590 public String toString()
591 {
592 return String.format("(%.3f,%.3f,%.3f)", this.x, this.y, this.z);
593 }
594
595 /** {@inheritDoc} */
596 @Override
597 @SuppressWarnings("checkstyle:designforextension")
598 public int hashCode()
599 {
600 final int prime = 31;
601 int result = 1;
602 long temp;
603 temp = Double.doubleToLongBits(this.x);
604 result = prime * result + (int) (temp ^ (temp >>> 32));
605 temp = Double.doubleToLongBits(this.y);
606 result = prime * result + (int) (temp ^ (temp >>> 32));
607 temp = Double.doubleToLongBits(this.z);
608 result = prime * result + (int) (temp ^ (temp >>> 32));
609 return result;
610 }
611
612 /** {@inheritDoc} */
613 @Override
614 @SuppressWarnings({ "checkstyle:designforextension", "checkstyle:needbraces" })
615 public boolean equals(final Object obj)
616 {
617 if (this == obj)
618 return true;
619 if (obj == null)
620 return false;
621 if (getClass() != obj.getClass())
622 return false;
623 OTSPoint3D../../../org/opentrafficsim/core/geometry/OTSPoint3D.html#OTSPoint3D">OTSPoint3D other = (OTSPoint3D) obj;
624 if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x))
625 return false;
626 if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y))
627 return false;
628 if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z))
629 return false;
630 return true;
631 }
632
633 }