1 /*
2 * Copyright (C) 2017 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.irurueta.geometry;
18
19 import java.io.Serializable;
20 import java.util.Objects;
21
22 /**
23 * Subclass of Point3D defining an inhomogeneous 3D point.
24 * An inhomogeneous 3D point is defined by three coordinates: (x, y, z), where
25 * x, y and z are the horizontal, vertical and depth coordinates, respectively.
26 * Homogeneous 3D points can be transformed into inhomogeneous ones by
27 * normalizing x, y and z coordinates by the w factor as follows:
28 * Homogeneous 3D point (x,y,z,w) -< Inhomogeneous 3D point (x/w,y/w,z/w).
29 * Note that if and homogeneous 3D point is at infinity (w=0), its corresponding
30 * inhomogeneous point will be at infinity by setting (x=inf,y=inf,z=inf).
31 * Because of this, and because of machine precision, usually Homogeneous points
32 * are better suited when working at far distances or for numerical purposes,
33 * and their inhomogeneous counterparts are better suited when computing
34 * Euclidean distances, etc.
35 */
36 public class InhomogeneousPoint3D extends Point3D implements Serializable {
37
38 /**
39 * Defines the X coordinate of an inhomogeneous 2D point.
40 */
41 private double x;
42
43 /**
44 * Defines the Y coordinate of an inhomogeneous 2D point.
45 */
46 private double y;
47
48 /**
49 * Defines the Z coordinate of an inhomogeneous 2D point.
50 */
51 private double z;
52
53 /**
54 * Empty constructor.
55 */
56 public InhomogeneousPoint3D() {
57 super();
58 x = y = z = 0.0;
59 }
60
61 /**
62 * Constructor of this class. This constructor sets a new inhomogeneous v
63 * array containing the coordinates X, Y and Z of the given point.
64 *
65 * @param v Array of length 3 containing the 3D coordinates of an
66 * inhomogeneous point.
67 * @throws IllegalArgumentException Raised when the size of the array is not
68 * 2.
69 */
70 public InhomogeneousPoint3D(final double[] v) {
71 super();
72 setCoordinates(v);
73 }
74
75 /**
76 * Constructor of this class. This constructor sets a new inhomogeneous 3D
77 * point using the coordinates x, y and z of the given point.
78 *
79 * @param x X coordinate of the given 3D point.
80 * @param y Y coordinate of the given 3D point.
81 * @param z Z coordinate of the given 3D point.
82 */
83 public InhomogeneousPoint3D(final double x, final double y, final double z) {
84 this.x = x;
85 this.y = y;
86 this.z = z;
87 }
88
89 /**
90 * This constructor sets a new inhomogeneous 3D point using as
91 * initialization provided Point3D instance.
92 *
93 * @param point Point to initialize new instance to.
94 */
95 public InhomogeneousPoint3D(final Point3D point) {
96 setCoordinates(point);
97 }
98
99 /**
100 * Returns the X coordinate of the given homogeneous 3D point instance.
101 *
102 * @return X coordinate.
103 */
104 public double getX() {
105 return x;
106 }
107
108 /**
109 * Sets the X coordinate of this homogeneous point.
110 *
111 * @param x X coordinate.
112 */
113 public void setX(final double x) {
114 this.x = x;
115 }
116
117 /**
118 * Returns the Y coordinate of the given homogeneous 3D point instance.
119 *
120 * @return Y coordinate.
121 */
122 public double getY() {
123 return y;
124 }
125
126 /**
127 * Sets the Y coordinate of this homogeneous point.
128 *
129 * @param y Y coordinate.
130 */
131 public void setY(final double y) {
132 this.y = y;
133 }
134
135 /**
136 * Returns the Z coordinate of the given homogeneous 3D point instance.
137 *
138 * @return Z coordinate.
139 */
140 public double getZ() {
141 return z;
142 }
143
144 /**
145 * Sets the Z coordinate of this homogeneous point.
146 *
147 * @param z Z coordinate.
148 */
149 public void setZ(final double z) {
150 this.z = z;
151 }
152
153 /**
154 * Sets the coordinates of this inhomogeneous 3D point by using provided X,
155 * Y and Z coordinates.
156 *
157 * @param x X coordinate.
158 * @param y Y coordinate.
159 * @param z Z coordinate.
160 */
161 public void setCoordinates(final double x, final double y, final double z) {
162 this.x = x;
163 this.y = y;
164 this.z = z;
165 }
166
167 /**
168 * Sets the coordinates of a 3D point using an array containing its
169 * coordinates.
170 *
171 * @param v Array containing the coordinates of the point.
172 * @throws IllegalArgumentException Raised if provided array does not have a
173 * valid size.
174 */
175 @Override
176 public final void setCoordinates(final double[] v) {
177 if (v.length != POINT3D_INHOMOGENEOUS_COORDINATES_LENGTH) {
178 throw new IllegalArgumentException();
179 } else {
180 x = v[0];
181 y = v[1];
182 z = v[2];
183 }
184 }
185
186 /**
187 * Sets coordinates of this instance using the coordinates of provided 3D
188 * point.
189 *
190 * @param point Input point.
191 */
192 @Override
193 public final void setCoordinates(final Point3D point) {
194 switch (point.getType()) {
195 case INHOMOGENEOUS_COORDINATES:
196 final var inhomPoint = (InhomogeneousPoint3D) point;
197 x = inhomPoint.getX();
198 y = inhomPoint.getY();
199 z = inhomPoint.getZ();
200 break;
201
202 case HOMOGENEOUS_COORDINATES:
203 default:
204 final var homPoint = (HomogeneousPoint3D) point;
205 x = homPoint.getInhomX();
206 y = homPoint.getInhomY();
207 z = homPoint.getInhomZ();
208 break;
209 }
210 }
211
212 /**
213 * Returns X homogeneous coordinate of this 3D point.
214 *
215 * @return X homogeneous coordinate.
216 */
217 @Override
218 public double getHomX() {
219 return getX();
220 }
221
222 /**
223 * Returns Y homogeneous coordinate of this 3D point.
224 *
225 * @return Y homogeneous coordinate.
226 */
227 @Override
228 public double getHomY() {
229 return getY();
230 }
231
232 /**
233 * Returns Z homogeneous coordinate of this 3D point.
234 *
235 * @return Z homogeneous coordinate.
236 */
237 @Override
238 public double getHomZ() {
239 return getZ();
240 }
241
242 /**
243 * Returns W homogeneous coordinate of this 3D point.
244 *
245 * @return W homogeneous coordinate.
246 */
247 @Override
248 public double getHomW() {
249 return 1.0;
250 }
251
252 /**
253 * Sets coordinates of this 3D point instance using provided homogeneous
254 * coordinates.
255 *
256 * @param homX x homogeneous coordinate.
257 * @param homY y homogeneous coordinate.
258 * @param homZ z homogeneous coordinate.
259 * @param homW w homogeneous coordinate.
260 */
261 @Override
262 public void setHomogeneousCoordinates(final double homX, final double homY, final double homZ, final double homW) {
263 x = homX / homW;
264 y = homY / homW;
265 z = homZ / homW;
266 }
267
268 /**
269 * Returns X inhomogeneous coordinate of this 3D point.
270 *
271 * @return X inhomogeneous coordinate.
272 */
273 @Override
274 public double getInhomX() {
275 return getX();
276 }
277
278 /**
279 * Sets X inhomogeneous coordinate of this 3D point.
280 *
281 * @param inhomX inhomogeneous coordinate.
282 */
283 @Override
284 public void setInhomX(final double inhomX) {
285 x = inhomX;
286 }
287
288 /**
289 * Returns Y inhomogeneous coordinate of this 3D point.
290 *
291 * @return Y inhomogeneous coordinate.
292 */
293 @Override
294 public double getInhomY() {
295 return getY();
296 }
297
298 /**
299 * Sets Y inhomogeneous coordinate of this 3D point.
300 *
301 * @param inhomY Y inhomogeneous coordinate.
302 */
303 @Override
304 public void setInhomY(final double inhomY) {
305 y = inhomY;
306 }
307
308 /**
309 * Returns Z inhomogeneous coordinate of this 3D point.
310 *
311 * @return Z inhomogeneous coordinate.
312 */
313 @Override
314 public double getInhomZ() {
315 return getZ();
316 }
317
318 /**
319 * Sets Z inhomogeneous coordinate of this 3D point.
320 *
321 * @param inhomZ Z inhomogeneous coordinate.
322 */
323 @Override
324 public void setInhomZ(final double inhomZ) {
325 z = inhomZ;
326 }
327
328 /**
329 * Sets coordinates of this 3D point instance using provided inhomogeneous
330 * coordinates.
331 *
332 * @param inhomX x inhomogeneous coordinate.
333 * @param inhomY y inhomogeneous coordinate.
334 * @param inhomZ z inhomogeneous coordinate.
335 */
336 @Override
337 public void setInhomogeneousCoordinates(final double inhomX, final double inhomY, final double inhomZ) {
338 setCoordinates(inhomX, inhomY, inhomZ);
339 }
340
341 /**
342 * Checks if provided object equals current 2D point.
343 *
344 * @param obj Object to compare.
345 * @return True if both objects are considered to be equal, false otherwise.
346 */
347 @Override
348 public boolean equals(final Object obj) {
349 if (!(obj instanceof Point3D point)) {
350 return false;
351 }
352 if (obj == this) {
353 return true;
354 }
355
356 return equals(point);
357 }
358
359 /**
360 * Returns hash code value.
361 *
362 * @return Hash code value.
363 */
364 @Override
365 public int hashCode() {
366 return Objects.hash(x, y, z, 1.0);
367 }
368
369 /**
370 * Checks if the homogeneous 3D point described by this instance equals the
371 * input Point3D (using a comparison threshold).
372 *
373 * @param point Point that will be compared to.
374 * @param threshold threshold grade of tolerance to determine whether the
375 * points are equal or not. It is used because due to machine precision, the
376 * values might not be exactly equal (if not provided
377 * DEFAULT_COMPARISON_THRESHOLD is used).
378 * @return True if current point and input point are the same, false
379 * otherwise.
380 * @throws IllegalArgumentException Raised if threshold is negative.
381 */
382 @Override
383 public boolean equals(final Point3D point, final double threshold) {
384 if (point.getType() == CoordinatesType.INHOMOGENEOUS_COORDINATES) {
385 return equals((InhomogeneousPoint3D) point, threshold);
386 } else {
387 return equals((HomogeneousPoint3D) point, threshold);
388 }
389 }
390
391 /**
392 * Checks if the homogeneous 3D point described by this instance equals the
393 * input HomogeneousPoint3D (using a comparison threshold).
394 *
395 * @param point Point that will be compared to.
396 * @param threshold threshold grade of tolerance to determine whether the
397 * points are equal or not. It is used because due to machine precision, the
398 * values might not be exactly equal (if not provided
399 * DEFAULT_COMPARISON_THRESHOLD is used).
400 * @return True if current point and input point are the same, false
401 * otherwise.
402 * @throws IllegalArgumentException Raised if threshold is negative.
403 */
404 public boolean equals(final HomogeneousPoint3D point, final double threshold) {
405 if (threshold < MIN_THRESHOLD) {
406 throw new IllegalArgumentException();
407 }
408
409 final var dX = Math.abs((point.getX() / point.getW()) - x) <= threshold;
410 final var dY = Math.abs((point.getY() / point.getW()) - y) <= threshold;
411 final var dZ = Math.abs((point.getZ() / point.getW()) - z) <= threshold;
412
413 return (dX && dY && dZ);
414 }
415
416 /**
417 * Checks if the homogeneous 3D point described by this instance equals the
418 * input HomogeneousPoint3D (using a comparison threshold).
419 *
420 * @param point Point that will be compared to.
421 * @return True if current point and input point are the same, false
422 * otherwise
423 */
424 public boolean equals(final HomogeneousPoint3D point) {
425 return equals(point, DEFAULT_COMPARISON_THRESHOLD);
426 }
427
428 /**
429 * Checks if the homogeneous 3D point described by this instance equals the
430 * input InhomogeneousPoint3D (using a comparison threshold).
431 *
432 * @param point Point that will be compared to.
433 * @param threshold threshold grade of tolerance to determine whether the
434 * points are equal or not. It is used because due to machine precision, the
435 * values might not be exactly equal (if not provided
436 * DEFAULT_COMPARISON_THRESHOLD is used).
437 * @return True if current point and input point are the same, false
438 * otherwise.
439 * @throws IllegalArgumentException Raised if threshold is negative.
440 */
441 public boolean equals(final InhomogeneousPoint3D point, double threshold) {
442 if (threshold < MIN_THRESHOLD) {
443 throw new IllegalArgumentException();
444 }
445
446 final var dX = Math.abs(point.getX() - x) <= threshold;
447 final var dY = Math.abs(point.getY() - y) <= threshold;
448 final var dZ = Math.abs(point.getZ() - z) <= threshold;
449
450 return (dX && dY && dZ);
451 }
452
453 /**
454 * Checks if the homogeneous 3D point described by this instance equals the
455 * input InhomogeneousPoint3D (using a comparison threshold).
456 *
457 * @param point Point that will be compared to.
458 * @return True if current point and input point are the same, false
459 * otherwise.
460 */
461 public boolean equals(final InhomogeneousPoint3D point) {
462 return equals(point, DEFAULT_COMPARISON_THRESHOLD);
463 }
464
465 /**
466 * Checks whether this Point3D is at infinity or not.
467 *
468 * @return True if the point is at infinity. False otherwise.
469 */
470 @Override
471 public boolean isAtInfinity() {
472 return (Double.isInfinite(x) || Double.isNaN(x) || Double.isInfinite(y) || Double.isNaN(y)
473 || Double.isInfinite(z) || Double.isNaN(z));
474 }
475
476 /**
477 * Returns the type of coordinates used to represent a Point3D.
478 *
479 * @return Type of coordinates of this 3D point.
480 */
481 @Override
482 public CoordinatesType getType() {
483 return CoordinatesType.INHOMOGENEOUS_COORDINATES;
484 }
485
486 /**
487 * Converts this instance into an homogeneous 3D point and returns the
488 * result as a new homogeneous 3D point instance.
489 *
490 * @return Converts and returns this point as an homogeneous 3D point.
491 */
492 public HomogeneousPoint3D toHomogeneous() {
493 return new HomogeneousPoint3D(x, y, z, 1.0);
494 }
495
496 /**
497 * Returns an array containing the coordinates of this Point3D.
498 *
499 * @return Array containing coordinates of this Point3D.
500 */
501 @Override
502 public double[] asArray() {
503 final var out = new double[POINT3D_INHOMOGENEOUS_COORDINATES_LENGTH];
504 asArray(out);
505 return out;
506 }
507
508 /**
509 * Uses provided array to store the coordinates of this InhomogeneousPoint3D
510 *
511 * @param array Array where coordinates will be stored.
512 * @throws IllegalArgumentException Raised if length of array is not 2.
513 */
514 @Override
515 public void asArray(double[] array) {
516 if (array.length != POINT3D_INHOMOGENEOUS_COORDINATES_LENGTH)
517 throw new IllegalArgumentException();
518 array[0] = x;
519 array[1] = y;
520 array[2] = z;
521 }
522 }