Intermediate, partially working stuff on the 1-sphere.

Chord/SubChord are most probably not the appropriate classes. They are
too complex and should be replaced by something simpler and more
0-dimension, like OrientedPoint in Euclidean 1-D.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1554652 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2014-01-01 17:28:51 +00:00
parent ed73c356c7
commit 83444ebe71
7 changed files with 815 additions and 76 deletions

View File

@ -54,7 +54,7 @@ public class Arc {
public Arc(final double lower, final double upper) {
this.lower = lower;
if (Precision.equals(lower, upper, 0)) {
this.upper = 2 * FastMath.PI + lower;
this.upper = MathUtils.TWO_PI + lower;
} else {
this.upper = MathUtils.normalizeAngle(upper, lower + FastMath.PI);
}
@ -103,7 +103,7 @@ public class Arc {
} else if (normalizedPoint > lower + tolerance && normalizedPoint < upper - tolerance) {
return Location.INSIDE;
} else {
return Location.BOUNDARY;
return (getSize() >= MathUtils.TWO_PI - tolerance) ? Location.INSIDE : Location.BOUNDARY;
}
}

View File

@ -18,10 +18,12 @@ package org.apache.commons.math3.geometry.spherical.oned;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.commons.math3.geometry.partitioning.AbstractRegion;
import org.apache.commons.math3.geometry.partitioning.BSPTree;
import org.apache.commons.math3.geometry.partitioning.BSPTreeVisitor;
import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.util.MathUtils;
@ -144,7 +146,7 @@ public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> {
protected void computeGeometricalProperties() {
if (getTree(false).getCut() == null) {
setBarycenter(S1Point.NaN);
setSize(((Boolean) getTree(false).getAttribute()) ? 2 * FastMath.PI : 0);
setSize(((Boolean) getTree(false).getAttribute()) ? MathUtils.TWO_PI : 0);
} else {
double size = 0.0;
double sum = 0.0;
@ -153,7 +155,7 @@ public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> {
sum += arc.getSize() * arc.getBarycenter();
}
setSize(size);
if (Precision.equals(size, 2 * FastMath.PI, 0)) {
if (Precision.equals(size, MathUtils.TWO_PI, 0)) {
setBarycenter(S1Point.NaN);
} else if (size >= Precision.SAFE_MIN) {
setBarycenter(new S1Point(sum / size));
@ -167,55 +169,84 @@ public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> {
/** Build an ordered list of arcs representing the instance.
* <p>This method builds this arcs set as an ordered list of
* {@link Arc Arc} elements. An empty tree will build an empty list
* while a tree representing the whole real line will build a one
* element list with bounds set to \( 0 and \pi \).</p>
* while a tree representing the whole circle will build a one
* element list with bounds set to \( 0 and 2 \pi \).</p>
* @return a new ordered list containing {@link Arc Arc} elements
*/
public List<Arc> asList() {
final List<Arc> list = new ArrayList<Arc>();
recurseList(getTree(false), list, 0, 2 * FastMath.PI);
return list;
}
final BSPTree<Sphere1D> root = getTree(false);
/** Update an arcs list.
* @param node current node
* @param list list to update
* @param lower lower bound of the current convex cell
* @param upper upper bound of the current convex cell
*/
private void recurseList(final BSPTree<Sphere1D> node, final List<Arc> list,
final double lower, final double upper) {
if (node.getCut() == null) {
if ((Boolean) node.getAttribute()) {
// this leaf cell is an inside cell: an arc
list.add(new Arc(lower, upper));
if (root.getCut() == null) {
// the tree has a single node
if ((Boolean) root.getAttribute()) {
// it is an inside node, it represents the full circle
list.add(new Arc(0.0, 0.0)); // since lower == upper, the arc covers the full circle
}
} else {
final SubChord cut = (SubChord) node.getCut();
final List<Arc> cutArcs = cut.getSubArcs();
final double cutStart = cutArcs.get(0).getInf();
final double cutEnd = cutArcs.get(cutArcs.size() - 1).getSup();
recurseList(node.getMinus(), list, lower, cutStart);
if (list.get(list.size() - 1).checkPoint(cutStart, tolerance) == Location.INSIDE) {
// merge the last arc before the sub-chord and the sub-chord
final Arc merged = new Arc(list.remove(list.size() - 1).getInf(),
cutArcs.remove(0).getSup());
cutArcs.add(0, merged);
// find all arcs limits
final LimitsCollector finder = new LimitsCollector();
root.visit(finder);
final List<Double> limits = finder.getLimits();
// sort them so the first angle is an arc start
Collections.sort(limits);
if (checkPoint(new S1Point(0.5 * (limits.get(0) + limits.get(1)))) == Location.OUTSIDE) {
// the first angle is not an arc start, its the last arc end
// move it properly to the end
limits.add(limits.remove(0) + MathUtils.TWO_PI);
}
final List<Arc> highList = new ArrayList<Arc>();
recurseList(node.getPlus(), highList, cutEnd, upper);
if (highList.get(0).checkPoint(cutEnd, tolerance) == Location.INSIDE) {
// merge the first arc after the sub-chord and the sub-chord
final Arc merged = new Arc(cutArcs.remove(cutArcs.size() - 1).getInf(),
highList.remove(0).getSup());
highList.add(0, merged);
// we can now build the list
for (int i = 0; i < limits.size(); i += 2) {
list.add(new Arc(limits.get(i), limits.get(i + 1)));
}
list.addAll(highList);
}
return list;
}
/** Visitor looking for arc limits. */
private final class LimitsCollector implements BSPTreeVisitor<Sphere1D> {
/** Collected limits. */
private List<Double> limits;
/** Simple constructor. */
public LimitsCollector() {
this.limits = new ArrayList<Double>();
}
/** {@inheritDoc} */
public BSPTreeVisitor.Order visitOrder(final BSPTree<Sphere1D> node) {
return Order.MINUS_PLUS_SUB;
}
/** {@inheritDoc} */
public void visitInternalNode(final BSPTree<Sphere1D> node) {
// check if the chord end points are arc limits
final Chord chord = (Chord) node.getCut().getHyperplane();
if (checkPoint(new S1Point(chord.getStart())) == Location.BOUNDARY) {
limits.add(MathUtils.normalizeAngle(chord.getStart(), FastMath.PI));
}
if (checkPoint(new S1Point(chord.getEnd())) == Location.BOUNDARY) {
limits.add(MathUtils.normalizeAngle(chord.getEnd(), FastMath.PI));
}
}
/** {@inheritDoc} */
public void visitLeafNode(final BSPTree<Sphere1D> node) {
}
/** Get the collected limits.
* @return collected limits
*/
public List<Double> getLimits() {
return limits;
}
}

View File

@ -69,6 +69,29 @@ public class SubChord implements SubHyperplane<Sphere1D> {
return subArcs;
}
/** Get the number of sub-arcs.
* @return number of sub-arcs
*/
public int getNbSubArcs() {
return limits.size() / 2;
}
/** Get the start of the i<sup>th</sup> sub-arc.
* @param i index of the desired arc (counting from 0)
* @return start of the i<sup>th</sup> sub-arc
*/
public double getStart(final int i) {
return limits.get(2 * i);
}
/** Get the end of the i<sup>th</sup> sub-arc.
* @param i index of the desired arc (counting from 0)
* @return end of the i<sup>th</sup> sub-arc
*/
public double getEnd(final int i) {
return limits.get(2 * i + 1);
}
/** {@inheritDoc} */
public double getSize() {
double sum = 0;
@ -81,15 +104,22 @@ public class SubChord implements SubHyperplane<Sphere1D> {
/** {@inheritDoc} */
public Side side(final Hyperplane<Sphere1D> hyperplane) {
final Chord testChord = (Chord) hyperplane;
final double reference = FastMath.PI + testChord.getStart();
final double otherEnd = testChord.getEnd();
final Chord testChord = (Chord) hyperplane;
final double reference = FastMath.PI + testChord.getStart();
final double chordLength = testChord.getEnd() - testChord.getStart();
boolean inMinus = false;
boolean inPlus = false;
for (int i = 0; i < limits.size(); i += 2) {
inMinus = inMinus || (MathUtils.normalizeAngle(limits.get(i), reference) < otherEnd);
inPlus = inPlus || (MathUtils.normalizeAngle(limits.get(i + 1), reference) > otherEnd);
final double syncedStart = MathUtils.normalizeAngle(limits.get(i), reference) - testChord.getStart();
final double chordOffset = limits.get(i) - syncedStart;
final double syncedEnd = limits.get(i + 1) - chordOffset;
if (syncedStart < chordLength || syncedEnd > MathUtils.TWO_PI) {
inMinus = true;
}
if (syncedEnd > chordLength) {
inPlus = true;
}
}
if (inMinus) {
@ -111,34 +141,76 @@ public class SubChord implements SubHyperplane<Sphere1D> {
/** {@inheritDoc} */
public SplitSubHyperplane<Sphere1D> split(final Hyperplane<Sphere1D> hyperplane) {
final Chord testChord = (Chord) hyperplane;
final double reference = FastMath.PI + testChord.getStart();
final double otherEnd = testChord.getEnd();
final List<Double> minus = new ArrayList<Double>(limits.size());
final List<Double> plus = new ArrayList<Double>(limits.size());
final Chord testChord = (Chord) hyperplane;
final double reference = FastMath.PI + testChord.getStart();
final double chordLength = testChord.getEnd() - testChord.getStart();
for (int i = 0; i < limits.size(); i += 2) {
final double subStart = MathUtils.normalizeAngle(limits.get(i), reference);
final double subEnd = MathUtils.normalizeAngle(limits.get(i + 1), reference);
if (subStart < otherEnd) {
minus.add(subStart);
minus.add(FastMath.min(subEnd, otherEnd));
}
if (subEnd > otherEnd) {
plus.add(FastMath.max(subStart, otherEnd));
plus.add(subEnd);
final double syncedStart = MathUtils.normalizeAngle(limits.get(i), reference) - testChord.getStart();
final double chordOffset = limits.get(i) - syncedStart;
final double syncedEnd = limits.get(i + 1) - chordOffset;
if (syncedStart < chordLength) {
// the start point limits.get(i) is in the minus part of the chord
minus.add(limits.get(i));
if (syncedEnd > chordLength) {
// the end point limits.get(i + 1) is past the end of the chord
// so we leave the minus part and enter the plus part
final double minusToPlus = chordLength + chordOffset;
minus.add(minusToPlus);
plus.add(minusToPlus);
if (syncedEnd > MathUtils.TWO_PI) {
// in fact the end point limits.get(i + 1) goes far enough that we
// leave the plus part of the chord and enter the minus part again
final double plusToMinus = MathUtils.TWO_PI + chordOffset;
plus.add(plusToMinus);
minus.add(plusToMinus);
minus.add(limits.get(i + 1));
} else {
// the end point limits.get(i + 1) is in the plus part of the chord
plus.add(limits.get(i + 1));
}
} else {
// the end point limits.get(i + 1) is in the minus part of the chord
minus.add(limits.get(i + 1));
}
} else {
// the start point limits.get(i) is in the plus part of the chord
plus.add(limits.get(i));
if (syncedEnd > MathUtils.TWO_PI) {
// the end point limits.get(i + 1) wraps around to the start of the chord
// so we leave the plus part and enter the minus part
final double plusToMinus = MathUtils.TWO_PI + chordOffset;
plus.add(plusToMinus);
minus.add(plusToMinus);
if (syncedEnd > MathUtils.TWO_PI + chordLength) {
// in fact the end point limits.get(i + 1) goes far enough that we
// leave the minus part of the chord and enter the plus part again
final double minusToPlus = MathUtils.TWO_PI + chordLength + chordOffset;
minus.add(minusToPlus);
plus.add(minusToPlus);
plus.add(limits.get(i + 1));
} else {
// the end point limits.get(i + 1) is in the minus part of the chord
minus.add(limits.get(i + 1));
}
} else {
// the end point limits.get(i + 1) is in the plus part of the chord
plus.add(limits.get(i + 1));
}
}
}
return new SplitSubHyperplane<Sphere1D>(new SubChord(chord, plus),
new SubChord(chord, minus));
return new SplitSubHyperplane<Sphere1D>(plus.isEmpty() ? null : new SubChord(chord, plus),
minus.isEmpty() ? null : new SubChord(chord, minus));
}
/** {@inheritDoc} */
public SubChord copySelf() {
return new SubChord(chord, limits);
return new SubChord(chord.copySelf(), limits);
}
/** {@inheritDoc} */
@ -157,9 +229,9 @@ public class SubChord implements SubHyperplane<Sphere1D> {
final List<Double> otherLimits = ((SubChord) other).limits;
final List<Double> merged;
if (otherLimits.isEmpty()) {
if (other.isEmpty()) {
merged = limits;
} else if (limits.isEmpty()) {
} else if (isEmpty()) {
merged = otherLimits;
} else {
@ -205,25 +277,29 @@ public class SubChord implements SubHyperplane<Sphere1D> {
i = -1;
} else {
++i;
angleI = MathUtils.normalizeAngle(limits.get(i), reference);
}
angleI = MathUtils.normalizeAngle(limits.get(i), reference);
enteringI = !enteringI;
} else {
if (inMerged && enteringI && (!enteringJ)) {
// we were in a merged arc and exit from it
merged.add(angleJ);
inMerged = false;
} else if (!inMerged && enteringJ) {
// we were outside and enter into a merged arc
merged.add(angleJ);
inMerged = true;
if (inMerged) {
if (enteringI && !enteringJ) {
// we were in a merged arc and exit from it
merged.add(angleJ);
inMerged = false;
}
} else {
if (enteringJ) {
// we were outside and enter into a merged arc
merged.add(angleJ);
inMerged = true;
}
}
if (j == jEnd) {
j = -1;
} else {
j = (j + 1) % otherLimits.size();
j = (j + 1) % otherLimits.size();
angleJ = MathUtils.normalizeAngle(otherLimits.get(j), reference);
}
angleJ = MathUtils.normalizeAngle(otherLimits.get(j), reference);
enteringJ = !enteringJ;
}
@ -235,9 +311,9 @@ public class SubChord implements SubHyperplane<Sphere1D> {
if (merged.isEmpty()) {
// the merged arc covers all the circle
merged.add(0.0);
merged.add(2 * FastMath.PI);
merged.add(MathUtils.TWO_PI);
} else {
double previousAngle = merged.get(merged.size() - 1) - 2 * FastMath.PI;
double previousAngle = merged.get(merged.size() - 1) - MathUtils.TWO_PI;
for (int k = 0; k < merged.size() - 1; ++k) {
final double tmp = merged.get(k);
merged.set(k, previousAngle);

View File

@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math3.geometry.spherical.oned;
import org.apache.commons.math3.geometry.partitioning.Region;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.util.Precision;
import org.junit.Assert;
import org.junit.Test;
public class ArcTest {
@Test
public void testArc() {
Arc arc = new Arc(2.3, 5.7);
Assert.assertEquals(3.4, arc.getSize(), 1.0e-10);
Assert.assertEquals(4.0, arc.getBarycenter(), 1.0e-10);
Assert.assertEquals(Region.Location.BOUNDARY, arc.checkPoint(2.3, 1.0e-10));
Assert.assertEquals(Region.Location.BOUNDARY, arc.checkPoint(5.7, 1.0e-10));
Assert.assertEquals(Region.Location.OUTSIDE, arc.checkPoint(1.2, 1.0e-10));
Assert.assertEquals(Region.Location.OUTSIDE, arc.checkPoint(8.5, 1.0e-10));
Assert.assertEquals(Region.Location.INSIDE, arc.checkPoint(8.7, 1.0e-10));
Assert.assertEquals(Region.Location.INSIDE, arc.checkPoint(3.0, 1.0e-10));
Assert.assertEquals(2.3, arc.getInf(), 1.0e-10);
Assert.assertEquals(5.7, arc.getSup(), 1.0e-10);
Assert.assertEquals(4.0, arc.getBarycenter(), 1.0e-10);
Assert.assertEquals(3.4, arc.getSize(), 1.0e-10);
}
@Test
public void testTolerance() {
Arc arc = new Arc(2.3, 5.7);
Assert.assertEquals(Region.Location.OUTSIDE, arc.checkPoint(1.2, 1.0));
Assert.assertEquals(Region.Location.BOUNDARY, arc.checkPoint(1.2, 1.2));
Assert.assertEquals(Region.Location.OUTSIDE, arc.checkPoint(6.5, 0.7));
Assert.assertEquals(Region.Location.BOUNDARY, arc.checkPoint(6.5, 0.9));
Assert.assertEquals(Region.Location.INSIDE, arc.checkPoint(3.0, 0.6));
Assert.assertEquals(Region.Location.BOUNDARY, arc.checkPoint(3.0, 0.8));
}
@Test
public void testFullCircle() {
Arc arc = new Arc(9.0, 9.0);
// no boundaries on a full circle
Assert.assertEquals(Region.Location.INSIDE, arc.checkPoint(9.0, 1.0e-10));
Assert.assertEquals(9.0, arc.getInf(), 1.0e-10);
Assert.assertEquals(9.0 + 2.0 * FastMath.PI, arc.getSup(), 1.0e-10);
Assert.assertEquals(2.0 * FastMath.PI, arc.getSize(), 1.0e-10);
for (double alpha = -20.0; alpha <= 20.0; alpha += 0.1) {
Assert.assertEquals(Region.Location.INSIDE,
arc.checkPoint(alpha, 1.0e-10));
}
}
@Test
public void testSmall() {
Arc arc = new Arc(1.0, FastMath.nextAfter(1.0, Double.POSITIVE_INFINITY));
Assert.assertEquals(2 * Precision.EPSILON, arc.getSize(), Precision.SAFE_MIN);
Assert.assertEquals(1.0, arc.getBarycenter(), Precision.EPSILON);
}
}

View File

@ -0,0 +1,185 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math3.geometry.spherical.oned;
import java.util.List;
import org.apache.commons.math3.geometry.partitioning.Region;
import org.apache.commons.math3.geometry.partitioning.Region.Location;
import org.apache.commons.math3.geometry.partitioning.RegionFactory;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.util.MathUtils;
import org.apache.commons.math3.util.Precision;
import org.junit.Assert;
import org.junit.Test;
public class ArcsSetTest {
@Test
public void testArc() {
ArcsSet set = new ArcsSet(2.3, 5.7, 1.0e-10);
Assert.assertEquals(3.4, set.getSize(), 1.0e-10);
Assert.assertEquals(4.0, ((S1Point) set.getBarycenter()).getAlpha(), 1.0e-10);
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(2.3)));
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.7)));
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new S1Point(1.2)));
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new S1Point(8.5)));
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(8.7)));
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(3.0)));
Assert.assertEquals(1, set.asList().size());
Assert.assertEquals(2.3, set.asList().get(0).getInf(), 1.0e-10);
Assert.assertEquals(5.7, set.asList().get(0).getSup(), 1.0e-10);
Assert.assertEquals(4.0, ((S1Point) set.getBarycenter()).getAlpha(), 1.0e-10);
Assert.assertEquals(3.4, set.getSize(), 1.0e-10);
}
@Test
public void testFullCircle() {
ArcsSet set = new ArcsSet(9.0, 9.0, 1.0e-10);
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(9.0)));
for (double alpha = -20.0; alpha <= 20.0; alpha += 0.1) {
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(alpha)));
}
Assert.assertEquals(1, set.asList().size());
Assert.assertEquals(0.0, set.asList().get(0).getInf(), 1.0e-10);
Assert.assertEquals(2 * FastMath.PI, set.asList().get(0).getSup(), 1.0e-10);
Assert.assertEquals(2 * FastMath.PI, set.getSize(), 1.0e-10);
}
@Test
public void testDifference() {
ArcsSet a = new ArcsSet(1.0, 6.0, 1.0e-10);
List<Arc> aList = a.asList();
Assert.assertEquals(1, aList.size());
Assert.assertEquals(1.0, aList.get(0).getInf(), 1.0e-10);
Assert.assertEquals(6.0, aList.get(0).getSup(), 1.0e-10);
ArcsSet b = new ArcsSet(3.0, 5.0, 1.0e-10);
List<Arc> bList = b.asList();
Assert.assertEquals(1, bList.size());
Assert.assertEquals(3.0, bList.get(0).getInf(), 1.0e-10);
Assert.assertEquals(5.0, bList.get(0).getSup(), 1.0e-10);
ArcsSet aMb = (ArcsSet) new RegionFactory<Sphere1D>().difference(a, b);
for (int k = -2; k < 3; ++k) {
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(0.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(0.9 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(1.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(1.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(2.9 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(3.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(3.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(4.9 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(5.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(5.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(5.9 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(6.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(6.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(6.2 + k * MathUtils.TWO_PI)));
}
List<Arc> aMbList = aMb.asList();
Assert.assertEquals(2, aMbList.size());
Assert.assertEquals(1.0, aMbList.get(0).getInf(), 1.0e-10);
Assert.assertEquals(3.0, aMbList.get(0).getSup(), 1.0e-10);
Assert.assertEquals(5.0, aMbList.get(1).getInf(), 1.0e-10);
Assert.assertEquals(6.0, aMbList.get(1).getSup(), 1.0e-10);
}
@Test
public void testIntersection() {
ArcsSet a = (ArcsSet) new RegionFactory<Sphere1D>().union(new ArcsSet(1.0, 3.0, 1.0e-10),
new ArcsSet(5.0, 6.0, 1.0e-10));
List<Arc> aList = a.asList();
Assert.assertEquals(2, aList.size());
Assert.assertEquals(1.0, aList.get(0).getInf(), 1.0e-10);
Assert.assertEquals(3.0, aList.get(0).getSup(), 1.0e-10);
Assert.assertEquals(5.0, aList.get(1).getInf(), 1.0e-10);
Assert.assertEquals(6.0, aList.get(1).getSup(), 1.0e-10);
ArcsSet b = new ArcsSet(0.0, 5.5, 1.0e-10);
List<Arc> bList = b.asList();
Assert.assertEquals(1, bList.size());
Assert.assertEquals(0.0, bList.get(0).getInf(), 1.0e-10);
Assert.assertEquals(5.5, bList.get(0).getSup(), 1.0e-10);
ArcsSet aMb = (ArcsSet) new RegionFactory<Sphere1D>().intersection(a, b);
for (int k = -2; k < 3; ++k) {
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(0.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(1.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(1.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(2.9 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(3.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(3.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(4.9 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(5.0 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(5.1 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.INSIDE, aMb.checkPoint(new S1Point(5.4 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.BOUNDARY, aMb.checkPoint(new S1Point(5.5 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(5.6 + k * MathUtils.TWO_PI)));
Assert.assertEquals(Location.OUTSIDE, aMb.checkPoint(new S1Point(6.2 + k * MathUtils.TWO_PI)));
}
List<Arc> aMbList = aMb.asList();
Assert.assertEquals(1, aMbList.size());
Assert.assertEquals(1.0, aMbList.get(0).getInf(), 1.0e-10);
Assert.assertEquals(3.0, aMbList.get(0).getSup(), 1.0e-10);
}
@Test
public void testMultiple() {
RegionFactory<Sphere1D> factory = new RegionFactory<Sphere1D>();
ArcsSet set = (ArcsSet)
factory.intersection(factory.union(factory.difference(new ArcsSet(1.0, 6.0, 1.0e-10),
new ArcsSet(3.0, 5.0, 1.0e-10)),
new ArcsSet(0.5, 2.0, 1.0e-10)),
new ArcsSet(0.0, 5.5, 1.0e-10));
Assert.assertEquals(3.0, set.getSize(), 1.0e-10);
Assert.assertEquals(7.0 / 3.0, ((S1Point) set.getBarycenter()).getAlpha(), 1.0e-10);
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new S1Point(0.0)));
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new S1Point(4.0)));
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new S1Point(6.0)));
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(1.2)));
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(5.25)));
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(0.5)));
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(3.0)));
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.0)));
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new S1Point(5.5)));
List<Arc> list = set.asList();
Assert.assertEquals(2, list.size());
Assert.assertEquals( 0.5, list.get(0).getInf(), 1.0e-10);
Assert.assertEquals( 3.0, list.get(0).getSup(), 1.0e-10);
Assert.assertEquals( 5.0, list.get(1).getInf(), 1.0e-10);
Assert.assertEquals( 5.5, list.get(1).getSup(), 1.0e-10);
}
@Test
public void testSinglePoint() {
ArcsSet set = new ArcsSet(1.0, FastMath.nextAfter(1.0, Double.POSITIVE_INFINITY), 1.0e-10);
Assert.assertEquals(2 * Precision.EPSILON, set.getSize(), Precision.SAFE_MIN);
Assert.assertEquals(1.0, ((S1Point) set.getBarycenter()).getAlpha(), Precision.EPSILON);
}
}

View File

@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math3.geometry.spherical.oned;
import org.apache.commons.math3.util.MathUtils;
import org.junit.Assert;
import org.junit.Test;
public class ChordTest {
@Test
public void testChord() {
Chord chord = new Chord(2.3, 5.7, 1.0e-10);
Assert.assertEquals(2.3, chord.copySelf().getStart(), 1.0e-10);
Assert.assertEquals(5.7, chord.copySelf().getEnd(), 1.0e-10);
Assert.assertEquals(1.0e-10, chord.copySelf().getTolerance(), 1.0e-20);
Assert.assertEquals(3.4, chord.wholeHyperplane().getSize(), 1.0e-10);
checkOutside(chord, 2.25);
checkBoundary(chord, 2.3);
checkInside(chord, 2.35);
checkInside(chord, 5.65);
checkBoundary(chord, 5.7);
checkOutside(chord, 5.75);
}
@Test
public void testReverse() {
Chord chord = new Chord(2.3, 5.7, 1.0e-10);
Chord reversed = chord.getReverse();
Assert.assertEquals(chord.getEnd(), reversed.getStart(), 1.0e-10);
Assert.assertEquals(chord.getStart() + MathUtils.TWO_PI, reversed.getEnd(), 1.0e-10);
Assert.assertEquals(1.0e-10, reversed.getTolerance(), 1.0e-20);
Assert.assertEquals(MathUtils.TWO_PI - 3.4, reversed.wholeHyperplane().getSize(), 1.0e-10);
Assert.assertFalse(chord.sameOrientationAs(reversed));
checkInside(reversed, 2.25);
checkBoundary(reversed, 2.3);
checkOutside(reversed, 2.35);
checkOutside(reversed, 5.65);
checkBoundary(reversed, 5.7);
checkInside(reversed, 5.75);
}
@Test
public void testWholeHyperplane() {
Chord chord = new Chord(2.3, 5.7, 1.0e-10);
SubChord subChord = chord.wholeHyperplane();
Assert.assertTrue(chord == subChord.getHyperplane());
Assert.assertEquals(chord.getEnd() - chord.getStart(), subChord.getSize(), 1.0e-10);
}
@Test
public void testWholeSpace() {
Chord chord = new Chord(2.3, 5.7, 1.0e-10);
ArcsSet set = chord.wholeSpace();
Assert.assertEquals(1, set.asList().size());
Assert.assertEquals(0.0, set.asList().get(0).getInf(), 1.0e-10);
Assert.assertEquals(MathUtils.TWO_PI, set.asList().get(0).getSup(), 1.0e-10);
}
private void checkInside(Chord chord, double alpha) {
for (int i = -2; i < 3; ++i) {
Assert.assertTrue(chord.getOffset(new S1Point(alpha + i * MathUtils.TWO_PI)) < 0.0);
}
}
private void checkOutside(Chord chord, double alpha) {
for (int i = -2; i < 3; ++i) {
Assert.assertTrue(chord.getOffset(new S1Point(alpha + i * MathUtils.TWO_PI)) > 0.0);
}
}
private void checkBoundary(Chord chord, double alpha) {
for (int i = -2; i < 3; ++i) {
Assert.assertEquals(0.0, chord.getOffset(new S1Point(alpha + i * MathUtils.TWO_PI)), chord.getTolerance());
}
}
}

View File

@ -0,0 +1,279 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math3.geometry.spherical.oned;
import java.util.List;
import org.apache.commons.math3.geometry.partitioning.Side;
import org.apache.commons.math3.geometry.partitioning.SubHyperplane.SplitSubHyperplane;
import org.apache.commons.math3.util.MathUtils;
import org.junit.Assert;
import org.junit.Test;
public class SubChordTest {
@Test
public void testSubChord() {
SubChord subChord = new SubChord(new Chord(2.3, 5.7, 1.0e-10));
Assert.assertEquals(3.4, subChord.getSize(), 1.0e-10);
Assert.assertFalse(subChord.isEmpty());
Assert.assertEquals(1, subChord.getNbSubArcs());
Assert.assertEquals(2.3, subChord.getStart(0), 1.0e-10);
Assert.assertEquals(5.7, subChord.getEnd(0), 1.0e-10);
Assert.assertEquals(1, subChord.getSubArcs().size());
Assert.assertEquals(2.3, subChord.getSubArcs().get(0).getInf(), 1.0e-10);
Assert.assertEquals(5.7, subChord.getSubArcs().get(0).getSup(), 1.0e-10);
// despite a deep copy is used, chord being immutable its copy returns the same instance
Assert.assertTrue(subChord.getHyperplane() == subChord.copySelf().getHyperplane());
}
@Test
public void testSideEmbedded() {
SubChord s35 = new SubChord(new Chord(3.0, 5.0, 1.0e-10));
SubChord s16 = new SubChord(new Chord(1.0, 6.0, 1.0e-10));
Assert.assertEquals(Side.BOTH, s16.side(s35.getHyperplane()));
Assert.assertEquals(Side.BOTH, s16.side(s35.getHyperplane().getReverse()));
Assert.assertEquals(Side.MINUS, s35.side(s16.getHyperplane()));
Assert.assertEquals(Side.PLUS, s35.side(s16.getHyperplane().getReverse()));
}
@Test
public void testSideOverlapping() {
SubChord s35 = new SubChord(new Chord(3.0, 5.0, 1.0e-10));
SubChord s46 = new SubChord(new Chord(4.0, 6.0, 1.0e-10));
Assert.assertEquals(Side.BOTH, s46.side(s35.getHyperplane()));
Assert.assertEquals(Side.BOTH, s46.side(s35.getHyperplane().getReverse()));
Assert.assertEquals(Side.BOTH, s35.side(s46.getHyperplane()));
Assert.assertEquals(Side.BOTH, s35.side(s46.getHyperplane().getReverse()));
}
@Test
public void testSideHyper() {
Chord zeroLength = new Chord(2.0, 2.0, 1.0e-10);
SubChord sub = new SubChord(zeroLength);
Assert.assertTrue(sub.isEmpty());
Assert.assertEquals(Side.HYPER, sub.side(zeroLength));
}
@Test
public void testSplitEmbedded() {
SubChord s35 = new SubChord(new Chord(3.0, 5.0, 1.0e-10));
SubChord s16 = new SubChord(new Chord(1.0, 6.0, 1.0e-10));
SplitSubHyperplane<Sphere1D> split1 = s16.split(s35.getHyperplane());
SubChord split1Plus = (SubChord) split1.getPlus();
SubChord split1Minus = (SubChord) split1.getMinus();
Assert.assertEquals(3.0, split1Plus.getSize(), 1.0e-10);
Assert.assertEquals(2, split1Plus.getNbSubArcs());
Assert.assertEquals(1.0, split1Plus.getStart(0), 1.0e-10);
Assert.assertEquals(3.0, split1Plus.getEnd(0), 1.0e-10);
Assert.assertEquals(5.0, split1Plus.getStart(1), 1.0e-10);
Assert.assertEquals(6.0, split1Plus.getEnd(1), 1.0e-10);
Assert.assertEquals(2.0, split1Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split1Minus.getNbSubArcs());
Assert.assertEquals(3.0, split1Minus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split1Minus.getEnd(0), 1.0e-10);
SplitSubHyperplane<Sphere1D> split2 = s16.split(s35.getHyperplane().getReverse());
SubChord split2Plus = (SubChord) split2.getPlus();
SubChord split2Minus = (SubChord) split2.getMinus();
Assert.assertEquals(2.0, split2Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split2Plus.getNbSubArcs());
Assert.assertEquals(3.0, split2Plus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split2Plus.getEnd(0), 1.0e-10);
Assert.assertEquals(3.0, split2Minus.getSize(), 1.0e-10);
Assert.assertEquals(2, split2Minus.getNbSubArcs());
Assert.assertEquals(1.0, split2Minus.getStart(0), 1.0e-10);
Assert.assertEquals(3.0, split2Minus.getEnd(0), 1.0e-10);
Assert.assertEquals(5.0, split2Minus.getStart(1), 1.0e-10);
Assert.assertEquals(6.0, split2Minus.getEnd(1), 1.0e-10);
SplitSubHyperplane<Sphere1D> split3 = s35.split(s16.getHyperplane());
SubChord split3Plus = (SubChord) split3.getPlus();
SubChord split3Minus = (SubChord) split3.getMinus();
Assert.assertNull(split3Plus);
Assert.assertEquals(2.0, split3Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split3Minus.getNbSubArcs());
Assert.assertEquals(3.0, split3Minus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split3Minus.getEnd(0), 1.0e-10);
SplitSubHyperplane<Sphere1D> split4 = s35.split(s16.getHyperplane().getReverse());
SubChord split4Plus = (SubChord) split4.getPlus();
SubChord split4Minus = (SubChord) split4.getMinus();
Assert.assertEquals(2.0, split4Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split4Plus.getNbSubArcs());
Assert.assertEquals(3.0, split4Plus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split4Plus.getEnd(0), 1.0e-10);
Assert.assertNull(split4Minus);
}
@Test
public void testSplitOverlapping() {
SubChord s35 = new SubChord(new Chord(3.0, 5.0, 1.0e-10));
SubChord s46 = new SubChord(new Chord(4.0, 6.0, 1.0e-10));
SplitSubHyperplane<Sphere1D> split1 = s46.split(s35.getHyperplane());
SubChord split1Plus = (SubChord) split1.getPlus();
SubChord split1Minus = (SubChord) split1.getMinus();
Assert.assertEquals(1.0, split1Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split1Plus.getNbSubArcs());
Assert.assertEquals(5.0, split1Plus.getStart(0), 1.0e-10);
Assert.assertEquals(6.0, split1Plus.getEnd(0), 1.0e-10);
Assert.assertEquals(1.0, split1Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split1Minus.getNbSubArcs());
Assert.assertEquals(4.0, split1Minus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split1Minus.getEnd(0), 1.0e-10);
SplitSubHyperplane<Sphere1D> split2 = s46.split(s35.getHyperplane().getReverse());
SubChord split2Plus = (SubChord) split2.getPlus();
SubChord split2Minus = (SubChord) split2.getMinus();
Assert.assertEquals(1.0, split2Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split2Plus.getNbSubArcs());
Assert.assertEquals(4.0, split2Plus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split2Plus.getEnd(0), 1.0e-10);
Assert.assertEquals(1.0, split2Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split2Minus.getNbSubArcs());
Assert.assertEquals(5.0, split2Minus.getStart(0), 1.0e-10);
Assert.assertEquals(6.0, split2Minus.getEnd(0), 1.0e-10);
SplitSubHyperplane<Sphere1D> split3 = s35.split(s46.getHyperplane());
SubChord split3Plus = (SubChord) split3.getPlus();
SubChord split3Minus = (SubChord) split3.getMinus();
Assert.assertEquals(1.0, split3Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split3Plus.getNbSubArcs());
Assert.assertEquals(3.0, split3Plus.getStart(0), 1.0e-10);
Assert.assertEquals(4.0, split3Plus.getEnd(0), 1.0e-10);
Assert.assertEquals(1.0, split3Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split3Minus.getNbSubArcs());
Assert.assertEquals(4.0, split3Minus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split3Minus.getEnd(0), 1.0e-10);
SplitSubHyperplane<Sphere1D> split4 = s35.split(s46.getHyperplane().getReverse());
SubChord split4Plus = (SubChord) split4.getPlus();
SubChord split4Minus = (SubChord) split4.getMinus();
Assert.assertEquals(1.0, split4Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split4Plus.getNbSubArcs());
Assert.assertEquals(4.0, split4Plus.getStart(0), 1.0e-10);
Assert.assertEquals(5.0, split4Plus.getEnd(0), 1.0e-10);
Assert.assertEquals(1.0, split4Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split4Minus.getNbSubArcs());
Assert.assertEquals(3.0, split4Minus.getStart(0), 1.0e-10);
Assert.assertEquals(4.0, split4Minus.getEnd(0), 1.0e-10);
}
@Test
public void testReunite() {
// build sub-chord with arcs: [0.5, 1.375], [1.5, 1.75], [2.25, 4.5]
SubChord sA1 = new SubChord(new Chord(0.5, 4.5, 1.0e-10));
SubChord sA2 = (SubChord) sA1.split(new Chord(1.375, 1.5, 1.0e-10)).getPlus();
SubChord sA = (SubChord) sA2.split(new Chord(1.75, 2.25, 1.0e-10)).getPlus();
List<Arc> listSa = sA.getSubArcs();
Assert.assertEquals(3, listSa.size());
Assert.assertEquals(0.5, listSa.get(0).getInf(), 1.0e-10);
Assert.assertEquals(1.375, listSa.get(0).getSup(), 1.0e-10);
Assert.assertEquals(1.5, listSa.get(1).getInf(), 1.0e-10);
Assert.assertEquals(1.75, listSa.get(1).getSup(), 1.0e-10);
Assert.assertEquals(2.25, listSa.get(2).getInf(), 1.0e-10);
Assert.assertEquals(4.5, listSa.get(2).getSup(), 1.0e-10);
// sub-chord with arcs: [5.0, 5.5], [5.75, 1.0+2pi], [ 1.625+2pi, 1.875+2pi], [2.0+2pi, 2.125+2pi], [2.5+2pi, 3.5+2pi]
SubChord sB1 = new SubChord(new Chord(5.0, 3.5 + MathUtils.TWO_PI, 1.0e-10));
SubChord sB2 = (SubChord) sB1.split(new Chord(5.5, 5.75, 1.0e-10)).getPlus();
SubChord sB3 = (SubChord) sB2.split(new Chord(1.0 + MathUtils.TWO_PI, 1.625 + MathUtils.TWO_PI, 1.0e-10)).getPlus();
SubChord sB4 = (SubChord) sB3.split(new Chord(1.875 + MathUtils.TWO_PI, 2.0 + MathUtils.TWO_PI, 1.0e-10)).getPlus();
SubChord sB = (SubChord) sB4.split(new Chord(2.125 + MathUtils.TWO_PI, 2.5 + MathUtils.TWO_PI, 1.0e-10)).getPlus();
List<Arc> listSb = sB.getSubArcs();
Assert.assertEquals(5, listSb.size());
Assert.assertEquals(5.0, listSb.get(0).getInf(), 1.0e-10);
Assert.assertEquals(5.5, listSb.get(0).getSup(), 1.0e-10);
Assert.assertEquals(5.75, listSb.get(1).getInf(), 1.0e-10);
Assert.assertEquals(1.0 + MathUtils.TWO_PI, listSb.get(1).getSup(), 1.0e-10);
Assert.assertEquals(1.625 + MathUtils.TWO_PI, listSb.get(2).getInf(), 1.0e-10);
Assert.assertEquals(1.875 + MathUtils.TWO_PI, listSb.get(2).getSup(), 1.0e-10);
Assert.assertEquals(2.0 + MathUtils.TWO_PI, listSb.get(3).getInf(), 1.0e-10);
Assert.assertEquals(2.125 + MathUtils.TWO_PI, listSb.get(3).getSup(), 1.0e-10);
Assert.assertEquals(2.5 + MathUtils.TWO_PI, listSb.get(4).getInf(), 1.0e-10);
Assert.assertEquals(3.5 + MathUtils.TWO_PI, listSb.get(4).getSup(), 1.0e-10);
List<Arc> listAB = sA.reunite(sB).getSubArcs();
Assert.assertEquals(5, listAB.size());
Assert.assertEquals(5.75 - MathUtils.TWO_PI, listAB.get(0).getInf(), 1.0e-10);
Assert.assertEquals(1.375, listAB.get(0).getSup(), 1.0e-10);
Assert.assertEquals(1.5, listAB.get(1).getInf(), 1.0e-10);
Assert.assertEquals(1.875, listAB.get(1).getSup(), 1.0e-10);
Assert.assertEquals(2.0, listAB.get(2).getInf(), 1.0e-10);
Assert.assertEquals(2.125, listAB.get(2).getSup(), 1.0e-10);
Assert.assertEquals(2.25, listAB.get(3).getInf(), 1.0e-10);
Assert.assertEquals(4.5, listAB.get(3).getSup(), 1.0e-10);
Assert.assertEquals(5.0, listAB.get(4).getInf(), 1.0e-10);
Assert.assertEquals(5.5, listAB.get(4).getSup(), 1.0e-10);
List<Arc> listBA = sB.reunite(sA).getSubArcs();
Assert.assertEquals(5, listBA.size());
Assert.assertEquals(5.0, listBA.get(0).getInf(), 1.0e-10);
Assert.assertEquals(5.5, listBA.get(0).getSup(), 1.0e-10);
Assert.assertEquals(5.75, listBA.get(1).getInf(), 1.0e-10);
Assert.assertEquals(1.375 + MathUtils.TWO_PI, listBA.get(1).getSup(), 1.0e-10);
Assert.assertEquals(1.5 + MathUtils.TWO_PI, listBA.get(2).getInf(), 1.0e-10);
Assert.assertEquals(1.875 + MathUtils.TWO_PI, listBA.get(2).getSup(), 1.0e-10);
Assert.assertEquals(2.0 + MathUtils.TWO_PI, listBA.get(3).getInf(), 1.0e-10);
Assert.assertEquals(2.125 + MathUtils.TWO_PI, listBA.get(3).getSup(), 1.0e-10);
Assert.assertEquals(2.25 + MathUtils.TWO_PI, listBA.get(4).getInf(), 1.0e-10);
Assert.assertEquals(4.5 + MathUtils.TWO_PI, listBA.get(4).getSup(), 1.0e-10);
// special cases
List<Arc> listAEmpty = sA.reunite(new SubChord(new Chord(0, 0, 1.0e-10))).getSubArcs();
Assert.assertEquals(3, listAEmpty.size());
Assert.assertEquals(0.5, listAEmpty.get(0).getInf(), 1.0e-10);
Assert.assertEquals(1.375, listAEmpty.get(0).getSup(), 1.0e-10);
Assert.assertEquals(1.5, listAEmpty.get(1).getInf(), 1.0e-10);
Assert.assertEquals(1.75, listAEmpty.get(1).getSup(), 1.0e-10);
Assert.assertEquals(2.25, listAEmpty.get(2).getInf(), 1.0e-10);
Assert.assertEquals(4.5, listAEmpty.get(2).getSup(), 1.0e-10);
List<Arc> listEmptyA = new SubChord(new Chord(0, 0, 1.0e-10)).reunite(sA).getSubArcs();
Assert.assertEquals(3, listAEmpty.size());
Assert.assertEquals(0.5, listEmptyA.get(0).getInf(), 1.0e-10);
Assert.assertEquals(1.375, listEmptyA.get(0).getSup(), 1.0e-10);
Assert.assertEquals(1.5, listEmptyA.get(1).getInf(), 1.0e-10);
Assert.assertEquals(1.75, listEmptyA.get(1).getSup(), 1.0e-10);
Assert.assertEquals(2.25, listEmptyA.get(2).getInf(), 1.0e-10);
Assert.assertEquals(4.5, listEmptyA.get(2).getSup(), 1.0e-10);
}
@Test
public void testReuniteFullCircle() {
SubChord s1 = new SubChord(new Chord(0, 4, 1.0e-10));
SubChord s2 = new SubChord(new Chord(3, 7, 1.0e-10));
Assert.assertEquals(MathUtils.TWO_PI, s1.reunite(s2).getSize(), 1.0e-10);
}
}