View Javadoc
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 }