You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2015/09/06 20:21:50 UTC

[2/2] [math] Fixed split/side inconsistencies in BSP trees.

Fixed split/side inconsistencies in BSP trees.

JIRA: MATH-1266


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/2091cfba
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/2091cfba
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/2091cfba

Branch: refs/heads/master
Commit: 2091cfbabc4e4940f70c2628cadc08da0baaedc8
Parents: 870d11b
Author: Luc Maisonobe <lu...@apache.org>
Authored: Sun Sep 6 20:17:13 2015 +0200
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Sun Sep 6 20:17:13 2015 +0200

----------------------------------------------------------------------
 src/changes/changes.xml                         |  3 +
 .../math4/exception/util/LocalizedFormats.java  |  1 +
 .../euclidean/oned/SubOrientedPoint.java        | 18 ++---
 .../geometry/euclidean/threed/SubPlane.java     | 50 ++------------
 .../math4/geometry/euclidean/twod/SubLine.java  | 33 ++-------
 .../geometry/partitioning/AbstractRegion.java   | 49 ++++++-------
 .../partitioning/AbstractSubHyperplane.java     |  4 --
 .../math4/geometry/partitioning/BSPTree.java    |  8 +--
 .../geometry/partitioning/Characterization.java |  4 +-
 .../geometry/partitioning/InsideFinder.java     |  8 +--
 .../math4/geometry/partitioning/Region.java     | 10 ---
 .../geometry/partitioning/RegionFactory.java    | 29 ++++++++
 .../geometry/partitioning/SubHyperplane.java    | 30 +++++---
 .../math4/geometry/spherical/oned/ArcsSet.java  | 57 +++++++---------
 .../geometry/spherical/oned/SubLimitAngle.java  |  8 ---
 .../geometry/spherical/twod/SubCircle.java      | 28 +-------
 .../util/LocalizedFormats_fr.properties         |  1 +
 .../exception/util/LocalizedFormatsTest.java    |  2 +-
 .../euclidean/twod/PolygonsSetTest.java         | 14 +++-
 .../geometry/spherical/oned/ArcsSetTest.java    | 72 ++++++++++++--------
 .../twod/SphericalPolygonsSetTest.java          | 22 ++++--
 .../geometry/spherical/twod/SubCircleTest.java  | 33 ++++++---
 22 files changed, 231 insertions(+), 253 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ee4b64c..91f3b24 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -54,6 +54,9 @@ If the output is not quite correct, check for invisible trailing spaces!
     </release>
 
     <release version="4.0" date="XXXX-XX-XX" description="">
+      <action dev="luc" type="fix" issue="MATH-1266"> <!-- backported to 3.6 -->
+        Fixed split/side inconsistencies in BSP trees.
+      </action>
       <action dev="erans" type="add" issue="MATH-1265"> <!-- backported to 3.6 -->
         "NeuronSquareMesh2D" (package "o.a.c.m.ml.neuralnet.twod") implements "Iterable".
       </action>

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/exception/util/LocalizedFormats.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/exception/util/LocalizedFormats.java b/src/main/java/org/apache/commons/math4/exception/util/LocalizedFormats.java
index 699a0cc..4349e40 100644
--- a/src/main/java/org/apache/commons/math4/exception/util/LocalizedFormats.java
+++ b/src/main/java/org/apache/commons/math4/exception/util/LocalizedFormats.java
@@ -180,6 +180,7 @@ public enum LocalizedFormats implements Localizable {
     NUMBER_OF_INTERPOLATION_POINTS("number of interpolation points ({0})"), /* keep */
     NUMBER_OF_TRIALS("number of trials ({0})"),
     NOT_CONVEX("vertices do not form a convex hull in CCW winding"),
+    NOT_CONVEX_HYPERPLANES("hyperplanes do not define a convex region"),
     ROBUSTNESS_ITERATIONS("number of robustness iterations ({0})"),
     START_POSITION("start position ({0})"), /* keep */
     NON_CONVERGENT_CONTINUED_FRACTION("Continued fraction convergents failed to converge (in less than {0} iterations) for value {1}"),

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPoint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPoint.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPoint.java
index dc654e9..a80873d 100644
--- a/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPoint.java
+++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPoint.java
@@ -19,7 +19,6 @@ package org.apache.commons.math4.geometry.euclidean.oned;
 import org.apache.commons.math4.geometry.partitioning.AbstractSubHyperplane;
 import org.apache.commons.math4.geometry.partitioning.Hyperplane;
 import org.apache.commons.math4.geometry.partitioning.Region;
-import org.apache.commons.math4.geometry.partitioning.Side;
 
 /** This class represents sub-hyperplane for {@link OrientedPoint}.
  * <p>An hyperplane in 1D is a simple point, its orientation being a
@@ -59,18 +58,15 @@ public class SubOrientedPoint extends AbstractSubHyperplane<Euclidean1D, Euclide
 
     /** {@inheritDoc} */
     @Override
-    public Side side(final Hyperplane<Euclidean1D> hyperplane) {
-        final double global = hyperplane.getOffset(((OrientedPoint) getHyperplane()).getLocation());
-        return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER);
-    }
-
-    /** {@inheritDoc} */
-    @Override
     public SplitSubHyperplane<Euclidean1D> split(final Hyperplane<Euclidean1D> hyperplane) {
         final double global = hyperplane.getOffset(((OrientedPoint) getHyperplane()).getLocation());
-        return (global < -1.0e-10) ?
-                                    new SplitSubHyperplane<Euclidean1D>(null, this) :
-                                        new SplitSubHyperplane<Euclidean1D>(this, null);
+        if (global < -1.0e-10) {
+            return new SplitSubHyperplane<Euclidean1D>(null, this);
+        } else if (global > 1.0e-10) {
+            return new SplitSubHyperplane<Euclidean1D>(this, null);
+        } else {
+            return new SplitSubHyperplane<Euclidean1D>(null, null);
+        }
     }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java
index 9bab72f..89885d4 100644
--- a/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java
+++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/threed/SubPlane.java
@@ -26,7 +26,6 @@ import org.apache.commons.math4.geometry.partitioning.AbstractSubHyperplane;
 import org.apache.commons.math4.geometry.partitioning.BSPTree;
 import org.apache.commons.math4.geometry.partitioning.Hyperplane;
 import org.apache.commons.math4.geometry.partitioning.Region;
-import org.apache.commons.math4.geometry.partitioning.Side;
 import org.apache.commons.math4.geometry.partitioning.SubHyperplane;
 
 /** This class represents a sub-hyperplane for {@link Plane}.
@@ -50,45 +49,6 @@ public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> {
         return new SubPlane(hyperplane, remainingRegion);
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public Side side(Hyperplane<Euclidean3D> hyperplane) {
-
-        final Plane otherPlane = (Plane) hyperplane;
-        final Plane thisPlane  = (Plane) getHyperplane();
-        final Line  inter      = otherPlane.intersection(thisPlane);
-        final double tolerance = thisPlane.getTolerance();
-
-        if (inter == null) {
-            // the hyperplanes are parallel,
-            // any point can be used to check their relative position
-            final double global = otherPlane.getOffset(thisPlane);
-            return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER);
-        }
-
-        // create a 2D line in the otherPlane canonical 2D frame such that:
-        //   - the line is the crossing line of the two planes in 3D
-        //   - the line splits the otherPlane in two half planes with an
-        //     orientation consistent with the orientation of the instance
-        //     (i.e. the 3D half space on the plus side (resp. minus side)
-        //      of the instance contains the 2D half plane on the plus side
-        //      (resp. minus side) of the 2D line
-        Vector2D p = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ZERO));
-        Vector2D q = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ONE));
-        Vector3D crossP = Vector3D.crossProduct(inter.getDirection(), thisPlane.getNormal());
-        if (crossP.dotProduct(otherPlane.getNormal()) < 0) {
-            final Vector2D tmp = p;
-            p           = q;
-            q           = tmp;
-        }
-        final org.apache.commons.math4.geometry.euclidean.twod.Line line2D =
-            new org.apache.commons.math4.geometry.euclidean.twod.Line(p, q, tolerance);
-
-        // check the side on the 2D plane
-        return getRemainingRegion().side(line2D);
-
-    }
-
     /** Split the instance in two parts by an hyperplane.
      * @param hyperplane splitting hyperplane
      * @return an object containing both the part of the instance
@@ -106,9 +66,13 @@ public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> {
         if (inter == null) {
             // the hyperplanes are parallel
             final double global = otherPlane.getOffset(thisPlane);
-            return (global < -1.0e-10) ?
-                   new SplitSubHyperplane<Euclidean3D>(null, this) :
-                   new SplitSubHyperplane<Euclidean3D>(this, null);
+            if (global < -tolerance) {
+                return new SplitSubHyperplane<Euclidean3D>(null, this);
+            } else if (global > tolerance) {
+                return new SplitSubHyperplane<Euclidean3D>(this, null);
+            } else {
+                return new SplitSubHyperplane<Euclidean3D>(null, null);
+            }
         }
 
         // the hyperplanes do intersect

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/SubLine.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/SubLine.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/SubLine.java
index 2976b3f..4f53e6c 100644
--- a/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/SubLine.java
+++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/SubLine.java
@@ -29,7 +29,6 @@ import org.apache.commons.math4.geometry.partitioning.AbstractSubHyperplane;
 import org.apache.commons.math4.geometry.partitioning.BSPTree;
 import org.apache.commons.math4.geometry.partitioning.Hyperplane;
 import org.apache.commons.math4.geometry.partitioning.Region;
-import org.apache.commons.math4.geometry.partitioning.Side;
 import org.apache.commons.math4.geometry.partitioning.SubHyperplane;
 import org.apache.commons.math4.geometry.partitioning.Region.Location;
 import org.apache.commons.math4.util.FastMath;
@@ -158,27 +157,6 @@ public class SubLine extends AbstractSubHyperplane<Euclidean2D, Euclidean1D> {
 
     /** {@inheritDoc} */
     @Override
-    public Side side(final Hyperplane<Euclidean2D> hyperplane) {
-
-        final Line    thisLine  = (Line) getHyperplane();
-        final Line    otherLine = (Line) hyperplane;
-        final Vector2D crossing  = thisLine.intersection(otherLine);
-
-        if (crossing == null) {
-            // the lines are parallel,
-            final double global = otherLine.getOffset(thisLine);
-            return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER);
-        }
-
-        // the lines do intersect
-        final boolean direct = FastMath.sin(thisLine.getAngle() - otherLine.getAngle()) < 0;
-        final Vector1D x = thisLine.toSubSpace((Point<Euclidean2D>) crossing);
-        return getRemainingRegion().side(new OrientedPoint(x, direct, thisLine.getTolerance()));
-
-    }
-
-    /** {@inheritDoc} */
-    @Override
     public SplitSubHyperplane<Euclidean2D> split(final Hyperplane<Euclidean2D> hyperplane) {
 
         final Line    thisLine  = (Line) getHyperplane();
@@ -189,9 +167,13 @@ public class SubLine extends AbstractSubHyperplane<Euclidean2D, Euclidean1D> {
         if (crossing == null) {
             // the lines are parallel
             final double global = otherLine.getOffset(thisLine);
-            return (global < -1.0e-10) ?
-                   new SplitSubHyperplane<Euclidean2D>(null, this) :
-                   new SplitSubHyperplane<Euclidean2D>(this, null);
+            if (global < -tolerance) {
+                return new SplitSubHyperplane<Euclidean2D>(null, this);
+            } else if (global > tolerance) {
+                return new SplitSubHyperplane<Euclidean2D>(this, null);
+            } else {
+                return new SplitSubHyperplane<Euclidean2D>(null, null);
+            }
         }
 
         // the lines do intersect
@@ -211,7 +193,6 @@ public class SubLine extends AbstractSubHyperplane<Euclidean2D, Euclidean1D> {
                                                new BSPTree<Euclidean1D>(Boolean.FALSE) :
                                                new BSPTree<Euclidean1D>(subMinus, new BSPTree<Euclidean1D>(Boolean.FALSE),
                                                                         splitTree.getMinus(), null);
-
         return new SplitSubHyperplane<Euclidean2D>(new SubLine(thisLine.copySelf(), new IntervalsSet(plusTree, tolerance)),
                                                    new SubLine(thisLine.copySelf(), new IntervalsSet(minusTree, tolerance)));
 

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractRegion.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractRegion.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractRegion.java
index f75c0b3..1df1fcf 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractRegion.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractRegion.java
@@ -221,7 +221,8 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
         final ArrayList<SubHyperplane<S>> minusList = new ArrayList<SubHyperplane<S>>();
         while (iterator.hasNext()) {
             final SubHyperplane<S> other = iterator.next();
-            switch (other.side(inserted)) {
+            final SubHyperplane.SplitSubHyperplane<S> split = other.split(inserted);
+            switch (split.getSide()) {
             case PLUS:
                 plusList.add(other);
                 break;
@@ -229,7 +230,6 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
                 minusList.add(other);
                 break;
             case BOTH:
-                final SubHyperplane.SplitSubHyperplane<S> split = other.split(inserted);
                 plusList.add(split.getPlus());
                 minusList.add(split.getMinus());
                 break;
@@ -426,16 +426,6 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
 
     /** {@inheritDoc} */
     @Override
-    public Side side(final Hyperplane<S> hyperplane) {
-        final InsideFinder<S> finder = new InsideFinder<S>(this);
-        finder.recurseSides(tree, hyperplane.wholeHyperplane());
-        return finder.plusFound() ?
-              (finder.minusFound() ? Side.BOTH  : Side.PLUS) :
-              (finder.minusFound() ? Side.MINUS : Side.HYPER);
-    }
-
-    /** {@inheritDoc} */
-    @Override
     public SubHyperplane<S> intersection(final SubHyperplane<S> sub) {
         return recurseIntersection(tree, sub);
     }
@@ -453,23 +443,28 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
         }
 
         final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
-        switch (sub.side(hyperplane)) {
-        case PLUS :
-            return recurseIntersection(node.getPlus(), sub);
-        case MINUS :
-            return recurseIntersection(node.getMinus(), sub);
-        case BOTH :
-            final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
-            final SubHyperplane<S> plus  = recurseIntersection(node.getPlus(),  split.getPlus());
-            final SubHyperplane<S> minus = recurseIntersection(node.getMinus(), split.getMinus());
-            if (plus == null) {
-                return minus;
-            } else if (minus == null) {
-                return plus;
+        final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
+        if (split.getPlus() != null) {
+            if (split.getMinus() != null) {
+                // both sides
+                final SubHyperplane<S> plus  = recurseIntersection(node.getPlus(),  split.getPlus());
+                final SubHyperplane<S> minus = recurseIntersection(node.getMinus(), split.getMinus());
+                if (plus == null) {
+                    return minus;
+                } else if (minus == null) {
+                    return plus;
+                } else {
+                    return plus.reunite(minus);
+                }
             } else {
-                return plus.reunite(minus);
+                // only on plus side
+                return recurseIntersection(node.getPlus(), sub);
             }
-        default :
+        } else if (split.getMinus() != null) {
+            // only on minus side
+            return recurseIntersection(node.getMinus(), sub);
+        } else {
+            // on hyperplane
             return recurseIntersection(node.getPlus(),
                                        recurseIntersection(node.getMinus(), sub));
         }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractSubHyperplane.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractSubHyperplane.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractSubHyperplane.java
index f75998c..76c925c 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractSubHyperplane.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/AbstractSubHyperplane.java
@@ -180,10 +180,6 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
 
     /** {@inheritDoc} */
     @Override
-    public abstract Side side(Hyperplane<S> hyper);
-
-    /** {@inheritDoc} */
-    @Override
     public abstract SplitSubHyperplane<S> split(Hyperplane<S> hyper);
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/BSPTree.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/BSPTree.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/BSPTree.java
index 3be5b08..5a4f18e 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/BSPTree.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/BSPTree.java
@@ -558,11 +558,12 @@ public class BSPTree<S extends Space> {
 
         final Hyperplane<S> cHyperplane = cut.getHyperplane();
         final Hyperplane<S> sHyperplane = sub.getHyperplane();
-        switch (sub.side(cHyperplane)) {
+        final SubHyperplane.SplitSubHyperplane<S> subParts = sub.split(cHyperplane);
+        switch (subParts.getSide()) {
         case PLUS :
         { // the partitioning sub-hyperplane is entirely in the plus sub-tree
             final BSPTree<S> split = plus.split(sub);
-            if (cut.side(sHyperplane) == Side.PLUS) {
+            if (cut.split(sHyperplane).getSide() == Side.PLUS) {
                 split.plus =
                     new BSPTree<S>(cut.copySelf(), split.plus, minus.copySelf(), attribute);
                 split.plus.condense();
@@ -578,7 +579,7 @@ public class BSPTree<S extends Space> {
         case MINUS :
         { // the partitioning sub-hyperplane is entirely in the minus sub-tree
             final BSPTree<S> split = minus.split(sub);
-            if (cut.side(sHyperplane) == Side.PLUS) {
+            if (cut.split(sHyperplane).getSide() == Side.PLUS) {
                 split.plus =
                     new BSPTree<S>(cut.copySelf(), plus.copySelf(), split.plus, attribute);
                 split.plus.condense();
@@ -594,7 +595,6 @@ public class BSPTree<S extends Space> {
         case BOTH :
         {
             final SubHyperplane.SplitSubHyperplane<S> cutParts = cut.split(sHyperplane);
-            final SubHyperplane.SplitSubHyperplane<S> subParts = sub.split(cHyperplane);
             final BSPTree<S> split =
                 new BSPTree<S>(sub, plus.split(subParts.getPlus()), minus.split(subParts.getMinus()),
                                null);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/Characterization.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/Characterization.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/Characterization.java
index e1caf17..fb5256d 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/Characterization.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/Characterization.java
@@ -86,7 +86,8 @@ class Characterization<S extends Space> {
             }
         } else {
             final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
-            switch (sub.side(hyperplane)) {
+            final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
+            switch (split.getSide()) {
             case PLUS:
                 characterize(node.getPlus(),  sub, splitters);
                 break;
@@ -94,7 +95,6 @@ class Characterization<S extends Space> {
                 characterize(node.getMinus(), sub, splitters);
                 break;
             case BOTH:
-                final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
                 splitters.add(node);
                 characterize(node.getPlus(),  split.getPlus(),  splitters);
                 characterize(node.getMinus(), split.getMinus(), splitters);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/InsideFinder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/InsideFinder.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/InsideFinder.java
index 14bd142..da72e6d 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/InsideFinder.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/InsideFinder.java
@@ -69,10 +69,11 @@ class InsideFinder<S extends Space> {
         }
 
         final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
-        switch (sub.side(hyperplane)) {
+        final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
+        switch (split.getSide()) {
         case PLUS :
             // the sub-hyperplane is entirely in the plus sub-tree
-            if (node.getCut().side(sub.getHyperplane()) == Side.PLUS) {
+            if (node.getCut().split(sub.getHyperplane()).getSide() == Side.PLUS) {
                 if (!region.isEmpty(node.getMinus())) {
                     plusFound  = true;
                 }
@@ -87,7 +88,7 @@ class InsideFinder<S extends Space> {
             break;
         case MINUS :
             // the sub-hyperplane is entirely in the minus sub-tree
-            if (node.getCut().side(sub.getHyperplane()) == Side.PLUS) {
+            if (node.getCut().split(sub.getHyperplane()).getSide() == Side.PLUS) {
                 if (!region.isEmpty(node.getPlus())) {
                     plusFound  = true;
                 }
@@ -102,7 +103,6 @@ class InsideFinder<S extends Space> {
             break;
         case BOTH :
             // the sub-hyperplane extends in both sub-trees
-            final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
 
             // explore first the plus sub-tree
             recurseSides(node.getPlus(), split.getPlus());

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/Region.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/Region.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/Region.java
index 80c80b8..404d15d 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/Region.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/Region.java
@@ -197,16 +197,6 @@ public interface Region<S extends Space> {
      */
     Point<S> getBarycenter();
 
-    /** Compute the relative position of the instance with respect to an
-     * hyperplane.
-     * @param hyperplane reference hyperplane
-     * @return one of {@link Side#PLUS Side.PLUS}, {@link Side#MINUS
-     * Side.MINUS}, {@link Side#BOTH Side.BOTH} or {@link Side#HYPER
-     * Side.HYPER} (the latter result can occur only if the tree
-     * contains only one cut hyperplane)
-     */
-    Side side(final Hyperplane<S> hyperplane);
-
     /** Get the parts of a sub-hyperplane that are contained in the region.
      * <p>The parts of the sub-hyperplane that belong to the boundary are
      * <em>not</em> included in the resulting parts.</p>

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/RegionFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/RegionFactory.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/RegionFactory.java
index 9e32c99..bcae157 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/RegionFactory.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/RegionFactory.java
@@ -19,10 +19,13 @@ package org.apache.commons.math4.geometry.partitioning;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.commons.math4.exception.MathIllegalArgumentException;
+import org.apache.commons.math4.exception.util.LocalizedFormats;
 import org.apache.commons.math4.geometry.Point;
 import org.apache.commons.math4.geometry.Space;
 import org.apache.commons.math4.geometry.partitioning.BSPTree.VanishingCutHandler;
 import org.apache.commons.math4.geometry.partitioning.Region.Location;
+import org.apache.commons.math4.geometry.partitioning.SubHyperplane.SplitSubHyperplane;
 
 /** This class is a factory for {@link Region}.
 
@@ -63,6 +66,32 @@ public class RegionFactory<S extends Space> {
                 node.getPlus().setAttribute(Boolean.FALSE);
                 node = node.getMinus();
                 node.setAttribute(Boolean.TRUE);
+            } else {
+                // the hyperplane could not be inserted in the current leaf node
+                // either it is completely outside (which means the input hyperplanes
+                // are wrong), or it is parallel to a previous hyperplane
+                SubHyperplane<S> s = hyperplane.wholeHyperplane();
+                for (BSPTree<S> tree = node; tree.getParent() != null && s != null; tree = tree.getParent()) {
+                    final Hyperplane<S>         other = tree.getParent().getCut().getHyperplane();
+                    final SplitSubHyperplane<S> split = s.split(other);
+                    switch (split.getSide()) {
+                        case HYPER :
+                            // the hyperplane is parallel to a previous hyperplane
+                            if (!hyperplane.sameOrientationAs(other)) {
+                                // this hyperplane is opposite to the other one,
+                                // the region is thinner than the tolerance, we consider it empty
+                                return getComplement(hyperplanes[0].wholeSpace());
+                            }
+                            // the hyperplane is an extension of an already known hyperplane, we just ignore it
+                            break;
+                        case PLUS :
+                        // the hyperplane is outside of the current convex zone,
+                        // the input hyperplanes are inconsistent
+                        throw new MathIllegalArgumentException(LocalizedFormats.NOT_CONVEX_HYPERPLANES);
+                        default :
+                            s = split.getMinus();
+                    }
+                }
             }
         }
 

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/partitioning/SubHyperplane.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/partitioning/SubHyperplane.java b/src/main/java/org/apache/commons/math4/geometry/partitioning/SubHyperplane.java
index 33afd20..03a766e 100644
--- a/src/main/java/org/apache/commons/math4/geometry/partitioning/SubHyperplane.java
+++ b/src/main/java/org/apache/commons/math4/geometry/partitioning/SubHyperplane.java
@@ -66,14 +66,6 @@ public interface SubHyperplane<S extends Space> {
      */
     double getSize();
 
-    /** Compute the relative position of the instance with respect
-     * to an hyperplane.
-     * @param hyperplane hyperplane to check instance against
-     * @return one of {@link Side#PLUS}, {@link Side#MINUS}, {@link Side#BOTH},
-     * {@link Side#HYPER}
-     */
-    Side side(Hyperplane<S> hyperplane);
-
     /** Split the instance in two parts by an hyperplane.
      * @param hyperplane splitting hyperplane
      * @return an object containing both the part of the instance
@@ -126,6 +118,28 @@ public interface SubHyperplane<S extends Space> {
             return minus;
         }
 
+        /** Get the side of the split sub-hyperplane with respect to its splitter.
+         * @return {@link Side#PLUS} if only {@link #getPlus()} is neither null nor empty,
+         * {@link Side#MINUS} if only {@link #getMinus()} is neither null nor empty,
+         * {@link Side#BOTH} if both {@link #getPlus()} and {@link #getMinus()}
+         * are neither null nor empty or {@link Side#HYPER} if both {@link #getPlus()} and
+         * {@link #getMinus()} are either null or empty
+         * @since 3.6
+         */
+        public Side getSide() {
+            if (plus != null && !plus.isEmpty()) {
+                if (minus != null && !minus.isEmpty()) {
+                    return Side.BOTH;
+                } else {
+                    return Side.PLUS;
+                }
+            } else if (minus != null && !minus.isEmpty()) {
+                return Side.MINUS;
+            } else {
+                return Side.HYPER;
+            }
+        }
+
     }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSet.java b/src/main/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSet.java
index bd195c0..c5f772b 100644
--- a/src/main/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSet.java
+++ b/src/main/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSet.java
@@ -709,40 +709,11 @@ public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> implements Itera
      * @param arc arc to check instance against
      * @return one of {@link Side#PLUS}, {@link Side#MINUS}, {@link Side#BOTH}
      * or {@link Side#HYPER}
+     * @deprecated as of 3.6, replaced with {@link #split(Arc)}.{@link Split#getSide()}
      */
+    @Deprecated
     public Side side(final Arc arc) {
-
-        final double reference = FastMath.PI + arc.getInf();
-        final double arcLength = arc.getSup() - arc.getInf();
-
-        boolean inMinus = false;
-        boolean inPlus  = false;
-        for (final double[] a : this) {
-            final double syncedStart = MathUtils.normalizeAngle(a[0], reference) - arc.getInf();
-            final double arcOffset   = a[0] - syncedStart;
-            final double syncedEnd   = a[1] - arcOffset;
-            if (syncedStart <= arcLength - getTolerance() || syncedEnd >= MathUtils.TWO_PI + getTolerance()) {
-                inMinus = true;
-            }
-            if (syncedEnd >= arcLength + getTolerance()) {
-                inPlus = true;
-            }
-        }
-
-        if (inMinus) {
-            if (inPlus) {
-                return Side.BOTH;
-            } else {
-                return Side.MINUS;
-            }
-        } else {
-            if (inPlus) {
-                return Side.PLUS;
-            } else {
-                return Side.HYPER;
-            }
-        }
-
+        return split(arc).getSide();
     }
 
     /** Split the instance in two parts by an arc.
@@ -941,6 +912,28 @@ public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> implements Itera
             return minus;
         }
 
+        /** Get the side of the split arc with respect to its splitter.
+         * @return {@link Side#PLUS} if only {@link #getPlus()} returns non-null,
+         * {@link Side#MINUS} if only {@link #getMinus()} returns non-null,
+         * {@link Side#BOTH} if both {@link #getPlus()} and {@link #getMinus()}
+         * return non-null or {@link Side#HYPER} if both {@link #getPlus()} and
+         * {@link #getMinus()} return null
+         * @since 3.6
+         */
+        public Side getSide() {
+            if (plus != null) {
+                if (minus != null) {
+                    return Side.BOTH;
+                } else {
+                    return Side.PLUS;
+                }
+            } else if (minus != null) {
+                return Side.MINUS;
+            } else {
+                return Side.HYPER;
+            }
+        }
+
     }
 
     /** Specialized exception for inconsistent BSP tree state inconsistency.

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/spherical/oned/SubLimitAngle.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/spherical/oned/SubLimitAngle.java b/src/main/java/org/apache/commons/math4/geometry/spherical/oned/SubLimitAngle.java
index e90ad8b..31f79fd 100644
--- a/src/main/java/org/apache/commons/math4/geometry/spherical/oned/SubLimitAngle.java
+++ b/src/main/java/org/apache/commons/math4/geometry/spherical/oned/SubLimitAngle.java
@@ -19,7 +19,6 @@ package org.apache.commons.math4.geometry.spherical.oned;
 import org.apache.commons.math4.geometry.partitioning.AbstractSubHyperplane;
 import org.apache.commons.math4.geometry.partitioning.Hyperplane;
 import org.apache.commons.math4.geometry.partitioning.Region;
-import org.apache.commons.math4.geometry.partitioning.Side;
 
 /** This class represents sub-hyperplane for {@link LimitAngle}.
  * <p>Instances of this class are guaranteed to be immutable.</p>
@@ -57,13 +56,6 @@ public class SubLimitAngle extends AbstractSubHyperplane<Sphere1D, Sphere1D> {
 
     /** {@inheritDoc} */
     @Override
-    public Side side(final Hyperplane<Sphere1D> hyperplane) {
-        final double global = hyperplane.getOffset(((LimitAngle) getHyperplane()).getLocation());
-        return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER);
-    }
-
-    /** {@inheritDoc} */
-    @Override
     public SplitSubHyperplane<Sphere1D> split(final Hyperplane<Sphere1D> hyperplane) {
         final double global = hyperplane.getOffset(((LimitAngle) getHyperplane()).getLocation());
         return (global < -1.0e-10) ?

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/java/org/apache/commons/math4/geometry/spherical/twod/SubCircle.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/geometry/spherical/twod/SubCircle.java b/src/main/java/org/apache/commons/math4/geometry/spherical/twod/SubCircle.java
index afa5005..837c953 100644
--- a/src/main/java/org/apache/commons/math4/geometry/spherical/twod/SubCircle.java
+++ b/src/main/java/org/apache/commons/math4/geometry/spherical/twod/SubCircle.java
@@ -20,7 +20,6 @@ import org.apache.commons.math4.geometry.euclidean.threed.Vector3D;
 import org.apache.commons.math4.geometry.partitioning.AbstractSubHyperplane;
 import org.apache.commons.math4.geometry.partitioning.Hyperplane;
 import org.apache.commons.math4.geometry.partitioning.Region;
-import org.apache.commons.math4.geometry.partitioning.Side;
 import org.apache.commons.math4.geometry.spherical.oned.Arc;
 import org.apache.commons.math4.geometry.spherical.oned.ArcsSet;
 import org.apache.commons.math4.geometry.spherical.oned.Sphere1D;
@@ -49,36 +48,15 @@ public class SubCircle extends AbstractSubHyperplane<Sphere2D, Sphere1D> {
 
     /** {@inheritDoc} */
     @Override
-    public Side side(final Hyperplane<Sphere2D> hyperplane) {
-
-        final Circle thisCircle  = (Circle) getHyperplane();
-        final Circle otherCircle = (Circle) hyperplane;
-        final double angle = Vector3D.angle(thisCircle.getPole(), otherCircle.getPole());
-
-        if (angle < thisCircle.getTolerance() || angle > FastMath.PI - thisCircle.getTolerance()) {
-            // the two circles are aligned or opposite
-            return Side.HYPER;
-        } else {
-            // the two circles intersect each other
-            return ((ArcsSet) getRemainingRegion()).side(thisCircle.getInsideArc(otherCircle));
-        }
-
-    }
-
-    /** {@inheritDoc} */
-    @Override
     public SplitSubHyperplane<Sphere2D> split(final Hyperplane<Sphere2D> hyperplane) {
 
         final Circle thisCircle   = (Circle) getHyperplane();
         final Circle otherCircle  = (Circle) hyperplane;
         final double angle = Vector3D.angle(thisCircle.getPole(), otherCircle.getPole());
 
-        if (angle < thisCircle.getTolerance()) {
-            // the two circles are aligned
-            return new SplitSubHyperplane<Sphere2D>(null, this);
-        } else if (angle > FastMath.PI - thisCircle.getTolerance()) {
-            // the two circles are opposite
-            return new SplitSubHyperplane<Sphere2D>(this, null);
+        if (angle < thisCircle.getTolerance() || angle > FastMath.PI - thisCircle.getTolerance()) {
+            // the two circles are aligned or opposite
+            return new SplitSubHyperplane<Sphere2D>(null, null);
         } else {
             // the two circles intersect each other
             final Arc    arc          = thisCircle.getInsideArc(otherCircle);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/main/resources/assets/org/apache/commons/math4/exception/util/LocalizedFormats_fr.properties
----------------------------------------------------------------------
diff --git a/src/main/resources/assets/org/apache/commons/math4/exception/util/LocalizedFormats_fr.properties b/src/main/resources/assets/org/apache/commons/math4/exception/util/LocalizedFormats_fr.properties
index eba92a0..cbbec08 100644
--- a/src/main/resources/assets/org/apache/commons/math4/exception/util/LocalizedFormats_fr.properties
+++ b/src/main/resources/assets/org/apache/commons/math4/exception/util/LocalizedFormats_fr.properties
@@ -167,6 +167,7 @@ NORMALIZE_INFINITE = impossible de normaliser vers une valeur infinie
 NORMALIZE_NAN = impossible de normaliser vers NaN
 NOT_ADDITION_COMPATIBLE_MATRICES = les dimensions {0}x{1} et {2}x{3} sont incompatibles pour l''addition matricielle
 NOT_CONVEX = les points ne constituent pas une enveloppe convexe
+NOT_CONVEX_HYPERPLANES = les hyperplans ne d\u00e9finissent pas une r\u00e9gion convexe
 NOT_DECREASING_NUMBER_OF_POINTS = les points {0} et {1} ne sont pas d\u00e9croissants ({2} < {3})
 NOT_DECREASING_SEQUENCE = les points {3} et {2} ne sont pas d\u00e9croissants ({1} < {0})
 NOT_ENOUGH_DATA_FOR_NUMBER_OF_PREDICTORS = pas assez de donn\u00e9es ({0} lignes) pour {1} pr\u00e9dicteurs

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/test/java/org/apache/commons/math4/exception/util/LocalizedFormatsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/exception/util/LocalizedFormatsTest.java b/src/test/java/org/apache/commons/math4/exception/util/LocalizedFormatsTest.java
index 6912f5f..4d1dcbf 100644
--- a/src/test/java/org/apache/commons/math4/exception/util/LocalizedFormatsTest.java
+++ b/src/test/java/org/apache/commons/math4/exception/util/LocalizedFormatsTest.java
@@ -29,7 +29,7 @@ public class LocalizedFormatsTest {
 
     @Test
     public void testMessageNumber() {
-        Assert.assertEquals(326, LocalizedFormats.values().length);
+        Assert.assertEquals(327, LocalizedFormats.values().length);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java b/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java
index a444273..34f10c2 100644
--- a/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java
+++ b/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java
@@ -19,6 +19,7 @@ package org.apache.commons.math4.geometry.euclidean.twod;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.math4.exception.MathIllegalArgumentException;
 import org.apache.commons.math4.geometry.euclidean.oned.Interval;
 import org.apache.commons.math4.geometry.euclidean.oned.IntervalsSet;
 import org.apache.commons.math4.geometry.euclidean.oned.Vector1D;
@@ -1153,12 +1154,19 @@ public class PolygonsSetTest {
             new Line(pD, pA, 1.0 / 16)
         };
         Region<Euclidean2D> degeneratedPolygon = factory.buildConvex(h2);
-        Assert.assertEquals(1.0 / 64.0, degeneratedPolygon.getSize(), 1.0e-10);
-        Assert.assertTrue(Double.isInfinite(new RegionFactory<Euclidean2D>().getComplement(degeneratedPolygon).getSize()));
-        Assert.assertEquals(2 * (1.0 + 1.0 / 64.0), degeneratedPolygon.getBoundarySize(), 1.0e-10);
+        Assert.assertEquals(0.0, degeneratedPolygon.getSize(), 1.0e-10);
+        Assert.assertTrue(degeneratedPolygon.isEmpty());
 
     }
 
+    @SuppressWarnings("unchecked")
+    @Test(expected=MathIllegalArgumentException.class)
+    public void testInconsistentHyperplanes() {
+        double tolerance = 1.0e-10;
+        new RegionFactory<Euclidean2D>().buildConvex(new Line(new Vector2D(0, 0), new Vector2D(0, 1), tolerance),
+                                                     new Line(new Vector2D(1, 1), new Vector2D(1, 0), tolerance));
+    }
+
     @Test
     public void testBoundarySimplification() {
 

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/test/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSetTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSetTest.java b/src/test/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSetTest.java
index 1eaa73c..e57286b 100644
--- a/src/test/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSetTest.java
+++ b/src/test/java/org/apache/commons/math4/geometry/spherical/oned/ArcsSetTest.java
@@ -389,27 +389,27 @@ public class ArcsSetTest {
         ArcsSet set = (ArcsSet) new RegionFactory<Sphere1D>().difference(new ArcsSet(1.0, 6.0, 1.0e-10),
                                                                          new ArcsSet(3.0, 5.0, 1.0e-10));
         for (int k = -2; k < 3; ++k) {
-            Assert.assertEquals(Side.MINUS, set.side(new Arc(0.5 + k * MathUtils.TWO_PI,
-                                                             6.1 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
-            Assert.assertEquals(Side.PLUS,  set.side(new Arc(0.5 + k * MathUtils.TWO_PI,
-                                                             0.8 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
-            Assert.assertEquals(Side.PLUS,  set.side(new Arc(6.2 + k * MathUtils.TWO_PI,
-                                                             6.3 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
-            Assert.assertEquals(Side.PLUS,  set.side(new Arc(3.5 + k * MathUtils.TWO_PI,
-                                                             4.5 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
-            Assert.assertEquals(Side.BOTH,  set.side(new Arc(2.9 + k * MathUtils.TWO_PI,
-                                                             4.5 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
-            Assert.assertEquals(Side.BOTH,  set.side(new Arc(0.5 + k * MathUtils.TWO_PI,
-                                                             1.2 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
-            Assert.assertEquals(Side.BOTH,  set.side(new Arc(0.5 + k * MathUtils.TWO_PI,
-                                                             5.9 + k * MathUtils.TWO_PI,
-                                                             set.getTolerance())));
+            Assert.assertEquals(Side.MINUS, set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
+                                                              6.1 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
+            Assert.assertEquals(Side.PLUS,  set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
+                                                              0.8 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
+            Assert.assertEquals(Side.PLUS,  set.split(new Arc(6.2 + k * MathUtils.TWO_PI,
+                                                              6.3 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
+            Assert.assertEquals(Side.PLUS,  set.split(new Arc(3.5 + k * MathUtils.TWO_PI,
+                                                              4.5 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
+            Assert.assertEquals(Side.BOTH,  set.split(new Arc(2.9 + k * MathUtils.TWO_PI,
+                                                              4.5 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
+            Assert.assertEquals(Side.BOTH,  set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
+                                                              1.2 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
+            Assert.assertEquals(Side.BOTH,  set.split(new Arc(0.5 + k * MathUtils.TWO_PI,
+                                                              5.9 + k * MathUtils.TWO_PI,
+                                                              set.getTolerance())).getSide());
         }
     }
 
@@ -419,10 +419,10 @@ public class ArcsSetTest {
         ArcsSet s35 = new ArcsSet(3.0, 5.0, 1.0e-10);
         ArcsSet s16 = new ArcsSet(1.0, 6.0, 1.0e-10);
 
-        Assert.assertEquals(Side.BOTH,  s16.side(new Arc(3.0, 5.0, 1.0e-10)));
-        Assert.assertEquals(Side.BOTH,  s16.side(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10)));
-        Assert.assertEquals(Side.MINUS, s35.side(new Arc(1.0, 6.0, 1.0e-10)));
-        Assert.assertEquals(Side.PLUS,  s35.side(new Arc(6.0, 1.0 + MathUtils.TWO_PI, 1.0e-10)));
+        Assert.assertEquals(Side.BOTH,  s16.split(new Arc(3.0, 5.0, 1.0e-10)).getSide());
+        Assert.assertEquals(Side.BOTH,  s16.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
+        Assert.assertEquals(Side.MINUS, s35.split(new Arc(1.0, 6.0, 1.0e-10)).getSide());
+        Assert.assertEquals(Side.PLUS,  s35.split(new Arc(6.0, 1.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
 
     }
 
@@ -431,17 +431,17 @@ public class ArcsSetTest {
         ArcsSet s35 = new ArcsSet(3.0, 5.0, 1.0e-10);
         ArcsSet s46 = new ArcsSet(4.0, 6.0, 1.0e-10);
 
-        Assert.assertEquals(Side.BOTH,  s46.side(new Arc(3.0, 5.0, 1.0e-10)));
-        Assert.assertEquals(Side.BOTH,  s46.side(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10)));
-        Assert.assertEquals(Side.BOTH, s35.side(new Arc(4.0, 6.0, 1.0e-10)));
-        Assert.assertEquals(Side.BOTH,  s35.side(new Arc(6.0, 4.0 + MathUtils.TWO_PI, 1.0e-10)));
+        Assert.assertEquals(Side.BOTH,  s46.split(new Arc(3.0, 5.0, 1.0e-10)).getSide());
+        Assert.assertEquals(Side.BOTH,  s46.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
+        Assert.assertEquals(Side.BOTH, s35.split(new Arc(4.0, 6.0, 1.0e-10)).getSide());
+        Assert.assertEquals(Side.BOTH,  s35.split(new Arc(6.0, 4.0 + MathUtils.TWO_PI, 1.0e-10)).getSide());
     }
 
     @Test
     public void testSideHyper() {
         ArcsSet sub = (ArcsSet) new RegionFactory<Sphere1D>().getComplement(new ArcsSet(1.0e-10));
         Assert.assertTrue(sub.isEmpty());
-        Assert.assertEquals(Side.HYPER,  sub.side(new Arc(2.0, 3.0, 1.0e-10)));
+        Assert.assertEquals(Side.HYPER,  sub.split(new Arc(2.0, 3.0, 1.0e-10)).getSide());
     }
 
     @Test
@@ -583,4 +583,16 @@ public class ArcsSetTest {
         Assert.assertNull(split.getMinus());
     }
 
+    @Test
+    public void testSideSplitConsistency() {
+        double  epsilon = 1.0e-6;
+        double  a       = 4.725;
+        ArcsSet set     = new ArcsSet(a, a + 0.5, epsilon);
+        Arc     arc     = new Arc(a + 0.5 * epsilon, a + 1, epsilon);
+        ArcsSet.Split split = set.split(arc);
+        Assert.assertNotNull(split.getMinus());
+        Assert.assertNull(split.getPlus());
+        Assert.assertEquals(Side.MINUS, set.split(arc).getSide());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SphericalPolygonsSetTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SphericalPolygonsSetTest.java b/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SphericalPolygonsSetTest.java
index e2359a3..e9fbe47 100644
--- a/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SphericalPolygonsSetTest.java
+++ b/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SphericalPolygonsSetTest.java
@@ -228,17 +228,23 @@ public class SphericalPolygonsSetTest {
         boolean zVFound = false;
         Vertex first = loops.get(0);
         int count = 0;
+        double sumPoleX = 0;
+        double sumPoleY = 0;
+        double sumPoleZ = 0;
         for (Vertex v = first; count == 0 || v != first; v = v.getOutgoing().getEnd()) {
             ++count;
             Edge e = v.getIncoming();
             Assert.assertTrue(v == e.getStart().getOutgoing().getEnd());
-            xPFound = xPFound || e.getCircle().getPole().distance(Vector3D.MINUS_I) < 1.0e-10;
-            yPFound = yPFound || e.getCircle().getPole().distance(Vector3D.MINUS_J) < 1.0e-10;
-            zPFound = zPFound || e.getCircle().getPole().distance(Vector3D.PLUS_K)  < 1.0e-10;
-            if (Vector3D.PLUS_K.distance(e.getCircle().getPole()) < 1.0e-10) {
-                Assert.assertEquals(1.5 * FastMath.PI, e.getLength(), 1.0e-10);
+            if (e.getCircle().getPole().distance(Vector3D.MINUS_I) < 1.0e-10) {
+                xPFound = true;
+                sumPoleX += e.getLength();
+            } else if (e.getCircle().getPole().distance(Vector3D.MINUS_J) < 1.0e-10) {
+                yPFound = true;
+                sumPoleY += e.getLength();
             } else {
-                Assert.assertEquals(0.5 * FastMath.PI, e.getLength(), 1.0e-10);
+                Assert.assertEquals(0.0, e.getCircle().getPole().distance(Vector3D.PLUS_K), 1.0e-10);
+                zPFound = true;
+                sumPoleZ += e.getLength();
             }
             xVFound = xVFound || v.getLocation().getVector().distance(Vector3D.PLUS_I) < 1.0e-10;
             yVFound = yVFound || v.getLocation().getVector().distance(Vector3D.PLUS_J) < 1.0e-10;
@@ -250,7 +256,9 @@ public class SphericalPolygonsSetTest {
         Assert.assertTrue(xVFound);
         Assert.assertTrue(yVFound);
         Assert.assertTrue(zVFound);
-        Assert.assertEquals(3, count);
+        Assert.assertEquals(0.5 * FastMath.PI, sumPoleX, 1.0e-10);
+        Assert.assertEquals(0.5 * FastMath.PI, sumPoleY, 1.0e-10);
+        Assert.assertEquals(1.5 * FastMath.PI, sumPoleZ, 1.0e-10);
 
         Assert.assertEquals(1.5 * FastMath.PI, threeOctants.getSize(), 1.0e-10);
 

http://git-wip-us.apache.org/repos/asf/commons-math/blob/2091cfba/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SubCircleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SubCircleTest.java b/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SubCircleTest.java
index 743cdbc..891f620 100644
--- a/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SubCircleTest.java
+++ b/src/test/java/org/apache/commons/math4/geometry/spherical/twod/SubCircleTest.java
@@ -47,19 +47,19 @@ public class SubCircleTest {
         Circle xzPlane = new Circle(Vector3D.PLUS_J, 1.0e-10);
 
         SubCircle sc1 = create(Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_J, 1.0e-10, 1.0, 3.0, 5.0, 6.0);
-        Assert.assertEquals(Side.BOTH, sc1.side(xzPlane));
+        Assert.assertEquals(Side.BOTH, sc1.split(xzPlane).getSide());
 
         SubCircle sc2 = create(Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_J, 1.0e-10, 1.0, 3.0);
-        Assert.assertEquals(Side.MINUS, sc2.side(xzPlane));
+        Assert.assertEquals(Side.MINUS, sc2.split(xzPlane).getSide());
 
         SubCircle sc3 = create(Vector3D.PLUS_K, Vector3D.PLUS_I, Vector3D.PLUS_J, 1.0e-10, 5.0, 6.0);
-        Assert.assertEquals(Side.PLUS, sc3.side(xzPlane));
+        Assert.assertEquals(Side.PLUS, sc3.split(xzPlane).getSide());
 
         SubCircle sc4 = create(Vector3D.PLUS_J, Vector3D.PLUS_K, Vector3D.PLUS_I, 1.0e-10, 5.0, 6.0);
-        Assert.assertEquals(Side.HYPER, sc4.side(xzPlane));
+        Assert.assertEquals(Side.HYPER, sc4.split(xzPlane).getSide());
 
         SubCircle sc5 = create(Vector3D.MINUS_J, Vector3D.PLUS_I, Vector3D.PLUS_K, 1.0e-10, 5.0, 6.0);
-        Assert.assertEquals(Side.HYPER, sc5.side(xzPlane));
+        Assert.assertEquals(Side.HYPER, sc5.split(xzPlane).getSide());
 
     }
 
@@ -97,17 +97,34 @@ public class SubCircleTest {
 
         SubCircle sc4 = create(Vector3D.PLUS_J, Vector3D.PLUS_K, Vector3D.PLUS_I, 1.0e-10, 5.0, 6.0);
         SplitSubHyperplane<Sphere2D> split4 = sc4.split(xzPlane);
-        Assert.assertEquals(Side.HYPER, sc4.side(xzPlane));
+        Assert.assertEquals(Side.HYPER, sc4.split(xzPlane).getSide());
         Assert.assertNull(split4.getPlus());
-        Assert.assertTrue(split4.getMinus() == sc4);
+        Assert.assertNull(split4.getMinus());
 
         SubCircle sc5 = create(Vector3D.MINUS_J, Vector3D.PLUS_I, Vector3D.PLUS_K, 1.0e-10, 5.0, 6.0);
         SplitSubHyperplane<Sphere2D> split5 = sc5.split(xzPlane);
-        Assert.assertTrue(split5.getPlus() == sc5);
+        Assert.assertEquals(Side.HYPER, sc5.split(xzPlane).getSide());
+        Assert.assertNull(split5.getPlus());
         Assert.assertNull(split5.getMinus());
 
     }
 
+    @Test
+    public void testSideSplitConsistency() {
+
+        double tolerance = 1.0e-6;
+        Circle hyperplane = new Circle(new Vector3D(9.738804529764676E-5, -0.6772824575010357, -0.7357230887208355),
+                                       tolerance);
+        SubCircle sub = new SubCircle(new Circle(new Vector3D(2.1793884139073498E-4, 0.9790647032675541, -0.20354915700704285),
+                                                 tolerance),
+                                      new ArcsSet(4.7121441684170700, 4.7125386635004760, tolerance));
+        SplitSubHyperplane<Sphere2D> split = sub.split(hyperplane);
+        Assert.assertNotNull(split.getMinus());
+        Assert.assertNull(split.getPlus());
+        Assert.assertEquals(Side.MINUS, sub.split(hyperplane).getSide());
+
+    }
+
     private SubCircle create(Vector3D pole, Vector3D x, Vector3D y,
                              double tolerance, double ... limits) {
         RegionFactory<Sphere1D> factory = new RegionFactory<Sphere1D>();