You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2018/09/14 14:25:08 UTC

[commons-geometry] 03/05: GEOMETRY-8: simplifying exception handling to use mix of JDK exceptions (for argument validation and illegal states) and GeometryException subclasses (for geometry-specific situations)

This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-geometry.git

commit fc1af80256cb7b1f562aab0841267565695215fd
Author: Matt Juntunen <ma...@hotmail.com>
AuthorDate: Fri Sep 14 00:23:28 2018 -0400

    GEOMETRY-8: simplifying exception handling to use mix of JDK exceptions (for argument validation and illegal states) and GeometryException subclasses (for geometry-specific situations)
---
 .../geometry/core/exception/GeometryException.java |   4 +-
 .../core/exception/GeometryValueException.java     |  30 -----
 .../core/exception/IllegalNormException.java       |  12 +-
 .../geometry/core/exception/package-info.java      |   2 +-
 .../GeometryInternalError.java}                    |  22 ++--
 .../commons/geometry/enclosing/WelzlEncloser.java  |   3 +-
 .../geometry/euclidean/internal/Vectors.java       |  16 ++-
 .../commons/geometry/euclidean/oned/Vector1D.java  |  12 +-
 .../commons/geometry/euclidean/threed/Plane.java   |   7 +-
 .../geometry/euclidean/threed/Rotation.java        | 124 ++++++++++++++-------
 .../geometry/euclidean/threed/Vector3D.java        |   4 +-
 .../commons/geometry/euclidean/twod/Vector2D.java  |   4 +-
 .../geometry/euclidean/internal/VectorsTest.java   |  36 ++++--
 .../geometry/euclidean/threed/RotationTest.java    |  14 ++-
 .../commons/geometry/spherical/oned/ArcsSet.java   |  44 ++------
 .../spherical/twod/PropertiesComputer.java         |   3 +-
 .../geometry/spherical/oned/ArcsSetTest.java       |   2 +-
 17 files changed, 184 insertions(+), 155 deletions(-)

diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryException.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryException.java
index 48e4b2a..57462be 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryException.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryException.java
@@ -16,7 +16,9 @@
  */
 package org.apache.commons.geometry.core.exception;
 
-/** Base class for geometry exceptions.
+/** Base class for geometry exceptions. The semantics of this class
+ * are intended to be similar to {@link java.lang.ArithmeticException}
+ * but for geometric operations.
  */
 public class GeometryException extends RuntimeException {
 
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryValueException.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryValueException.java
deleted file mode 100644
index 5d7b0d6..0000000
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryValueException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.geometry.core.exception;
-
-public class GeometryValueException extends GeometryException {
-
-    /** Serializable version identifier */
-    private static final long serialVersionUID = 20180909L;
-
-    /** Simple constructor with error message.
-     * @param msg exception message string
-     */
-    public GeometryValueException(String msg) {
-        super(msg);
-    }
-}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/IllegalNormException.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/IllegalNormException.java
index b0d80e8..26fc11c 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/IllegalNormException.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/IllegalNormException.java
@@ -19,16 +19,22 @@ package org.apache.commons.geometry.core.exception;
 /** Exception thrown when an illegal vector norm value is encountered
  * in an operation.
  */
-public class IllegalNormException extends GeometryValueException {
+public class IllegalNormException extends GeometryException {
 
     /** Serializable version identifier */
     private static final long serialVersionUID = 20180909L;
 
-    /**
-     * Simple constructor accepting the illegal norm value.
+    /** Simple constructor accepting the illegal norm value.
      * @param norm the illegal norm value
      */
     public IllegalNormException(double norm) {
         super("Illegal norm: " + norm);
     }
+
+    /** Constructor accepting an error message.
+     * @param msg the error message
+     */
+    public IllegalNormException(String msg) {
+        super(msg);
+    }
 }
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/package-info.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/package-info.java
index 8180f81..2b7d21b 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/package-info.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/package-info.java
@@ -17,7 +17,7 @@
 /**
  *
  * <p>
- * This package contains exception types used by this library.
+ * This package contains specialized exception types used by this library.
  * </p>
  */
 package org.apache.commons.geometry.core.exception;
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryStateException.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/internal/GeometryInternalError.java
similarity index 50%
rename from commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryStateException.java
rename to commons-geometry-core/src/main/java/org/apache/commons/geometry/core/internal/GeometryInternalError.java
index 4a8080e..219ccdb 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/exception/GeometryStateException.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/internal/GeometryInternalError.java
@@ -14,17 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.geometry.core.exception;
+package org.apache.commons.geometry.core.internal;
 
-public class GeometryStateException extends GeometryException {
+/** Exception thrown when something that should not happen does happen.
+ * This class is not intended to be part of the public API and should
+ * never be seen by the user when algorithms are functioning correctly.
+ */
+public class GeometryInternalError extends IllegalStateException {
+
+    /** Error message used for exceptions of this type. */
+    private static final String ERROR_MSG = "An internal geometry error occurred. This most often indicates an " +
+            "error in the algorithm implementation than in the calling code or data. Please file a bug report " +
+            "with the developers.";
 
     /** Serializable version identifier */
-    private static final long serialVersionUID = 20180909L;
+    private static final long serialVersionUID = 20180913L;
 
-    /** Simple constructor with error message.
-     * @param msg exception message string
+    /** Simple constructor with a default error message.
      */
-    public GeometryStateException(String msg) {
-        super(msg);
+    public GeometryInternalError() {
+        super(ERROR_MSG);
     }
 }
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java
index 4ec5ad5..65dbc2a 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.geometry.core.Point;
+import org.apache.commons.geometry.core.internal.GeometryInternalError;
 
 /** Class implementing Emo Welzl algorithm to find the smallest enclosing ball in linear time.
  * <p>
@@ -98,7 +99,7 @@ public class WelzlEncloser<P extends Point<P>> implements Encloser<P> {
             ball = moveToFrontBall(extreme, extreme.size(), support);
             if (ball.getRadius() < savedBall.getRadius()) {
                 // this should never happen
-                throw new IllegalStateException("Please file a bug report");
+                throw new GeometryInternalError();
             }
 
             // it was an interesting point, move it to the front
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/internal/Vectors.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/internal/Vectors.java
index cbb19b2..31ec162 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/internal/Vectors.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/internal/Vectors.java
@@ -25,17 +25,27 @@ public final class Vectors {
     /** Private constructor. */
     private Vectors() {}
 
+    /** Returns true if the given value is finite (ie, not NaN or inifinite)
+     * and not equal to zero.
+     * @param value the value to test
+     * @return true if {@code value} is not NaN, infinite, or zero; otherwise
+     *      false
+     */
+    public static boolean isFiniteNonZero(final double value) {
+        return Double.isFinite(value) && value != 0.0;
+    }
+
 
     /** Throws an {@link IllegalNormException} if the  given norm value
      * is not finite (ie, NaN or infinite) or zero. The argument is returned
-     * to allow this method to be called in-line.
+     * to allow this method to be called inline.
      * @param norm vector norm value
      * @return the validated norm value
      * @throws IllegalNormException if the given norm value is NaN, infinite,
      *  or zero
      */
-    public static double checkFiniteNonZeroNorm(final double norm) throws IllegalNormException {
-        if (!Double.isFinite(norm) || norm == 0.0) {
+    public static double ensureFiniteNonZeroNorm(final double norm) throws IllegalNormException {
+        if (!isFiniteNonZero(norm)) {
             throw new IllegalNormException(norm);
         }
 
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
index 26df5d1..79a4d35 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
@@ -116,7 +116,7 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point
     /** {@inheritDoc} */
     @Override
     public Vector1D withMagnitude(double magnitude) {
-        Vectors.checkFiniteNonZeroNorm(getNorm());
+        Vectors.ensureFiniteNonZeroNorm(getNorm());
 
         return (getX() > 0.0)? new Vector1D(magnitude) : new Vector1D(-magnitude);
     }
@@ -154,7 +154,7 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point
     /** {@inheritDoc} */
     @Override
     public Vector1D normalize() {
-        Vectors.checkFiniteNonZeroNorm(getNorm());
+        Vectors.ensureFiniteNonZeroNorm(getNorm());
 
         return (getX() > 0.0) ? ONE : MINUS_ONE;
     }
@@ -200,7 +200,7 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point
      */
     @Override
     public Vector1D project(final Vector1D base) {
-        Vectors.checkFiniteNonZeroNorm(base.getNorm());
+        Vectors.ensureFiniteNonZeroNorm(base.getNorm());
 
         return this;
     }
@@ -210,7 +210,7 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point
      */
     @Override
     public Vector1D reject(final Vector1D base) {
-        Vectors.checkFiniteNonZeroNorm(base.getNorm());
+        Vectors.ensureFiniteNonZeroNorm(base.getNorm());
 
         return Vector1D.ZERO;
     }
@@ -221,8 +221,8 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point
      */
     @Override
     public double angle(final Vector1D v) {
-        Vectors.checkFiniteNonZeroNorm(getNorm());
-        Vectors.checkFiniteNonZeroNorm(v.getNorm());
+        Vectors.ensureFiniteNonZeroNorm(getNorm());
+        Vectors.ensureFiniteNonZeroNorm(v.getNorm());
 
         final double sig1 = Math.signum(getX());
         final double sig2 = Math.signum(v.getX());
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java
index bc3c040..424fbb3 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java
@@ -18,6 +18,7 @@ package org.apache.commons.geometry.euclidean.threed;
 
 import org.apache.commons.geometry.core.partitioning.Embedding;
 import org.apache.commons.geometry.core.partitioning.Hyperplane;
+import org.apache.commons.geometry.euclidean.internal.Vectors;
 import org.apache.commons.geometry.euclidean.oned.Point1D;
 import org.apache.commons.geometry.euclidean.twod.Point2D;
 import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
@@ -141,10 +142,8 @@ public class Plane implements Hyperplane<Point3D>, Embedding<Point3D, Point2D> {
      * @exception IllegalArgumentException if the normal norm is too close to zero
      */
     private void setNormal(final Vector3D normal) {
-        final double norm = normal.getNorm();
-        if (norm < 1.0e-10) {
-            throw new IllegalArgumentException("Norm is zero");
-        }
+        final double norm = Vectors.ensureFiniteNonZeroNorm(normal.getNorm());
+
         w = Vector3D.linearCombination(1.0 / norm, normal);
     }
 
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java
index 2e9b63d..466aedc 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java
@@ -19,7 +19,9 @@ package org.apache.commons.geometry.euclidean.threed;
 
 import java.io.Serializable;
 
+import org.apache.commons.geometry.core.exception.GeometryException;
 import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.euclidean.internal.Vectors;
 import org.apache.commons.numbers.arrays.LinearCombination;
 
 /**
@@ -97,12 +99,6 @@ public class Rotation implements Serializable {
   /** Serializable version identifier */
   private static final long serialVersionUID = 20180903L;
 
-  /** Error message for Cardan angle singularities */
-  private static final String CARDAN_SINGULARITY_MSG = "Cardan angles singularity";
-
-  /** Error message for Euler angle singularities */
-  private static final String EULER_SINGULARITY_MSG = "Euler angles singularity";
-
   /** Scalar coordinate of the quaternion. */
   private final double q0;
 
@@ -172,14 +168,14 @@ public class Rotation implements Serializable {
    * @param axis axis around which to rotate
    * @param angle rotation angle
    * @param convention convention to use for the semantics of the angle
-   * @exception IllegalArgumentException if the axis norm is zero
+   * @exception IllegalNormException if the axis norm is zero, NaN, or infinite
    */
   public Rotation(final Vector3D axis, final double angle, final RotationConvention convention)
-      throws IllegalArgumentException {
+      throws IllegalNormException {
 
     double norm = axis.getNorm();
-    if (norm == 0) {
-      throw new IllegalArgumentException("Zero norm for rotation axis");
+    if (!Vectors.isFiniteNonZero(norm)) {
+      throw new IllegalNormException("Illegal norm for rotation axis: " + norm);
     }
 
     double halfAngle = convention == RotationConvention.VECTOR_OPERATOR ? -0.5 * angle : +0.5 * angle;
@@ -320,13 +316,13 @@ public class Rotation implements Serializable {
 
    * @param u origin vector
    * @param v desired image of u by the rotation
-   * @exception IllegalArgumentException if the norm of one of the vectors is zero
+   * @exception IllegalNormException if the norm of one of the vectors is zero, NaN, or infinite
    */
   public Rotation(Vector3D u, Vector3D v) {
 
     double normProduct = u.getNorm() * v.getNorm();
-    if (normProduct == 0) {
-        throw new IllegalArgumentException("Zero norm for rotation defining vector");
+    if (!Vectors.isFiniteNonZero(normProduct)) {
+        throw new IllegalNormException("Illegal norm for rotation defining vector: " + normProduct);
     }
 
     double dot = u.dotProduct(v);
@@ -568,13 +564,13 @@ public class Rotation implements Serializable {
 
    * @param order rotation order to use
    * @return an array of three angles, in the order specified by the set
-   * @exception IllegalStateException if the rotation is
+   * @exception AngleSetSingularityException if the rotation is
    * singular with respect to the angles set specified
    * @deprecated as of 3.6, replaced with {@link #getAngles(RotationOrder, RotationConvention)}
    */
   @Deprecated
   public double[] getAngles(RotationOrder order)
-      throws IllegalStateException {
+      throws AngleSetSingularityException {
       return getAngles(order, RotationConvention.VECTOR_OPERATOR);
   }
 
@@ -611,11 +607,11 @@ public class Rotation implements Serializable {
    * @param order rotation order to use
    * @param convention convention to use for the semantics of the angle
    * @return an array of three angles, in the order specified by the set
-   * @exception IllegalStateException if the rotation is
-   * singular with respect to the angles set specified
+   * @exception AngleSetSingularityException if the rotation is
+   * singular with respect to the angle set specified
    */
   public double[] getAngles(RotationOrder order, RotationConvention convention)
-      throws IllegalStateException {
+      throws AngleSetSingularityException {
 
       if (convention == RotationConvention.VECTOR_OPERATOR) {
           if (order == RotationOrder.XYZ) {
@@ -628,7 +624,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if  ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(-(v1.getY()), v1.getZ()),
@@ -646,7 +642,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getZ(), v1.getY()),
@@ -664,7 +660,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getX(), v1.getZ()),
@@ -682,7 +678,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(-(v1.getZ()), v1.getX()),
@@ -700,7 +696,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(-(v1.getX()), v1.getY()),
@@ -718,7 +714,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getY(), v1.getX()),
@@ -736,7 +732,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getY(), -v1.getZ()),
@@ -754,7 +750,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getZ(), v1.getY()),
@@ -772,7 +768,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getX(), v1.getZ()),
@@ -790,7 +786,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getZ(), -v1.getX()),
@@ -808,7 +804,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getX(), -v1.getY()),
@@ -826,7 +822,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v1.getY(), v1.getX()),
@@ -846,7 +842,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(-v2.getY(), v2.getZ()),
@@ -864,7 +860,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getZ(), v2.getY()),
@@ -882,7 +878,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getX(), v2.getZ()),
@@ -900,7 +896,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(-v2.getZ(), v2.getX()),
@@ -918,7 +914,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(-v2.getX(), v2.getY()),
@@ -936,7 +932,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if  ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
+                  throw new CardanSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getY(), v2.getX()),
@@ -954,7 +950,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getY(), -v2.getZ()),
@@ -972,7 +968,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_X);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
               if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getZ(), v2.getY()),
@@ -990,7 +986,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getX(), v2.getZ()),
@@ -1008,7 +1004,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Y);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
               if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getZ(), -v2.getX()),
@@ -1026,7 +1022,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getX(), -v2.getY()),
@@ -1044,7 +1040,7 @@ public class Rotation implements Serializable {
               Vector3D v1 = applyTo(Vector3D.PLUS_Z);
               Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
               if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
-                  throw new IllegalStateException(EULER_SINGULARITY_MSG);
+                  throw new EulerSingularityException();
               }
               return new double[] {
                   Math.atan2(v2.getY(), v2.getX()),
@@ -1411,4 +1407,48 @@ public class Rotation implements Serializable {
       return r1.composeInverseInternal(r2).getAngle();
   }
 
+  /** Exception thrown when an angle set encounters a singularity.
+   */
+  public static class AngleSetSingularityException extends GeometryException {
+
+    /** Serializable version identifier */
+    private static final long serialVersionUID = 20180913L;
+
+    /** Simple constructor with an error message.
+     * @param msg error message
+     */
+    public AngleSetSingularityException(String msg) {
+      super(msg);
+    }
+  }
+
+  /** Exception thrown when a Cardan angles singularity is encountered.
+   */
+  public static class CardanSingularityException extends AngleSetSingularityException {
+
+    /** Serializable version identifier */
+    private static final long serialVersionUID = 20180913L;
+
+    /**
+     * Simple constructor.
+     */
+    public CardanSingularityException() {
+      super("Cardan angles singularity");
+    }
+  }
+
+  /** Exception thrown when an Euler angles singularity is encountered.
+   */
+  public static class EulerSingularityException extends AngleSetSingularityException {
+
+    /** Serializable version identifier */
+    private static final long serialVersionUID = 20180913L;
+
+    /**
+     * Simple constructor.
+     */
+    public EulerSingularityException() {
+      super("Euler angles singularity");
+    }
+  }
 }
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
index 5c5317c..4b96f43 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
@@ -389,7 +389,7 @@ public final class Vector3D extends Cartesian3D implements EuclideanVector<Point
      * @throws IllegalNormException if the norm is zero, NaN, or infinite
      */
     private double getFiniteNonZeroNorm() {
-        return Vectors.checkFiniteNonZeroNorm(getNorm());
+        return Vectors.ensureFiniteNonZeroNorm(getNorm());
     }
 
     /** Returns a component of the current instance relative to the given base
@@ -406,7 +406,7 @@ public final class Vector3D extends Cartesian3D implements EuclideanVector<Point
     private Vector3D getComponent(Vector3D base, boolean reject) {
         final double aDotB = dotProduct(base);
 
-        final double baseMag = Vectors.checkFiniteNonZeroNorm(base.getNorm());
+        final double baseMag = Vectors.ensureFiniteNonZeroNorm(base.getNorm());
 
         final double scale = aDotB / (baseMag * baseMag);
 
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
index 1d7be1c..36338d0 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
@@ -334,7 +334,7 @@ public final class Vector2D extends Cartesian2D implements EuclideanVector<Point
      * @throws IllegalNormException if the norm is zero, NaN, or infinite
      */
     private double getFiniteNonZeroNorm() {
-        return Vectors.checkFiniteNonZeroNorm(getNorm());
+        return Vectors.ensureFiniteNonZeroNorm(getNorm());
     }
 
     /** Returns a component of the current instance relative to the given base
@@ -351,7 +351,7 @@ public final class Vector2D extends Cartesian2D implements EuclideanVector<Point
     private Vector2D getComponent(Vector2D base, boolean reject) {
         final double aDotB = dotProduct(base);
 
-        final double baseMag = Vectors.checkFiniteNonZeroNorm(base.getNorm());
+        final double baseMag = Vectors.ensureFiniteNonZeroNorm(base.getNorm());
 
         final double scale = aDotB / (baseMag * baseMag);
 
diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/internal/VectorsTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/internal/VectorsTest.java
index 2d38904..2d38b03 100644
--- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/internal/VectorsTest.java
+++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/internal/VectorsTest.java
@@ -27,23 +27,37 @@ public class VectorsTest {
     private static final double EPS = Math.ulp(1d);
 
     @Test
-    public void testCheckFiniteNonZeroNorm() {
+    public void testIsFiniteNonZero() {
         // act/assert
-        Assert.assertEquals(1.0, Vectors.checkFiniteNonZeroNorm(1.0), EPS);
-        Assert.assertEquals(23.12, Vectors.checkFiniteNonZeroNorm(23.12), EPS);
-        Assert.assertEquals(2e-12, Vectors.checkFiniteNonZeroNorm(2e-12), EPS);
+        Assert.assertTrue(Vectors.isFiniteNonZero(1e-20));
+        Assert.assertTrue(Vectors.isFiniteNonZero(1e20));
+        Assert.assertTrue(Vectors.isFiniteNonZero(-1e-20));
+        Assert.assertTrue(Vectors.isFiniteNonZero(-1e20));
+
+        Assert.assertFalse(Vectors.isFiniteNonZero(0.0));
+        Assert.assertFalse(Vectors.isFiniteNonZero(Double.NaN));
+        Assert.assertFalse(Vectors.isFiniteNonZero(Double.POSITIVE_INFINITY));
+        Assert.assertFalse(Vectors.isFiniteNonZero(Double.NEGATIVE_INFINITY));
+    }
+
+    @Test
+    public void testEnsureFiniteNonZeroNorm() {
+        // act/assert
+        Assert.assertEquals(1.0, Vectors.ensureFiniteNonZeroNorm(1.0), EPS);
+        Assert.assertEquals(23.12, Vectors.ensureFiniteNonZeroNorm(23.12), EPS);
+        Assert.assertEquals(2e-12, Vectors.ensureFiniteNonZeroNorm(2e-12), EPS);
 
-        Assert.assertEquals(-1.0, Vectors.checkFiniteNonZeroNorm(-1.0), EPS);
-        Assert.assertEquals(-23.12, Vectors.checkFiniteNonZeroNorm(-23.12), EPS);
-        Assert.assertEquals(-2e-12, Vectors.checkFiniteNonZeroNorm(-2e-12), EPS);
+        Assert.assertEquals(-1.0, Vectors.ensureFiniteNonZeroNorm(-1.0), EPS);
+        Assert.assertEquals(-23.12, Vectors.ensureFiniteNonZeroNorm(-23.12), EPS);
+        Assert.assertEquals(-2e-12, Vectors.ensureFiniteNonZeroNorm(-2e-12), EPS);
 
-        GeometryTestUtils.assertThrows(() -> Vectors.checkFiniteNonZeroNorm(0.0),
+        GeometryTestUtils.assertThrows(() -> Vectors.ensureFiniteNonZeroNorm(0.0),
                 IllegalNormException.class, "Illegal norm: 0.0");
-        GeometryTestUtils.assertThrows(() -> Vectors.checkFiniteNonZeroNorm(Double.NaN),
+        GeometryTestUtils.assertThrows(() -> Vectors.ensureFiniteNonZeroNorm(Double.NaN),
                 IllegalNormException.class, "Illegal norm: NaN");
-        GeometryTestUtils.assertThrows(() -> Vectors.checkFiniteNonZeroNorm(Double.POSITIVE_INFINITY),
+        GeometryTestUtils.assertThrows(() -> Vectors.ensureFiniteNonZeroNorm(Double.POSITIVE_INFINITY),
                 IllegalNormException.class, "Illegal norm: Infinity");
-        GeometryTestUtils.assertThrows(() -> Vectors.checkFiniteNonZeroNorm(Double.NEGATIVE_INFINITY),
+        GeometryTestUtils.assertThrows(() -> Vectors.ensureFiniteNonZeroNorm(Double.NEGATIVE_INFINITY),
                 IllegalNormException.class, "Illegal norm: -Infinity");
     }
 
diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RotationTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RotationTest.java
index 9e5bad0..136a4cb 100644
--- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RotationTest.java
+++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RotationTest.java
@@ -18,6 +18,8 @@
 package org.apache.commons.geometry.euclidean.threed;
 
 import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.euclidean.threed.Rotation.CardanSingularityException;
+import org.apache.commons.geometry.euclidean.threed.Rotation.EulerSingularityException;
 import org.apache.commons.numbers.angle.PlaneAngleRadians;
 import org.junit.Assert;
 import org.junit.Test;
@@ -63,7 +65,7 @@ public class RotationTest {
     try {
       new Rotation(Vector3D.of(0, 0, 0), 2 * Math.PI / 3);
       Assert.fail("an exception should have been thrown");
-    } catch (IllegalArgumentException e) {
+    } catch (IllegalNormException e) {
     }
 
     r = new Rotation(Vector3D.PLUS_Z, 1.5 * Math.PI);
@@ -93,7 +95,7 @@ public class RotationTest {
     try {
       new Rotation(Vector3D.of(0, 0, 0), 2 * Math.PI / 3, RotationConvention.VECTOR_OPERATOR);
       Assert.fail("an exception should have been thrown");
-    } catch (IllegalArgumentException e) {
+    } catch (IllegalNormException e) {
     }
 
     r = new Rotation(Vector3D.PLUS_Z, 1.5 * Math.PI, RotationConvention.VECTOR_OPERATOR);
@@ -126,7 +128,7 @@ public class RotationTest {
     try {
       new Rotation(Vector3D.of(0, 0, 0), 2 * Math.PI / 3, RotationConvention.FRAME_TRANSFORM);
       Assert.fail("an exception should have been thrown");
-    } catch (IllegalArgumentException e) {
+    } catch (IllegalNormException e) {
     }
 
     r = new Rotation(Vector3D.PLUS_Z, 1.5 * Math.PI, RotationConvention.FRAME_TRANSFORM);
@@ -196,7 +198,7 @@ public class RotationTest {
     try {
         new Rotation(u, Vector3D.ZERO);
         Assert.fail("an exception should have been thrown");
-    } catch (IllegalArgumentException e) {
+    } catch (IllegalNormException e) {
         // expected behavior
     }
 
@@ -494,7 +496,7 @@ public class RotationTest {
                   try {
                       r.getAngles(CardanOrders[i], convention);
                       Assert.fail("an exception should have been caught");
-                  } catch (IllegalStateException cese) {
+                  } catch (CardanSingularityException cese) {
                       // expected behavior
                   }
               }
@@ -512,7 +514,7 @@ public class RotationTest {
                   try {
                       r.getAngles(EulerOrders[i], convention);
                       Assert.fail("an exception should have been caught");
-                  } catch (IllegalStateException cese) {
+                  } catch (EulerSingularityException cese) {
                       // expected behavior
                   }
               }
diff --git a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/ArcsSet.java b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/ArcsSet.java
index 311950f..8ca86ce 100644
--- a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/ArcsSet.java
+++ b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/ArcsSet.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.NoSuchElementException;
 
 import org.apache.commons.geometry.core.Geometry;
+import org.apache.commons.geometry.core.internal.GeometryInternalError;
 import org.apache.commons.geometry.core.partitioning.AbstractRegion;
 import org.apache.commons.geometry.core.partitioning.BSPTree;
 import org.apache.commons.geometry.core.partitioning.BoundaryProjection;
@@ -42,9 +43,6 @@ import org.apache.commons.numbers.core.Precision;
  */
 public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterable<double[]> {
 
-    /** Message used for internal errors. */
-    private static final String INTERNAL_ERROR_MESSAGE = "Please file a bug report";
-
     /** Build an arcs set representing the whole circle.
      * @param tolerance tolerance below which close sub-arcs are merged together
      */
@@ -79,11 +77,11 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
      * {@code Boolean.TRUE} and {@code Boolean.FALSE}</p>
      * @param tree inside/outside BSP tree representing the arcs set
      * @param tolerance tolerance below which close sub-arcs are merged together
-     * @exception InconsistentStateAt2PiWrapping if the tree leaf nodes are not
+     * @exception IllegalArgumentException if the tree leaf nodes are not
      * consistent across the \( 0, 2 \pi \) crossing
      */
     public ArcsSet(final BSPTree<S1Point> tree, final double tolerance)
-        throws InconsistentStateAt2PiWrapping {
+        throws IllegalArgumentException {
         super(tree, tolerance);
         check2PiConsistency();
     }
@@ -107,11 +105,11 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
      * space.</p>
      * @param boundary collection of boundary elements
      * @param tolerance tolerance below which close sub-arcs are merged together
-     * @exception InconsistentStateAt2PiWrapping if the tree leaf nodes are not
+     * @exception IllegalArgumentException if the tree leaf nodes are not
      * consistent across the \( 0, 2 \pi \) crossing
      */
     public ArcsSet(final Collection<SubHyperplane<S1Point>> boundary, final double tolerance)
-        throws InconsistentStateAt2PiWrapping {
+        throws IllegalArgumentException {
         super(boundary, tolerance);
         check2PiConsistency();
     }
@@ -167,10 +165,10 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
     }
 
     /** Check consistency.
-    * @exception InconsistentStateAt2PiWrapping if the tree leaf nodes are not
+    * @exception IllegalArgumentException if the tree leaf nodes are not
     * consistent across the \( 0, 2 \pi \) crossing
     */
-    private void check2PiConsistency() throws InconsistentStateAt2PiWrapping {
+    private void check2PiConsistency() throws IllegalArgumentException {
 
         // start search at the tree root
         BSPTree<S1Point> root = getTree(false);
@@ -185,7 +183,7 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
         final Boolean stateAfter = (Boolean) getLastLeaf(root).getAttribute();
 
         if (stateBefore ^ stateAfter) {
-            throw new InconsistentStateAt2PiWrapping();
+            throw new IllegalArgumentException("Inconsistent state at 2\\u03c0 wrapping");
         }
 
     }
@@ -655,7 +653,7 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
                 }
                 if (end == null) {
                     // this should never happen
-                    throw new IllegalStateException(INTERNAL_ERROR_MESSAGE);
+                    throw new GeometryInternalError();
                 }
 
                 // we have identified the last arc
@@ -794,7 +792,7 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
         final BSPTree<S1Point> node = tree.getCell(limit.getLocation(), getTolerance());
         if (node.getCut() != null) {
             // this should never happen
-            throw new IllegalStateException(INTERNAL_ERROR_MESSAGE);
+            throw new GeometryInternalError();
         }
 
         node.insertCut(limit);
@@ -926,27 +924,5 @@ public class ArcsSet extends AbstractRegion<S1Point, S1Point> implements Iterabl
                 return Side.HYPER;
             }
         }
-
-    }
-
-    /** Specialized exception for inconsistent BSP tree state inconsistency.
-     * <p>
-     * This exception is thrown at {@link ArcsSet} construction time when the
-     * {@link org.apache.commons.geometry.core.partitioning.Region.Location inside/outside}
-     * state is not consistent at the 0, \(2 \pi \) crossing.
-     * </p>
-     */
-    public static class InconsistentStateAt2PiWrapping extends IllegalArgumentException {
-
-        /** Serializable UID. */
-        private static final long serialVersionUID = 20140107L;
-
-        /** Simple constructor.
-         */
-        public InconsistentStateAt2PiWrapping() {
-            super("Inconsistent state at 2\\u03c0 wrapping");
-        }
-
     }
-
 }
diff --git a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/PropertiesComputer.java b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/PropertiesComputer.java
index 3f6da88..536a2dd 100644
--- a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/PropertiesComputer.java
+++ b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/PropertiesComputer.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.geometry.core.Geometry;
+import org.apache.commons.geometry.core.internal.GeometryInternalError;
 import org.apache.commons.geometry.core.partitioning.BSPTree;
 import org.apache.commons.geometry.core.partitioning.BSPTreeVisitor;
 import org.apache.commons.geometry.euclidean.threed.Point3D;
@@ -79,7 +80,7 @@ class PropertiesComputer implements BSPTreeVisitor<S2Point> {
             final List<Vertex> boundary = convex.getBoundaryLoops();
             if (boundary.size() != 1) {
                 // this should never happen
-                throw new IllegalStateException("Please file a bug report");
+                throw new GeometryInternalError();
             }
 
             // compute the geometrical properties of the convex cell
diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/ArcsSetTest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/ArcsSetTest.java
index a6bab1a..8d8c600 100644
--- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/ArcsSetTest.java
+++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/ArcsSetTest.java
@@ -358,7 +358,7 @@ public class ArcsSetTest {
 
     }
 
-    @Test(expected=ArcsSet.InconsistentStateAt2PiWrapping.class)
+    @Test(expected=IllegalArgumentException.class)
     public void testInconsistentState() {
         SubLimitAngle l1 = new LimitAngle(S1Point.of(1.0), false, 1.0e-10).wholeHyperplane();
         SubLimitAngle l2 = new LimitAngle(S1Point.of(2.0), true,  1.0e-10).wholeHyperplane();