Fixed split/side inconsistencies in BSP trees.
JIRA: MATH-1266
This commit is contained in:
parent
5fccd09a81
commit
50c5eae1a6
|
@ -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>
|
||||
|
|
|
@ -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}"),
|
||||
|
|
|
@ -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
|
||||
|
@ -57,20 +56,17 @@ public class SubOrientedPoint extends AbstractSubHyperplane<Euclidean1D, Euclide
|
|||
return new SubOrientedPoint(hyperplane, remainingRegion);
|
||||
}
|
||||
|
||||
/** {@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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -169,27 +168,6 @@ public class SubLine extends AbstractSubHyperplane<Euclidean2D, Euclidean1D> {
|
|||
return new SubLine(hyperplane, remainingRegion);
|
||||
}
|
||||
|
||||
/** {@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) {
|
||||
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
@ -55,13 +54,6 @@ public class SubLimitAngle extends AbstractSubHyperplane<Sphere1D, Sphere1D> {
|
|||
return new SubLimitAngle(hyperplane, remainingRegion);
|
||||
}
|
||||
|
||||
/** {@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) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -47,24 +46,6 @@ public class SubCircle extends AbstractSubHyperplane<Sphere2D, Sphere1D> {
|
|||
return new SubCircle(hyperplane, remainingRegion);
|
||||
}
|
||||
|
||||
/** {@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) {
|
||||
|
@ -73,12 +54,9 @@ public class SubCircle extends AbstractSubHyperplane<Sphere2D, Sphere1D> {
|
|||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,7 +29,7 @@ public class LocalizedFormatsTest {
|
|||
|
||||
@Test
|
||||
public void testMessageNumber() {
|
||||
Assert.assertEquals(326, LocalizedFormats.values().length);
|
||||
Assert.assertEquals(327, LocalizedFormats.values().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>();
|
||||
|
|
Loading…
Reference in New Issue