Repository: commons-math Updated Branches: refs/heads/MATH_3_X 5fccd09a8 -> 50c5eae1a
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/50c5eae1 Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/50c5eae1 Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/50c5eae1 Branch: refs/heads/MATH_3_X Commit: 50c5eae1a6dd3d0b36ae862db2c3c8e2f564b098 Parents: 5fccd09 Author: Luc Maisonobe <l...@apache.org> Authored: Sun Sep 6 19:47:27 2015 +0200 Committer: Luc Maisonobe <l...@apache.org> Committed: Sun Sep 6 20:04:25 2015 +0200 ---------------------------------------------------------------------- src/changes/changes.xml | 3 + .../math3/exception/util/LocalizedFormats.java | 1 + .../euclidean/oned/SubOrientedPoint.java | 18 ++--- .../geometry/euclidean/threed/SubPlane.java | 52 +++----------- .../math3/geometry/euclidean/twod/SubLine.java | 33 ++------- .../geometry/partitioning/AbstractRegion.java | 40 ++++++----- .../partitioning/AbstractSubHyperplane.java | 5 +- .../math3/geometry/partitioning/BSPTree.java | 8 +-- .../geometry/partitioning/Characterization.java | 4 +- .../geometry/partitioning/InsideFinder.java | 8 +-- .../math3/geometry/partitioning/Region.java | 3 + .../geometry/partitioning/RegionFactory.java | 31 ++++++++- .../geometry/partitioning/SubHyperplane.java | 24 +++++++ .../math3/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, 243 insertions(+), 224 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/50c5eae1/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ede16f9..6f437b4 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces! </properties> <body> <release version="3.6" date="XXXX-XX-XX" description=""> + <action dev="luc" type="fix" issue="MATH-1266"> + Fixed split/side inconsistencies in BSP trees. + </action> <action dev="erans" type="add" issue="MATH-1265"> "NeuronSquareMesh2D" (package "o.a.c.m.ml.neuralnet.twod") implements "Iterable". </action> http://git-wip-us.apache.org/repos/asf/commons-math/blob/50c5eae1/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java b/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java index 8fe4dc9..7fc662f 100644 --- a/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java +++ b/src/main/java/org/apache/commons/math3/exception/util/LocalizedFormats.java @@ -182,6 +182,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/euclidean/oned/SubOrientedPoint.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/oned/SubOrientedPoint.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/oned/SubOrientedPoint.java index 697cfaf..a0288bb 100644 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/oned/SubOrientedPoint.java +++ b/src/main/java/org/apache/commons/math3/geometry/euclidean/oned/SubOrientedPoint.java @@ -19,7 +19,6 @@ package org.apache.commons.math3.geometry.euclidean.oned; import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; import org.apache.commons.math3.geometry.partitioning.Hyperplane; import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java index 64fe1ed..ce02a38 100644 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java +++ b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java @@ -20,13 +20,12 @@ import org.apache.commons.math3.geometry.Point; import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; -import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; +import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; import org.apache.commons.math3.geometry.partitioning.BSPTree; import org.apache.commons.math3.geometry.partitioning.Hyperplane; import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.geometry.partitioning.Side; import org.apache.commons.math3.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.math3.geometry.euclidean.twod.Line line2D = - new org.apache.commons.math3.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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/SubLine.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/SubLine.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/SubLine.java index d27b116..d930b76 100644 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/SubLine.java +++ b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/SubLine.java @@ -30,7 +30,6 @@ import org.apache.commons.math3.geometry.partitioning.BSPTree; import org.apache.commons.math3.geometry.partitioning.Hyperplane; import org.apache.commons.math3.geometry.partitioning.Region; import org.apache.commons.math3.geometry.partitioning.Region.Location; -import org.apache.commons.math3.geometry.partitioning.Side; import org.apache.commons.math3.geometry.partitioning.SubHyperplane; import org.apache.commons.math3.util.FastMath; @@ -171,27 +170,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(); @@ -202,9 +180,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 @@ -224,7 +206,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java index 6928331..c92637a 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java +++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java @@ -216,7 +216,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; @@ -224,7 +225,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; @@ -408,6 +408,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement protected abstract void computeGeometricalProperties(); /** {@inheritDoc} */ + @Deprecated public Side side(final Hyperplane<S> hyperplane) { final InsideFinder<S> finder = new InsideFinder<S>(this); finder.recurseSides(tree, hyperplane.wholeHyperplane()); @@ -434,23 +435,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractSubHyperplane.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractSubHyperplane.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractSubHyperplane.java index 3fd6b54..396b795 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractSubHyperplane.java +++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractSubHyperplane.java @@ -175,7 +175,10 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space> } /** {@inheritDoc} */ - public abstract Side side(Hyperplane<S> hyper); + @Deprecated + public Side side(Hyperplane<S> hyper) { + return split(hyper).getSide(); + } /** {@inheritDoc} */ public abstract SplitSubHyperplane<S> split(Hyperplane<S> hyper); http://git-wip-us.apache.org/repos/asf/commons-math/blob/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/BSPTree.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/BSPTree.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/BSPTree.java index 5395218..c74e443 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/BSPTree.java +++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/BSPTree.java @@ -574,11 +574,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(); @@ -594,7 +595,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(); @@ -610,7 +611,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/Characterization.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/Characterization.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/Characterization.java index 58efe0f..ca43be6 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/Characterization.java +++ b/src/main/java/org/apache/commons/math3/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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/InsideFinder.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/InsideFinder.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/InsideFinder.java index 2b0b405..82a6d9e 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/InsideFinder.java +++ b/src/main/java/org/apache/commons/math3/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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/Region.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/Region.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/Region.java index 3f4d5f5..f7bc3aa 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/Region.java +++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/Region.java @@ -204,7 +204,10 @@ public interface Region<S extends Space> { * 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) + * @deprecated as of 3.6, this method which was only intended for + * internal use is not used anymore */ + @Deprecated Side side(final Hyperplane<S> hyperplane); /** Get the parts of a sub-hyperplane that are contained in the region. http://git-wip-us.apache.org/repos/asf/commons-math/blob/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/RegionFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/RegionFactory.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/RegionFactory.java index 16d4472..0f46848 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/RegionFactory.java +++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/RegionFactory.java @@ -19,10 +19,13 @@ package org.apache.commons.math3.geometry.partitioning; import java.util.HashMap; import java.util.Map; +import org.apache.commons.math3.exception.MathIllegalArgumentException; +import org.apache.commons.math3.exception.util.LocalizedFormats; import org.apache.commons.math3.geometry.Point; import org.apache.commons.math3.geometry.Space; import org.apache.commons.math3.geometry.partitioning.BSPTree.VanishingCutHandler; import org.apache.commons.math3.geometry.partitioning.Region.Location; +import org.apache.commons.math3.geometry.partitioning.SubHyperplane.SplitSubHyperplane; /** This class is a factory for {@link Region}. @@ -45,7 +48,7 @@ public class RegionFactory<S extends Space> { * @param hyperplanes collection of bounding hyperplanes * @return a new convex region, or null if the collection is empty */ - public Region<S> buildConvex(final Hyperplane<S> ... hyperplanes) { + public Region<S> buildConvex(@SuppressWarnings("unchecked") final Hyperplane<S> ... hyperplanes) { if ((hyperplanes == null) || (hyperplanes.length == 0)) { return null; } @@ -62,6 +65,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/partitioning/SubHyperplane.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/SubHyperplane.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/SubHyperplane.java index 70c6043..9b6625b 100644 --- a/src/main/java/org/apache/commons/math3/geometry/partitioning/SubHyperplane.java +++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/SubHyperplane.java @@ -71,7 +71,9 @@ public interface SubHyperplane<S extends Space> { * @param hyperplane hyperplane to check instance against * @return one of {@link Side#PLUS}, {@link Side#MINUS}, {@link Side#BOTH}, * {@link Side#HYPER} + * @deprecated as of 3.6, replaced with {@link #split(Hyperplane)}.{@link SplitSubHyperplane#getSide()} */ + @Deprecated Side side(Hyperplane<S> hyperplane); /** Split the instance in two parts by an hyperplane. @@ -126,6 +128,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java index 5c03150..c0ca6c1 100644 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java +++ b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java @@ -705,40 +705,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. @@ -937,6 +908,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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java index 880a7e8..ebd3627 100644 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java +++ b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java @@ -19,7 +19,6 @@ package org.apache.commons.math3.geometry.spherical.oned; import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; import org.apache.commons.math3.geometry.partitioning.Hyperplane; import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.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/50c5eae1/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java b/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java index fa7fd9c..97164cc 100644 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java +++ b/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java @@ -20,7 +20,6 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; import org.apache.commons.math3.geometry.partitioning.Hyperplane; import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.geometry.partitioning.Side; import org.apache.commons.math3.geometry.spherical.oned.Arc; import org.apache.commons.math3.geometry.spherical.oned.ArcsSet; import org.apache.commons.math3.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/50c5eae1/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties ---------------------------------------------------------------------- diff --git a/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties b/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties index 610ffb8..8cf559b 100644 --- a/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties +++ b/src/main/resources/assets/org/apache/commons/math3/exception/util/LocalizedFormats_fr.properties @@ -168,6 +168,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/50c5eae1/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java b/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java index 791829f..3c2a447 100644 --- a/src/test/java/org/apache/commons/math3/exception/util/LocalizedFormatsTest.java +++ b/src/test/java/org/apache/commons/math3/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/50c5eae1/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java b/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java index a459484..526c076 100644 --- a/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java +++ b/src/test/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSetTest.java @@ -19,6 +19,7 @@ package org.apache.commons.math3.geometry.euclidean.twod; import java.util.ArrayList; import java.util.List; +import org.apache.commons.math3.exception.MathIllegalArgumentException; import org.apache.commons.math3.geometry.euclidean.oned.Interval; import org.apache.commons.math3.geometry.euclidean.oned.IntervalsSet; import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; @@ -1148,12 +1149,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/50c5eae1/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java b/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java index 5b9da17..5f330ee 100644 --- a/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java +++ b/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java @@ -383,27 +383,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()); } } @@ -413,10 +413,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()); } @@ -425,17 +425,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 @@ -577,4 +577,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/50c5eae1/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SphericalPolygonsSetTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SphericalPolygonsSetTest.java b/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SphericalPolygonsSetTest.java index 6fbbcdc..9efdd6c 100644 --- a/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SphericalPolygonsSetTest.java +++ b/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SphericalPolygonsSetTest.java @@ -221,17 +221,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; @@ -243,7 +249,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/50c5eae1/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SubCircleTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SubCircleTest.java b/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SubCircleTest.java index 5b1c25f..343f894 100644 --- a/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SubCircleTest.java +++ b/src/test/java/org/apache/commons/math3/geometry/spherical/twod/SubCircleTest.java @@ -44,19 +44,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()); } @@ -94,17 +94,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>();