View Javadoc
1   /*
2    * Copyright (C) 2012 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  package com.irurueta.geometry;
17  
18  import com.irurueta.algebra.Matrix;
19  import com.irurueta.algebra.Utils;
20  import com.irurueta.algebra.WrongSizeException;
21  
22  import java.io.Serializable;
23  
24  /**
25   * Class defining the base interface of any possible quadric.
26   * Appropriate subclasses should be used for each quadric type: pure quadrics
27   * and dual quadrics.
28   */
29  public abstract class BaseQuadric implements Serializable {
30      /**
31       * Number of rows of one matrix that contains quadric parameters.
32       */
33      public static final int BASEQUADRIC_MATRIX_ROW_SIZE = 4;
34  
35      /**
36       * Number of columns of one matrix that contains quadric parameters.
37       */
38      public static final int BASEQUADRIC_MATRIX_COLUMN_SIZE = 4;
39  
40      /**
41       * Number of parameters on a quadric or dual quadric.
42       */
43      public static final int N_PARAMS = 10;
44  
45      /**
46       * Threshold above zero to determine whether a point lies inside (is locus
47       * of) the given quadric or not.
48       */
49      public static final double DEFAULT_LOCUS_THRESHOLD = 1e-12;
50  
51      /**
52       * Threshold above zero to determine whether two points of a quadric are
53       * perpendicular or not.
54       */
55      public static final double DEFAULT_PERPENDICULAR_THRESHOLD = 1e-12;
56  
57      /**
58       * Minimum allowed threshold.
59       */
60      public static final double MIN_THRESHOLD = 0.0;
61  
62      /**
63       * Threshold above zero to determine whether one matrix is symmetric or not.
64       */
65      private static final double DEFAULT_SYMMETRIC_THRESHOLD = 1e-12;
66  
67      /**
68       * Machine precision.
69       */
70      private static final double PRECISION = 1e-12;
71  
72      /**
73       * A element of the matrix defining a quadric.
74       */
75      private double a;
76  
77      /**
78       * B element of the matrix defining a quadric.
79       */
80      private double b;
81  
82      /**
83       * C element of the matrix defining a quadric.
84       */
85      private double c;
86  
87      /**
88       * D element of the matrix defining a quadric.
89       */
90      private double d;
91  
92      /**
93       * E element of the matrix defining a quadric.
94       */
95      private double e;
96  
97      /**
98       * F element of the matrix defining a quadric.
99       */
100     private double f;
101 
102     /**
103      * G element of the matrix defining a quadric.
104      */
105     private double g;
106 
107     /**
108      * H element of the matrix defining a quadric.
109      */
110     private double h;
111 
112     /**
113      * I element of the matrix defining a quadric.
114      */
115     private double i;
116 
117     /**
118      * J element of the matrix defining a quadric.
119      */
120     private double j;
121 
122     /**
123      * Determines whether this instance is already normalized.
124      */
125     private boolean normalized;
126 
127     /**
128      * Constructor of this class.
129      */
130     protected BaseQuadric() {
131         a = b = c = d = e = f = g = h = i = j = 0.0;
132         normalized = false;
133     }
134 
135     /**
136      * Constructor of this class. This constructor accepts every parameter
137      * describing a base quadric (parameters a, b, c, d, e, f, g, h, i).
138      *
139      * @param a Parameter A of the base quadric.
140      * @param b Parameter B of the base quadric.
141      * @param c Parameter C of the base quadric.
142      * @param d Parameter D of the base quadric.
143      * @param e Parameter E of the base quadric.
144      * @param f Parameter F of the base quadric.
145      * @param g Parameter G of the base quadric.
146      * @param h Parameter H of the base quadric.
147      * @param i Parameter I of the base quadric.
148      * @param j Parameter J of the base quadric.
149      */
150     protected BaseQuadric(final double a, final double b, final double c, final double d, final double e,
151                           final double f, final double g, final double h, final double i, final double j) {
152         setParameters(a, b, c, d, e, f, g, h, i, j);
153     }
154 
155     /**
156      * Constructor. This constructor accepts a Matrix describing a base quadric.
157      *
158      * @param m 4x4 matrix describing a base quadric.
159      * @throws NonSymmetricMatrixException Raised when the quadric matrix is not
160      *                                     symmetric.
161      * @throws IllegalArgumentException    Raised when the size of the matrix is
162      *                                     not 4x4.
163      */
164     protected BaseQuadric(final Matrix m) throws NonSymmetricMatrixException {
165         setParameters(m);
166     }
167 
168     /**
169      * Returns parameter A of the given base quadric.
170      *
171      * @return Parameter B of a matrix describing a base quadric.
172      */
173     public double getA() {
174         return a;
175     }
176 
177     /**
178      * Returns parameter B of the given base quadric.
179      *
180      * @return Parameter B of a matrix describing a base quadric.
181      */
182     public double getB() {
183         return b;
184     }
185 
186     /**
187      * Returns parameter C of the given base quadric.
188      *
189      * @return Parameter C of a matrix describing a base quadric.
190      */
191     public double getC() {
192         return c;
193     }
194 
195     /**
196      * Returns parameter D of the given base quadric.
197      *
198      * @return Parameter D of a matrix describing a base quadric.
199      */
200     public double getD() {
201         return d;
202     }
203 
204     /**
205      * Returns parameter E of the given base quadric.
206      *
207      * @return Parameter E of a matrix describing a base quadric.
208      */
209     public double getE() {
210         return e;
211     }
212 
213     /**
214      * Returns parameter F of the given base quadric.
215      *
216      * @return Parameter F of a matrix describing a base quadric.
217      */
218     public double getF() {
219         return f;
220     }
221 
222     /**
223      * Returns parameter G of the given base quadric.
224      *
225      * @return Parameter G of a matrix describing a base quadric.
226      */
227     public double getG() {
228         return g;
229     }
230 
231     /**
232      * Returns parameter H of the given base quadric.
233      *
234      * @return Parameter H of a matrix describing a base quadric.
235      */
236     public double getH() {
237         return h;
238     }
239 
240     /**
241      * Returns parameter I of the given base quadric.
242      *
243      * @return Parameter I of a matrix describing a base quadric.
244      */
245     public double getI() {
246         return i;
247     }
248 
249     /**
250      * Returns parameter J of the given base quadric.
251      *
252      * @return Parameter J of a matrix describing a base quadric.
253      */
254     public double getJ() {
255         return j;
256     }
257 
258     /**
259      * This method accepts every parameter describing a base quadric (parameters
260      * a, b, c, d, e, f, g, h, i,, j).
261      *
262      * @param a Parameter A of the base quadric.
263      * @param b Parameter B of the base quadric.
264      * @param c Parameter C of the base quadric.
265      * @param d Parameter D of the base quadric.
266      * @param e Parameter E of the base quadric.
267      * @param f Parameter F of the base quadric.
268      * @param g Parameter G of the base quadric.
269      * @param h Parameter H of the base quadric.
270      * @param i Parameter I of the base quadric.
271      * @param j Parameter J of the base quadric.
272      */
273     public final void setParameters(final double a, final double b, final double c, final double d, final double e,
274                                     final double f, final double g, final double h, final double i, final double j) {
275         this.a = a;
276         this.b = b;
277         this.c = c;
278         this.d = d;
279         this.e = e;
280         this.f = f;
281         this.g = g;
282         this.h = h;
283         this.i = i;
284         this.j = j;
285         normalized = false;
286     }
287 
288     /**
289      * This method sets the matrix used for describing a base quadric.
290      * This matrix must be 4x4 and symmetric.
291      *
292      * @param m                  4x4 Matrix describing a base quadric.
293      * @param symmetricThreshold Grade of tolerance to determine whether a
294      *                           matrix is symmetric or not. It is used because due to machine precision
295      *                           a matrix might not be considered exactly symmetric (by default:
296      *                           DEFAULT_SYMMETRIC_THRESHOLD is used).
297      * @throws IllegalArgumentException    Raised when the size of the matrix is
298      *                                     not 4x4.
299      * @throws NonSymmetricMatrixException Raised when the quadric matrix is not
300      *                                     symmetric.
301      */
302     public final void setParameters(final Matrix m, final double symmetricThreshold)
303             throws NonSymmetricMatrixException {
304         if (m.getRows() != BASEQUADRIC_MATRIX_ROW_SIZE || m.getColumns() != BASEQUADRIC_MATRIX_COLUMN_SIZE) {
305             throw new IllegalArgumentException();
306         } else {
307             if (!Utils.isSymmetric(m, symmetricThreshold)) {
308                 throw new NonSymmetricMatrixException();
309             } else {
310                 a = m.getElementAt(0, 0);
311                 b = m.getElementAt(1, 1);
312                 c = m.getElementAt(2, 2);
313                 d = m.getElementAt(0, 1);
314                 e = m.getElementAt(2, 1);
315                 f = m.getElementAt(2, 0);
316                 g = m.getElementAt(3, 0);
317                 h = m.getElementAt(3, 1);
318                 i = m.getElementAt(3, 2);
319                 j = m.getElementAt(3, 3);
320                 normalized = false;
321             }
322         }
323     }
324 
325     /**
326      * This method sets the matrix used for describing a base quadric.
327      * This matrix must be 4x4 and symmetric.
328      *
329      * @param m 4x4 matrix describing a base quadric.
330      * @throws IllegalArgumentException    Raised when the size of the matrix is
331      *                                     not 4x4.
332      * @throws NonSymmetricMatrixException Raised when the quadric matrix is not
333      *                                     symmetric.
334      */
335     public final void setParameters(final Matrix m) throws NonSymmetricMatrixException {
336         setParameters(m, DEFAULT_SYMMETRIC_THRESHOLD);
337     }
338 
339     /**
340      * This method sets the A parameter of a base quadric.
341      *
342      * @param a Parameter A of the given base quadric.
343      */
344     public void setA(final double a) {
345         this.a = a;
346         normalized = false;
347     }
348 
349     /**
350      * This method sets the B parameter of a base quadric.
351      *
352      * @param b Parameter B of the given base quadric.
353      */
354     public void setB(final double b) {
355         this.b = b;
356         normalized = false;
357     }
358 
359     /**
360      * This method sets the C parameter of a base quadric.
361      *
362      * @param c Parameter C of the given base quadric.
363      */
364     public void setC(final double c) {
365         this.c = c;
366         normalized = false;
367     }
368 
369     /**
370      * This method sets the D parameter of a base quadric.
371      *
372      * @param d Parameter D of the given base quadric.
373      */
374     public void setD(final double d) {
375         this.d = d;
376         normalized = false;
377     }
378 
379     /**
380      * This method sets the E parameter of a base quadric.
381      *
382      * @param e Parameter E of the given base quadric.
383      */
384     public void setE(final double e) {
385         this.e = e;
386         normalized = false;
387     }
388 
389     /**
390      * This method sets the F parameter of a base quadric.
391      *
392      * @param f Parameter F of the given base quadric.
393      */
394     public void setF(final double f) {
395         this.f = f;
396         normalized = false;
397     }
398 
399     /**
400      * This method sets the G parameter of a base quadric.
401      *
402      * @param g Parameter G of the given base quadric.
403      */
404     public void setG(final double g) {
405         this.g = g;
406         normalized = false;
407     }
408 
409     /**
410      * This method sets the H parameter of a base quadric.
411      *
412      * @param h Parameter H of the given base quadric.
413      */
414     public void setH(final double h) {
415         this.h = h;
416         normalized = false;
417     }
418 
419     /**
420      * This method sets the "I" parameter of a base quadric.
421      *
422      * @param i Parameter "I" of the given base quadric.
423      */
424     public void setI(final double i) {
425         this.i = i;
426         normalized = false;
427     }
428 
429     /**
430      * This method sets the J parameter of a base quadric.
431      *
432      * @param j Parameter J of the given base quadric.
433      */
434     public void setJ(final double j) {
435         this.j = j;
436         normalized = false;
437     }
438 
439     /**
440      * Returns the matrix that describes this base quadric.
441      *
442      * @return 4x4 matrix describing this base quadric.
443      */
444     public Matrix asMatrix() {
445         Matrix out = null;
446         try {
447             out = new Matrix(BASEQUADRIC_MATRIX_ROW_SIZE,
448                     BASEQUADRIC_MATRIX_COLUMN_SIZE);
449             asMatrix(out);
450         } catch (final WrongSizeException ignore) {
451             // never happens
452         }
453         return out;
454     }
455 
456     /**
457      * Sets the values in provided matrix corresponding to this base quadric.
458      *
459      * @param m Provided matrix where values will be stored.
460      * @throws IllegalArgumentException Raised if provided matrix is not 4x4.
461      */
462     public void asMatrix(final Matrix m) {
463         if (m.getRows() != BASEQUADRIC_MATRIX_ROW_SIZE || m.getColumns() != BASEQUADRIC_MATRIX_ROW_SIZE) {
464             throw new IllegalArgumentException();
465         }
466 
467         m.setElementAt(0, 0, a);
468         m.setElementAt(1, 1, b);
469         m.setElementAt(2, 2, c);
470         m.setElementAt(3, 3, j);
471         m.setElementAt(1, 0, d);
472         m.setElementAt(0, 1, d);
473         m.setElementAt(2, 1, e);
474         m.setElementAt(1, 2, e);
475         m.setElementAt(2, 0, f);
476         m.setElementAt(0, 2, f);
477         m.setElementAt(3, 0, g);
478         m.setElementAt(0, 3, g);
479         m.setElementAt(3, 1, h);
480         m.setElementAt(1, 3, h);
481         m.setElementAt(3, 2, i);
482         m.setElementAt(2, 3, i);
483     }
484 
485     /**
486      * Normalizes the Quadric params using its norm.
487      */
488     public void normalize() {
489         if (!normalized) {
490             final var m = asMatrix();
491             final var norm = Utils.normF(m);
492 
493             if (norm > PRECISION) {
494                 a /= norm;
495                 b /= norm;
496                 c /= norm;
497                 d /= norm;
498                 e /= norm;
499                 f /= norm;
500                 g /= norm;
501                 h /= norm;
502                 i /= norm;
503                 j /= norm;
504                 normalized = true;
505             }
506         }
507     }
508 
509     /**
510      * Returns boolean indicating whether this base quadric has already been
511      * normalized.
512      *
513      * @return True if normalized, false otherwise.
514      */
515     public boolean isNormalized() {
516         return normalized;
517     }
518 }