1 /*
2 * Copyright (C) 2015 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.estimators;
17
18 import com.irurueta.geometry.Point3D;
19 import com.irurueta.geometry.Sphere;
20 import com.irurueta.numerical.robust.RobustEstimatorException;
21 import com.irurueta.numerical.robust.RobustEstimatorMethod;
22
23 import java.util.List;
24
25 /**
26 * This is an abstract class for algorithms to robustly find the best sphere
27 * that fits in a collection of 3D points.
28 * Implementations of this class should be able to detect and discard outliers
29 * in order to find the best solution.
30 */
31 @SuppressWarnings("DuplicatedCode")
32 public abstract class SphereRobustEstimator {
33 /**
34 * Minimum number of 3D points required to estimate a sphere.
35 */
36 public static final int MINIMUM_SIZE = 4;
37
38 /**
39 * Default amount of progress variation before notifying a change in
40 * estimation progress. By default, this is set to 5%.
41 */
42 public static final float DEFAULT_PROGRESS_DELTA = 0.05f;
43
44 /**
45 * Minimum allowed value for progress delta.
46 */
47 public static final float MIN_PROGRESS_DELTA = 0.0f;
48
49 /**
50 * Maximum allowed value for progress delta.
51 */
52 public static final float MAX_PROGRESS_DELTA = 1.0f;
53
54 /**
55 * Constant defining default confidence of the estimated result, which is
56 * 99%. This means that with a probability of 99% estimation will be
57 * accurate because chosen sub-samples will be inliers.
58 */
59 public static final double DEFAULT_CONFIDENCE = 0.99;
60
61 /**
62 * Default maximum allowed number of iterations.
63 */
64 public static final int DEFAULT_MAX_ITERATIONS = 5000;
65
66 /**
67 * Minimum allowed confidence value.
68 */
69 public static final double MIN_CONFIDENCE = 0.0;
70
71 /**
72 * Maximum allowed confidence value.
73 */
74 public static final double MAX_CONFIDENCE = 1.0;
75
76 /**
77 * Minimum allowed number of iterations.
78 */
79 public static final int MIN_ITERATIONS = 1;
80
81 /**
82 * Default robust estimator method when none is provided.
83 */
84 public static final RobustEstimatorMethod DEFAULT_ROBUST_METHOD = RobustEstimatorMethod.PROMEDS;
85
86 /**
87 * Listener to be notified of events such as when estimation starts, ends
88 * or its progress significantly changes.
89 */
90 protected SphereRobustEstimatorListener listener;
91
92 /**
93 * Indicates if this estimator is locked because an estimation is being
94 * computed.
95 */
96 protected volatile boolean locked;
97
98 /**
99 * Amount of progress variation before notifying a progress change during
100 * estimation.
101 */
102 protected float progressDelta;
103
104 /**
105 * Amount of confidence expressed as a value between 0.0 and 1.0 (which is
106 * equivalent to 100%). The amount of confidence indicates the probability
107 * that the estimated result is correct. Usually this value will be close
108 * to 1.0, but not exactly 1.0.
109 */
110 protected double confidence;
111
112 /**
113 * Maximum allowed number of iterations. When the maximum number of
114 * iterations is exceeded, result will not be available, however an
115 * approximate result will be available for retrieval.
116 */
117 protected int maxIterations;
118
119 /**
120 * List of points to be used to estimate a sphere. Provided list must have
121 * a size greater or equal than MINIMUM_SIZE.
122 */
123 protected List<Point3D> points;
124
125 /**
126 * Constructor.
127 */
128 protected SphereRobustEstimator() {
129 progressDelta = DEFAULT_PROGRESS_DELTA;
130 confidence = DEFAULT_CONFIDENCE;
131 maxIterations = DEFAULT_MAX_ITERATIONS;
132 }
133
134 /**
135 * Constructor.
136 *
137 * @param listener listener to be notified of events such as when estimation
138 * starts, ends or its progress significantly changes.
139 */
140 protected SphereRobustEstimator(final SphereRobustEstimatorListener listener) {
141 this.listener = listener;
142 progressDelta = DEFAULT_PROGRESS_DELTA;
143 confidence = DEFAULT_CONFIDENCE;
144 maxIterations = DEFAULT_MAX_ITERATIONS;
145 }
146
147 /**
148 * Constructor with points.
149 *
150 * @param points 3D points to estimate a sphere.
151 * @throws IllegalArgumentException if provided list of points don't have
152 * a size greater or equal than MINIMUM_SIZE.
153 */
154 protected SphereRobustEstimator(final List<Point3D> points) {
155 progressDelta = DEFAULT_PROGRESS_DELTA;
156 confidence = DEFAULT_CONFIDENCE;
157 maxIterations = DEFAULT_MAX_ITERATIONS;
158 internalSetPoints(points);
159 }
160
161 /**
162 * Constructor.
163 *
164 * @param points 3D points to estimate a sphere.
165 * @param listener listener to be notified of events such as when estimation
166 * starts, ends or its progress significantly changes.
167 * @throws IllegalArgumentException if provided list of points don't have
168 * a size greater or equal than MINIMUM_SIZE.
169 */
170 protected SphereRobustEstimator(final SphereRobustEstimatorListener listener, final List<Point3D> points) {
171 this.listener = listener;
172 progressDelta = DEFAULT_PROGRESS_DELTA;
173 confidence = DEFAULT_CONFIDENCE;
174 maxIterations = DEFAULT_MAX_ITERATIONS;
175 internalSetPoints(points);
176 }
177
178
179 /**
180 * Returns reference to listener to be notified of events such as when
181 * estimation starts, ends or its progress significantly changes.
182 *
183 * @return listener to be notified of events.
184 */
185 public SphereRobustEstimatorListener getListener() {
186 return listener;
187 }
188
189 /**
190 * Sets listener to be notified of events such as when estimation starts,
191 * ends or its progress significantly changes.
192 *
193 * @param listener listener to be notified of events.
194 * @throws LockedException if robust estimator is locked.
195 */
196 public void setListener(final SphereRobustEstimatorListener listener) throws LockedException {
197 if (isLocked()) {
198 throw new LockedException();
199 }
200 this.listener = listener;
201 }
202
203 /**
204 * Indicates whether listener has been provided and is available for
205 * retrieval.
206 *
207 * @return true if available, false otherwise.
208 */
209 public boolean isListenerAvailable() {
210 return listener != null;
211 }
212
213 /**
214 * Indicates if this instance is locked because estimation is being computed
215 *
216 * @return true if locked, false otherwise.
217 */
218 public boolean isLocked() {
219 return locked;
220 }
221
222 /**
223 * Returns amount of progress variation before notifying a progress change
224 * during estimation.
225 *
226 * @return amount of progress variation before notifying a progress change
227 * during estimation.
228 */
229 public float getProgressDelta() {
230 return progressDelta;
231 }
232
233 /**
234 * Sets amount of progress variation before notifying a progress change
235 * during estimation.
236 *
237 * @param progressDelta amount of progress variation before notifying a
238 * progress change during estimation.
239 * @throws IllegalArgumentException if progress delta is less than zero or
240 * greater than 1.
241 * @throws LockedException if this estimator is locked because an estimation
242 * is being computed.
243 */
244 public void setProgressDelta(final float progressDelta) throws LockedException {
245 if (isLocked()) {
246 throw new LockedException();
247 }
248 if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
249 throw new IllegalArgumentException();
250 }
251 this.progressDelta = progressDelta;
252 }
253
254 /**
255 * Returns amount of confidence expressed as a value between 0.0 and 1.0
256 * (which is equivalent to 100%). The amount of confidence indicates the
257 * probability that the estimated result is correct. Usually this value will
258 * be close to 1.0, but not exactly 1.0.
259 *
260 * @return amount of confidence as a value between 0.0 and 1.0.
261 */
262 public double getConfidence() {
263 return confidence;
264 }
265
266 /**
267 * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which
268 * is equivalent to 100%). The amount of confidence indicates the
269 * probability that the estimated result is correct. Usually this value will
270 * be close to 1.0, but not exactly 1.0.
271 *
272 * @param confidence confidence to be set as a value between 0.0 and 1.0.
273 * @throws IllegalArgumentException if provided value is not between 0.0 and
274 * 1.0.
275 * @throws LockedException if this estimator is locked because an estimator
276 * is being computed.
277 */
278 public void setConfidence(final double confidence) throws LockedException {
279 if (isLocked()) {
280 throw new LockedException();
281 }
282 if (confidence < MIN_CONFIDENCE || confidence > MAX_CONFIDENCE) {
283 throw new IllegalArgumentException();
284 }
285 this.confidence = confidence;
286 }
287
288 /**
289 * Returns maximum allowed number of iterations. If maximum allowed number
290 * of iterations is achieved without converging to a result when calling
291 * estimate(), a RobustEstimatorException will be raised.
292 *
293 * @return maximum allowed number of iterations.
294 */
295 public int getMaxIterations() {
296 return maxIterations;
297 }
298
299 /**
300 * Sets maximum allowed number of iterations. When the maximum number of
301 * iterations is exceeded, result will not be available, however an
302 * approximate result will be available for retrieval.
303 *
304 * @param maxIterations maximum allowed number of iterations to be set.
305 * @throws IllegalArgumentException if provided value is less than 1.
306 * @throws LockedException if this estimator is locked because an estimation
307 * is being computed.
308 */
309 public void setMaxIterations(final int maxIterations) throws LockedException {
310 if (isLocked()) {
311 throw new LockedException();
312 }
313 if (maxIterations < MIN_ITERATIONS) {
314 throw new IllegalArgumentException();
315 }
316 this.maxIterations = maxIterations;
317 }
318
319 /**
320 * Returns list of points to be used to estimate a sphere.
321 * Provided list must have a size greater or equal than MINIMUM_SIZE.
322 *
323 * @return list of points to be used to estimate a sphere.
324 */
325 public List<Point3D> getPoints() {
326 return points;
327 }
328
329 /**
330 * Sets list of points to be used to estimate a sphere.
331 * Provided list must have a size greater or equal than MINIMUM_SIZE.
332 *
333 * @param points list of points to be used to estimate a sphere.
334 * @throws IllegalArgumentException if provided list of points don't have
335 * a size greater or equal than MINIMUM_SIZE.
336 * @throws LockedException if estimator is locked because a computation is
337 * already in progress.
338 */
339 public void setPoints(final List<Point3D> points) throws LockedException {
340 if (isLocked()) {
341 throw new LockedException();
342 }
343 internalSetPoints(points);
344 }
345
346 /**
347 * Indicates if estimator is ready to start the sphere estimation.
348 * This is true when a minimum if MINIMUM_SIZE points are available.
349 *
350 * @return true if estimator is ready, false otherwise.
351 */
352 public boolean isReady() {
353 return points != null && points.size() >= MINIMUM_SIZE;
354 }
355
356 /**
357 * Returns quality scores corresponding to each point.
358 * The larger the score value the better the quality of the point measure.
359 * This implementation always returns null.
360 * Subclasses using quality scores must implement proper behaviour.
361 *
362 * @return quality scores corresponding to each point.
363 */
364 public double[] getQualityScores() {
365 return null;
366 }
367
368 /**
369 * Sets quality scores corresponding to each point.
370 * The larger the score value the better the quality of the matching.
371 * This implementation makes no action.
372 * Subclasses using quality scores must implement proper behaviour.
373 *
374 * @param qualityScores quality scores corresponding to each pair of matched
375 * points.
376 * @throws LockedException if robust estimator is locked because an
377 * estimation is already in progress.
378 * @throws IllegalArgumentException if provided quality scores length is
379 * smaller than MINIMUM_SIZE (i.e. 4 samples).
380 */
381 public void setQualityScores(final double[] qualityScores) throws LockedException {
382 }
383
384 /**
385 * Creates a sphere robust estimator based on 3D point samples and using
386 * provided robust estimator method.
387 *
388 * @param method method of a robust estimator algorithm to estimate the best
389 * sphere.
390 * @return an instance of a sphere robust estimator.
391 */
392 public static SphereRobustEstimator create(final RobustEstimatorMethod method) {
393 return switch (method) {
394 case LMEDS -> new LMedSSphereRobustEstimator();
395 case MSAC -> new MSACSphereRobustEstimator();
396 case PROSAC -> new PROSACSphereRobustEstimator();
397 case PROMEDS -> new PROMedSSphereRobustEstimator();
398 default -> new RANSACSphereRobustEstimator();
399 };
400 }
401
402 /**
403 * Creates a sphere robust estimator based on 3D point samples and using
404 * provided points and robust estimator method.
405 *
406 * @param points 3D points to estimate a sphere.
407 * @param method method of a robust estimator algorithm to estimate the best
408 * sphere.
409 * @return an instance of a sphere robust estimator.
410 * @throws IllegalArgumentException if provided list of points don't have a
411 * size greater or equal than MINIMUM_SIZE.
412 */
413 public static SphereRobustEstimator create(final List<Point3D> points, final RobustEstimatorMethod method) {
414 return switch (method) {
415 case LMEDS -> new LMedSSphereRobustEstimator(points);
416 case MSAC -> new MSACSphereRobustEstimator(points);
417 case PROSAC -> new PROSACSphereRobustEstimator(points);
418 case PROMEDS -> new PROMedSSphereRobustEstimator(points);
419 default -> new RANSACSphereRobustEstimator(points);
420 };
421 }
422
423 /**
424 * Creates a sphere robust estimator based on 3D point samples and using
425 * provided listener.
426 *
427 * @param listener listener to be notified of events such as when estimation
428 * starts, ends or its progress significantly changes.
429 * @param method method of a robust estimator algorithm to estimate the best
430 * sphere.
431 * @return an instance of a sphere robust estimator.
432 */
433 public static SphereRobustEstimator create(
434 final SphereRobustEstimatorListener listener, final RobustEstimatorMethod method) {
435 return switch (method) {
436 case LMEDS -> new LMedSSphereRobustEstimator(listener);
437 case MSAC -> new MSACSphereRobustEstimator(listener);
438 case PROSAC -> new PROSACSphereRobustEstimator(listener);
439 case PROMEDS -> new PROMedSSphereRobustEstimator(listener);
440 default -> new RANSACSphereRobustEstimator(listener);
441 };
442 }
443
444 /**
445 * Creates a sphere robust estimator based on 3D point samples and using
446 * provided listener and points.
447 *
448 * @param listener listener to be notified of events such as when estimation
449 * starts, ends or its progress significantly changes.
450 * @param points 3D points to estimate a sphere.
451 * @param method method of a robust estimator algorithm to estimate the best
452 * sphere.
453 * @return an instance of a sphere robust estimator.
454 * @throws IllegalArgumentException if provided list of points don't have a
455 * size greater or equal than MINIMUM_SIZE.
456 */
457 public static SphereRobustEstimator create(
458 final SphereRobustEstimatorListener listener, final List<Point3D> points,
459 final RobustEstimatorMethod method) {
460 return switch (method) {
461 case LMEDS -> new LMedSSphereRobustEstimator(listener, points);
462 case MSAC -> new MSACSphereRobustEstimator(listener, points);
463 case PROSAC -> new PROSACSphereRobustEstimator(listener, points);
464 case PROMEDS -> new PROMedSSphereRobustEstimator(listener, points);
465 default -> new RANSACSphereRobustEstimator(listener, points);
466 };
467 }
468
469 /**
470 * Creates a sphere robust estimator based on 3D point samples and using
471 * provided robust estimator method.
472 *
473 * @param qualityScores quality scores corresponding to each provided point.
474 * @param method method of a robust estimator algorithm to estimate the best
475 * sphere.
476 * @return an instance of a sphere robust estimator.
477 * @throws IllegalArgumentException if provided quality scores length is
478 * smaller than MINIMUM_SIZE (i.e. 4 points).
479 */
480 public static SphereRobustEstimator create(final double[] qualityScores, final RobustEstimatorMethod method) {
481 return switch (method) {
482 case LMEDS -> new LMedSSphereRobustEstimator();
483 case MSAC -> new MSACSphereRobustEstimator();
484 case PROSAC -> new PROSACSphereRobustEstimator(qualityScores);
485 case PROMEDS -> new PROMedSSphereRobustEstimator(qualityScores);
486 default -> new RANSACSphereRobustEstimator();
487 };
488 }
489
490 /**
491 * Creates a sphere robust estimator based on 3D point samples and using
492 * provided points and robust estimator method.
493 *
494 * @param points 3D points to estimate a sphere.
495 * @param qualityScores quality scores corresponding to each provided point.
496 * @param method method of a robust estimator algorithm to estimate the best
497 * sphere.
498 * @return an instance of a sphere robust estimator.
499 * @throws IllegalArgumentException if provided list of points don't have
500 * the same size as the list of provided quality scores, or it their size
501 * is not greater or equal than MINIMUM_SIZE.
502 */
503 public static SphereRobustEstimator create(
504 final List<Point3D> points, final double[] qualityScores, final RobustEstimatorMethod method) {
505 return switch (method) {
506 case LMEDS -> new LMedSSphereRobustEstimator(points);
507 case MSAC -> new MSACSphereRobustEstimator(points);
508 case PROSAC -> new PROSACSphereRobustEstimator(points, qualityScores);
509 case PROMEDS -> new PROMedSSphereRobustEstimator(points, qualityScores);
510 default -> new RANSACSphereRobustEstimator(points);
511 };
512 }
513
514 /**
515 * Creates a sphere robust estimator based on 3D point samples and using
516 * provided listener.
517 *
518 * @param listener listener to be notified of events such as when estimation
519 * starts, ends or its progress significantly changes.
520 * @param qualityScores quality scores corresponding to each provided point.
521 * @param method method of a robust estimator algorithm to estimate the best
522 * sphere.
523 * @return an instance of a sphere robust estimator.
524 * @throws IllegalArgumentException if provided quality scores length is
525 * smaller than MINIMUM_SIZE (i.e. 4 points).
526 */
527 public static SphereRobustEstimator create(
528 final SphereRobustEstimatorListener listener, final double[] qualityScores,
529 final RobustEstimatorMethod method) {
530 return switch (method) {
531 case LMEDS -> new LMedSSphereRobustEstimator(listener);
532 case MSAC -> new MSACSphereRobustEstimator(listener);
533 case PROSAC -> new PROSACSphereRobustEstimator(listener, qualityScores);
534 case PROMEDS -> new PROMedSSphereRobustEstimator(listener, qualityScores);
535 default -> new RANSACSphereRobustEstimator(listener);
536 };
537 }
538
539 /**
540 * Creates a sphere robust estimator based on 3D point samples and using
541 * provided listener and points.
542 *
543 * @param listener listener to be notified of events such as when estimation
544 * starts, ends or its progress significantly changes.
545 * @param points 3D points to estimate a sphere.
546 * @param qualityScores quality scores corresponding to each provided point.
547 * @param method method of a robust estimator algorithm to estimate the best
548 * sphere.
549 * @return an instance of a sphere robust estimator.
550 * @throws IllegalArgumentException if provided list of points don't have
551 * the same size as the list of provided quality scores, or it their size
552 * is not greater or equal than MINIMUM_SIZE.
553 */
554 public static SphereRobustEstimator create(
555 final SphereRobustEstimatorListener listener, final List<Point3D> points, final double[] qualityScores,
556 final RobustEstimatorMethod method) {
557 return switch (method) {
558 case LMEDS -> new LMedSSphereRobustEstimator(listener, points);
559 case MSAC -> new MSACSphereRobustEstimator(listener, points);
560 case PROSAC -> new PROSACSphereRobustEstimator(listener, points, qualityScores);
561 case PROMEDS -> new PROMedSSphereRobustEstimator(listener, points, qualityScores);
562 default -> new RANSACSphereRobustEstimator(listener, points);
563 };
564 }
565
566 /**
567 * Creates a sphere robust estimator based on 3D point samples and using
568 * default robust estimator method.
569 *
570 * @return an instance of a sphere robust estimator.
571 */
572 public static SphereRobustEstimator create() {
573 return create(DEFAULT_ROBUST_METHOD);
574 }
575
576 /**
577 * Creates a sphere robust estimator based on 3D point samples and using
578 * provided points and default robust estimator method.
579 *
580 * @param points 3D points to estimate a sphere.
581 * @return an instance of a sphere robust estimator.
582 * @throws IllegalArgumentException if provided list of points don't have a
583 * size greater or equal than MINIMUM_SIZE.
584 */
585 public static SphereRobustEstimator create(final List<Point3D> points) {
586 return create(points, DEFAULT_ROBUST_METHOD);
587 }
588
589 /**
590 * Creates a sphere robust estimator based on 3D point samples and using
591 * provided listener and default robust estimator method.
592 *
593 * @param listener listener to be notified of events such as when estimation
594 * starts, ends or its progress significantly changes.
595 * @return an instance of a sphere robust estimator.
596 */
597 public static SphereRobustEstimator create(final SphereRobustEstimatorListener listener) {
598 return create(listener, DEFAULT_ROBUST_METHOD);
599 }
600
601 /**
602 * Creates a sphere robust estimator based on 3D point samples and using
603 * provided listener and points and default robust estimator method.
604 *
605 * @param listener listener to be notified of events such as when estimation
606 * starts, ends or its progress significantly changes.
607 * @param points 3D points to estimate a sphere.
608 * @return an instance of a sphere robust estimator.
609 * @throws IllegalArgumentException if provided list of points don't have a
610 * size greater or equal than MINIMUM_SIZE.
611 */
612 public static SphereRobustEstimator create(
613 final SphereRobustEstimatorListener listener, final List<Point3D> points) {
614 return create(listener, points, DEFAULT_ROBUST_METHOD);
615 }
616
617 /**
618 * Creates a sphere robust estimator based on 3D point samples and using
619 * default robust estimator method.
620 *
621 * @param qualityScores quality scores corresponding to each provided point.
622 * @return an instance of a sphere robust estimator.
623 * @throws IllegalArgumentException if provided quality scores length is
624 * smaller than MINIMUM_SIZE (i.e. 4 points).
625 */
626 public static SphereRobustEstimator create(final double[] qualityScores) {
627 return create(qualityScores, DEFAULT_ROBUST_METHOD);
628 }
629
630 /**
631 * Creates a sphere robust estimator based on 3D point samples and using
632 * provided points and default estimator method.
633 *
634 * @param points 3D points to estimate a sphere.
635 * @param qualityScores quality scores corresponding to each provided point.
636 * @return an instance of a sphere robust estimator.
637 * @throws IllegalArgumentException if provided list of points don't have
638 * the same size as the list of provided quality scores, or if their size
639 * is not greater or equal than MINIMUM_SIZE.
640 */
641 public static SphereRobustEstimator create(final List<Point3D> points, final double[] qualityScores) {
642 return create(points, qualityScores, DEFAULT_ROBUST_METHOD);
643 }
644
645 /**
646 * Creates a sphere robust estimator based on 3D point samples and using
647 * provided listener and default estimator method.
648 *
649 * @param listener listener to be notified of events such as when estimation
650 * starts, ends or its progress significantly changes.
651 * @param qualityScores quality scores corresponding to each provided point.
652 * @return an instance of a sphere robust estimator.
653 * @throws IllegalArgumentException if provided quality scores length is
654 * smaller than MINIMUM_SIZE (i.e. 4 points).
655 */
656 public static SphereRobustEstimator create(
657 final SphereRobustEstimatorListener listener, final double[] qualityScores) {
658 return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
659 }
660
661 /**
662 * Creates a sphere robust estimator based on 3D point samples and using
663 * provided listener and points and default estimator method.
664 *
665 * @param listener listener to be notified of events such as when estimation
666 * starts, ends or its progress significantly changes.
667 * @param points 3D points to estimate a sphere.
668 * @param qualityScores quality scores corresponding to each provided point.
669 * @return an instance of a sphere robust estimator.
670 * @throws IllegalArgumentException if provided list of points don't have
671 * the same size as the list of provided quality scores, or if their size
672 * is not greater or equal than MINIMUM_SIZE.
673 */
674 public static SphereRobustEstimator create(
675 final SphereRobustEstimatorListener listener, final List<Point3D> points, final double[] qualityScores) {
676 return create(listener, points, qualityScores, DEFAULT_ROBUST_METHOD);
677 }
678
679 /**
680 * Estimates a sphere using a robust estimator and the best set of 3D points
681 * that fit into the locus of the estimated sphere found using the robust
682 * estimator.
683 *
684 * @return a sphere.
685 * @throws LockedException if robust estimator is locked because an
686 * estimation is already in progress.
687 * @throws NotReadyException if provided input data is not enough to start
688 * the estimation.
689 * @throws RobustEstimatorException if estimation fails for any reason
690 * (i.e. numerical instability, no solution available, etc).
691 */
692 public abstract Sphere estimate() throws LockedException, NotReadyException, RobustEstimatorException;
693
694 /**
695 * Returns method being used for robust estimation.
696 *
697 * @return method being used for robust estimation.
698 */
699 public abstract RobustEstimatorMethod getMethod();
700
701 /**
702 * Internal method to set lists of points to be used to estimate a sphere.
703 * This method does not check whether estimator is locked or not
704 *
705 * @param points list of points to be used to estimate a sphere
706 * @throws IllegalArgumentException if provided list of points doesn't have
707 * a size greater or equal than MINIMUM_SIZE
708 */
709 private void internalSetPoints(final List<Point3D> points) {
710 if (points.size() < MINIMUM_SIZE) {
711 throw new IllegalArgumentException();
712 }
713 this.points = points;
714 }
715
716 /**
717 * Computes the residual between a sphere and a point.
718 *
719 * @param c a sphere.
720 * @param point a 3D point.
721 * @return residual.
722 */
723 protected double residual(final Sphere c, final Point3D point) {
724 point.normalize();
725
726 return c.getDistance(point);
727 }
728 }