2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
.geom
;
9 import gov
.nasa
.worldwind
.*;
12 * <code>Point</code> represents an homogeneous cartesian point in 3 dimensional space.
14 * Instances of <code>Point</code> are immutable. </p>
17 * @version $Id: Point.java 1750 2007-05-06 19:53:06Z tgaskins $
19 public class Point
implements gov
.nasa
.worldwind
.Cacheable
21 private final double x
;
22 private final double y
;
23 private final double z
;
24 private final double w
;
27 * Value of <code>ZERO</code> is (0,0,0)
29 public static final Point ZERO
= new Point(0, 0, 0);
31 * Value of <code>UNIT_X</code> is (1,0,0)
33 public static final Point UNIT_X
= new Point(1, 0, 0);
35 * Value of <code>UNIT_Y</code> is (0,1,0)
37 public static final Point UNIT_Y
= new Point(0, 1, 0);
39 * Value of <code>UNIT_Z</code> is (0,0,1)
41 public static final Point UNIT_Z
= new Point(0, 0, 1);
44 * Constructs a new <code>Point</code> from four parameters.
46 * @param x the x position of the <code>Point</code>
47 * @param y the y position of the <code>Point</code>
48 * @param z the z position of the <code>Point</code>
49 * @param w the w position of the <code>Point</code>
51 public Point(double x
, double y
, double z
, double w
)
60 * Constructs a new <code>Point</code> from three parameters. The <code>w</code> field is set to 1.
62 * @param x the x position of the <code>Point</code>
63 * @param y the y position of the <code>Point</code>
64 * @param z the z position of the <code>Point</code>
66 public Point(double x
, double y
, double z
)
75 * Returns the w element of this Point. This method differs from <code>w()</code> in that subclasses may override
78 * @return the w element of this <code>Point</code>
87 * Returns the x element of this Point. This method differs from <code>x()</code> in that subclasses may override
90 * @return the x element of this <code>Point</code>
99 * Returns the y element of this Point. This method differs from <code>y()</code> in that subclasses may override
102 * @return the y element of this <code>Point</code>
111 * Returns the y element of this Point. This method differs from <code>y()</code> in that subclasses may override
114 * @return the y element of this <code>Point</code>
123 * Returns the x element of this <code>Point</code>.
125 * @return the x element of this <code>Point</code>
127 public final double x()
133 * Returns the y element of this <code>Point</code>.
135 * @return the y element of this <code>Point</code>
137 public final double y()
143 * Returns the z element of this <code>Point</code>.
145 * @return the z element of this <code>Point</code>
147 public final double z()
153 * Returns the w element of this <code>Point</code>.
155 * @return the w element of this <code>Point</code>
157 public final double w()
163 * Calculates the sum of these two <code>Point</code>s. The resulting <code>Point</code> has x value equivalent to
164 * <code>this.x + p.x</code>, the results for y,z and w are calculated in the same way.
166 * @param p the <code>Point</code> to be added to this <code>Point</code>
167 * @return a <code>Point</code> resulting from the algebraic operation <code>this + p</code>
168 * @throws IllegalArgumentException if <code>p</code> is null
170 public final Point
add(Point p
)
174 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
175 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
176 throw new IllegalArgumentException(message
);
179 return new Point(this.x
+ p
.x
, this.y
+ p
.y
, this.z
+ p
.z
, 1);
183 * Calculates the difference between these two <code>Point</code>s. The resulting <code>Point</code> is equivalent
184 * to <code>this.x - p.x</code>, the results for y, z and w are calculated in the same way.
186 * @param p the <code>Point</code> to subtract from this <code>Point</code>
187 * @return a <code>Point</code> resulting from the algebraic operation<code>this - p</code>
188 * @throws IllegalArgumentException if <code>p</code> is null
190 public final Point
subtract(Point p
)
194 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
195 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
196 throw new IllegalArgumentException(message
);
199 return new Point(this.x
- p
.x
, this.y
- p
.y
, this.z
- p
.z
, 1);
203 * Multiplies this <code>Point</code> by a scalar quantity. This method simply returns a new <code>Point</code>
204 * whose values each equal the old <code>Point</code>'s corresponding value multiplied by this scalar.
206 * @param s the scalar to be multiplied by
207 * @return a <code>Point</code> resulting from the scalar multiplication of <code>this</code> and <code>s</code>
209 public final Point
multiply(double s
)
211 return new Point(this.x
* s
, this.y
* s
, this.z
* s
, 1);
214 public final Point
scale(double sx
, double sy
, double sz
)
216 return new Point(this.x
* sx
, this.y
* sy
, this.z
* sz
, this.w
);
219 public final Point
normalize()
221 double s
= 1d
/ this.length();
222 return this.scale(s
, s
, s
);
226 * Performs a dot product of the x, y and z coorinates of <code>this</code> and <code>p</code>.
228 * @param p the <code>Point</code> to perform a dot product with
229 * @return the scalar product of <code>this</code> and <code>p</code>
230 * @throws IllegalArgumentException if <code>p</code> is null
232 public final double dot(Point p
)
236 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
237 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
238 throw new IllegalArgumentException(message
);
241 return this.x
* p
.x
+ this.y
* p
.y
+ this.z
* p
.z
;
245 * Performs a dot product of the x, y and z coorinates of <code>this</code> with itself. This method is equivalent
246 * to <code>this.dot(this)</code>.
249 * A useful characteristic of this method is that the resulting value is the square of this <code>Point</code>'s
250 * distance from <code>ZERO</code>. Finding the square of the distance from the origin in this manner is preferred
251 * over finding the square by first finding the length and then squaring it because this is faster and less prone to
252 * loss of precision. </p>
254 * @return this <code>Point</code> dotted with itself
257 public final double selfDot()
259 return this.x
* this.x
+ this.y
* this.y
+ this.z
* this.z
;
263 * Performs a dot product of all four components of <code>this</code> and <code>p</code>.
265 * @param p the <code>Point</code> to perform a dot product with
266 * @return the scalar product of <code>this</code> and <code>p</code>
267 * @throws IllegalArgumentException if <code>p</code> is null
269 public final double dot4(Point p
)
273 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
274 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
275 throw new IllegalArgumentException(message
);
278 return this.x
* p
.x
+ this.y
* p
.y
+ this.z
* p
.z
+ this.w
* this.w
;
282 * Calculates the distance between this <code>Point</code> and the origin.
284 * @return the distance between this <code>Point</code> and <code>ZERO</code>
287 public final double length()
289 return Math
.sqrt(this.selfDot());
293 * Calculates the unsigned distance between this <code>Point</code> and <code>p</code>.
295 * @param p the <code>Point</code> to find the distance from
296 * @return the distance between these two <code>Point</code>s
297 * @throws IllegalArgumentException if <code>p</code> is null
299 public final double distanceTo(Point p
)
303 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
304 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
305 throw new IllegalArgumentException(message
);
308 double dx
= this.x
- p
.x
;
309 double dy
= this.y
- p
.y
;
310 double dz
= this.z
- p
.z
;
311 return Math
.sqrt(dx
* dx
+ dy
* dy
+ dz
* dz
);
315 * Calculates the squared unsigned distance between this <code>Point</code> and <code>p</code>. This method is
316 * useful when actual distances are not required, but some measure is needed for comparison purposes. It avoids the
317 * square root required for computing actual distance.
319 * @param p the <code>Point</code> to find the square distance from
320 * @return the square of the distance between these two <code>Point</code>s
321 * @throws IllegalArgumentException if <code>p</code> is null
323 public final double distanceToSquared(Point p
)
327 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
328 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
329 throw new IllegalArgumentException(message
);
331 double dx
= this.x
- p
.x
;
332 double dy
= this.y
- p
.y
;
333 double dz
= this.z
- p
.z
;
334 return (dx
* dx
+ dy
* dy
+ dz
* dz
);
338 * Determines the midpoint of two <code>Point</code>s.
340 * @param p1 the first <code>Point</code>
341 * @param p2 the second <code>Point</code>
342 * @return the midpoint of these two <code>Point</code>s
343 * @throws IllegalArgumentException if either <code>p1</code> or <code>p2</code> is null
345 public static Point
midPoint(Point p1
, Point p2
)
347 if (p1
== null || p2
== null)
349 String message
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
350 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
351 throw new IllegalArgumentException(message
);
354 return new Point(0.5 * (p1
.x
+ p2
.x
), 0.5 * (p1
.y
+ p2
.y
), 0.5 * (p1
.z
+ p2
.z
));
358 * Scales a <code>Point</code> along a vector. The resulting <code>Point</code> is affected by both the scale factor
359 * and the size of the vector direction. For example, a vector (2,2,2) and a vector (1,1,1) would produce a
360 * different result, if all other variables remain constant. For this reason, programmers may wish to normalize
361 * <code>direction</code> before calling this function.
363 * @param scale the factor to be scaled by
364 * @param direction the direction of scaling
365 * @param origin the original <code>Point</code>
366 * @return <code>origin</code> scaled by <code>scale</code> in the direction specified
367 * @throws IllegalArgumentException if <code>direction</code> or <code>origin</code> is null
369 public static Point
fromOriginAndDirection(double scale
, Point direction
, Point origin
)
371 if (direction
== null)
373 String message
= WorldWind
.retrieveErrMsg("nullValue.DirectionIsNull");
374 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
375 throw new IllegalArgumentException(message
);
380 String message
= WorldWind
.retrieveErrMsg("nullValue.OriginIsNull");
381 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
382 throw new IllegalArgumentException(message
);
385 double x
= scale
* direction
.x() + origin
.x
;
386 double y
= scale
* direction
.y() + origin
.y
;
387 double z
= scale
* direction
.z() + origin
.z
;
389 return new Point(x
, y
, z
);
393 * Calculate the extrema of a given array of <code>Point</code>s. The resulting array is always of length 2, with
394 * the first element containing the minimum extremum, and the second containing the maximum. The minimum extremum is
395 * composed by taking the smallest x, y and z values from all the <code>Point</code>s in the array. These values are
396 * not necessarily taken from the same <code>Point</code>. The maximum extrema is composed in the same fashion.
398 * @param points any array of <code>Point</code>s
399 * @return a array with length of 2, comprising the most extreme values in the given array
400 * @throws IllegalArgumentException if <code>points</code> is null
402 public static Point
[] composeExtrema(Point points
[])
406 String message
= WorldWind
.retrieveErrMsg("nullValue.PointsArrayIsNull");
407 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
408 throw new IllegalArgumentException(message
);
411 if (points
.length
== 0)
412 return new Point
[] {Point
.ZERO
, Point
.ZERO
};
414 double xmin
= points
[0].x
;
415 double ymin
= points
[0].y
;
416 double zmin
= points
[0].z
;
421 for (int i
= 1; i
< points
.length
; i
++)
423 double x
= points
[i
].x
;
433 double y
= points
[i
].y
;
443 double z
= points
[i
].z
;
454 return new Point
[] {new Point(xmin
, ymin
, zmin
), new Point(xmax
, ymax
, zmax
)};
458 * Determines the cross product of these two <code>Point</code>s. This is post multiplied by that.
460 * @param that the second <code>Point</code>
461 * @return the cross product of two <code>Point</code>s
462 * @throws IllegalArgumentException if <code>that</code> is null
464 public Point
cross(Point that
)
468 String msg
= WorldWind
.retrieveErrMsg("nullValue.PointIsNull");
469 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
470 throw new IllegalArgumentException(msg
);
472 return new Point(this.y
* that
.z
- this.z
* that
.y
, this.z
* that
.x
- this.x
* that
.z
,
473 this.x
* that
.y
- this.y
* that
.x
);
477 * Compares this <code>Point</code> to <code>o</code> for equality.
479 * This method makes comparisons on private fields; overriding implementations should include a call to
480 * <code>super.equals()</code>.
482 * @param o the <code>Object</code> to be compared to for equality.
483 * @return true if the contents are equal, false otherwise
486 public boolean equals(Object o
)
490 if (o
== null || getClass() != o
.getClass())
493 final gov
.nasa
.worldwind
.geom
.Point point
= (gov
.nasa
.worldwind
.geom
.Point
) o
;
495 if (Double
.compare(point
.w
, w
) != 0)
497 if (Double
.compare(point
.x
, x
) != 0)
499 if (Double
.compare(point
.y
, y
) != 0)
501 //noinspection RedundantIfStatement
502 if (Double
.compare(point
.z
, z
) != 0)
509 * Generates an integer that is always the same for identical objects, but usually different for different objects.
510 * This method overrides the one in <code>Object</code>.
512 * This method makes comparisons on private fields; overriding implementations should include a call to
513 * <code>super.hashCode()</code>.
515 * @return the hashCode for this <code>Point</code>.
518 public int hashCode()
522 temp
= x
!= +0.0d ? Double
.doubleToLongBits(x
) : 0L;
523 result
= (int) (temp ^
(temp
>>> 32));
524 temp
= y
!= +0.0d ? Double
.doubleToLongBits(y
) : 0L;
525 result
= 29 * result
+ (int) (temp ^
(temp
>>> 32));
526 temp
= z
!= +0.0d ? Double
.doubleToLongBits(z
) : 0L;
527 result
= 29 * result
+ (int) (temp ^
(temp
>>> 32));
528 temp
= w
!= +0.0d ? Double
.doubleToLongBits(w
) : 0L;
529 result
= 29 * result
+ (int) (temp ^
(temp
>>> 32));
534 * Generates a string representation of this object. The returned string has the format "(x, y, z, w)" where x, y, z
535 * and w correspond to their respective values in this <code>Point</code>.
537 * @return a string representation of this <code>Point</code>
540 public final String
toString()
542 return "(" + Double
.toString(this.x
) + ", " + Double
.toString(this.y
) + ", " + Double
.toString(this.z
) + ", "
543 + Double
.toString(this.w
) + ")";
547 * Obtains the amount of memory this <code>Point</code> consumes.
549 * @return the memory footprint of this <code>Point</code> in bytes.
551 public final long getSizeInBytes()
553 // we could consider using a constant value here
554 return Double
.SIZE
<< 2;