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 }