MATH-1437: adding additional unit tests and test utilities for o.a.c.m.geometry.euclidean.twod and o.a.c.m.geometry.euclidean.threed
This commit is contained in:
parent
1b99b4583c
commit
24d3dd8ba7
|
@ -512,7 +512,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
|
|||
final Plane plane = (Plane) cut.getHyperplane();
|
||||
|
||||
// establish search order
|
||||
final double offset = plane.getOffset((Point<Euclidean3D>) point);
|
||||
final double offset = plane.getOffset(point);
|
||||
final boolean in = FastMath.abs(offset) < getTolerance();
|
||||
final BSPTree<Euclidean3D> near;
|
||||
final BSPTree<Euclidean3D> far;
|
||||
|
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* 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.math4.geometry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
import org.apache.commons.math4.geometry.euclidean.oned.Cartesian1D;
|
||||
import org.apache.commons.math4.geometry.euclidean.oned.Euclidean1D;
|
||||
import org.apache.commons.math4.geometry.euclidean.oned.IntervalsSet;
|
||||
import org.apache.commons.math4.geometry.euclidean.oned.OrientedPoint;
|
||||
import org.apache.commons.math4.geometry.euclidean.oned.SubOrientedPoint;
|
||||
import org.apache.commons.math4.geometry.euclidean.oned.Vector1D;
|
||||
import org.apache.commons.math4.geometry.euclidean.threed.Cartesian3D;
|
||||
import org.apache.commons.math4.geometry.euclidean.threed.Euclidean3D;
|
||||
import org.apache.commons.math4.geometry.euclidean.threed.Plane;
|
||||
import org.apache.commons.math4.geometry.euclidean.threed.SubPlane;
|
||||
import org.apache.commons.math4.geometry.euclidean.threed.Vector3D;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.Cartesian2D;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.Euclidean2D;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.Line;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.PolygonsSet;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.SubLine;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.Vector2D;
|
||||
import org.apache.commons.math4.geometry.partitioning.BSPTree;
|
||||
import org.apache.commons.math4.geometry.partitioning.BSPTreeVisitor;
|
||||
import org.junit.Assert;
|
||||
|
||||
/** Class containing various geometry-related test utilities.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class GeometryTestUtils {
|
||||
|
||||
/** Asserts that corresponding values in the given vectors are equal, using the specified
|
||||
* tolerance value.
|
||||
* @param expected
|
||||
* @param actual
|
||||
* @param tolerance
|
||||
*/
|
||||
public static void assertVectorEquals(Vector1D expected, Vector1D actual, double tolerance) {
|
||||
String msg = "Expected vector to equal " + expected + " but was " + actual + ";";
|
||||
Assert.assertEquals(msg, expected.getX(), actual.getX(), tolerance);
|
||||
}
|
||||
|
||||
/** Asserts that corresponding values in the given vectors are equal, using the specified
|
||||
* tolerance value.
|
||||
* @param expected
|
||||
* @param actual
|
||||
* @param tolerance
|
||||
*/
|
||||
public static void assertVectorEquals(Vector2D expected, Vector2D actual, double tolerance) {
|
||||
String msg = "Expected vector to equal " + expected + " but was " + actual + ";";
|
||||
Assert.assertEquals(msg, expected.getX(), actual.getX(), tolerance);
|
||||
Assert.assertEquals(msg, expected.getY(), actual.getY(), tolerance);
|
||||
}
|
||||
|
||||
/** Asserts that corresponding values in the given vectors are equal, using the specified
|
||||
* tolerance value.
|
||||
* @param expected
|
||||
* @param actual
|
||||
* @param tolerance
|
||||
*/
|
||||
public static void assertVectorEquals(Vector3D expected, Vector3D actual, double tolerance) {
|
||||
String msg = "Expected vector to equal " + expected + " but was " + actual + ";";
|
||||
Assert.assertEquals(msg, expected.getX(), actual.getX(), tolerance);
|
||||
Assert.assertEquals(msg, expected.getY(), actual.getY(), tolerance);
|
||||
Assert.assertEquals(msg, expected.getZ(), actual.getZ(), tolerance);
|
||||
}
|
||||
|
||||
/** Prints a string representation of the given 1D {@link BSPTree} to
|
||||
* the console. This is intended for quick debugging of small trees.
|
||||
* @param tree
|
||||
*/
|
||||
public static void printTree1D(BSPTree<Euclidean1D> tree) {
|
||||
TreePrinter1D printer = new TreePrinter1D();
|
||||
System.out.println(printer.writeAsString(tree));
|
||||
}
|
||||
|
||||
/** Prints a string representation of the given 2D {@link BSPTree} to
|
||||
* the console. This is intended for quick debugging of small trees.
|
||||
* @param tree
|
||||
*/
|
||||
public static void printTree2D(BSPTree<Euclidean2D> tree) {
|
||||
TreePrinter2D printer = new TreePrinter2D();
|
||||
System.out.println(printer.writeAsString(tree));
|
||||
}
|
||||
|
||||
/** Prints a string representation of the given 3D {@link BSPTree} to
|
||||
* the console. This is intended for quick debugging of small trees.
|
||||
* @param tree
|
||||
*/
|
||||
public static void printTree3D(BSPTree<Euclidean3D> tree) {
|
||||
TreePrinter3D printer = new TreePrinter3D();
|
||||
System.out.println(printer.writeAsString(tree));
|
||||
}
|
||||
|
||||
/**
|
||||
* Base for classes that create string representations of {@link BSPTree}s.
|
||||
* @param <S>
|
||||
*/
|
||||
public static abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S> {
|
||||
|
||||
/** Indent per tree level */
|
||||
protected static final String INDENT = " ";
|
||||
|
||||
/** Current depth in the tree */
|
||||
protected int depth;
|
||||
|
||||
/** Contains the string output */
|
||||
protected StringBuilder output = new StringBuilder();
|
||||
|
||||
/** Returns a string representation of the given {@link BSPTree}.
|
||||
* @param tree
|
||||
* @return
|
||||
*/
|
||||
public String writeAsString(BSPTree<S> tree) {
|
||||
output.delete(0, output.length());
|
||||
|
||||
tree.visit(this);
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Order visitOrder(BSPTree<S> node) {
|
||||
return Order.SUB_MINUS_PLUS;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void visitInternalNode(BSPTree<S> node) {
|
||||
writeLinePrefix(node);
|
||||
writeInternalNode(node);
|
||||
|
||||
write("\n");
|
||||
|
||||
++depth;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void visitLeafNode(BSPTree<S> node) {
|
||||
writeLinePrefix(node);
|
||||
writeLeafNode(node);
|
||||
|
||||
write("\n");
|
||||
|
||||
BSPTree<S> cur = node;
|
||||
while (cur.getParent() != null && cur.getParent().getPlus() == cur) {
|
||||
--depth;
|
||||
cur = cur.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/** Writes the prefix for the current line in the output. This includes
|
||||
* the line indent, the plus/minus node indicator, and a string identifier
|
||||
* for the node itself.
|
||||
* @param node
|
||||
*/
|
||||
protected void writeLinePrefix(BSPTree<S> node) {
|
||||
for (int i=0; i<depth; ++i) {
|
||||
write(INDENT);
|
||||
}
|
||||
|
||||
if (node.getParent() != null) {
|
||||
if (node.getParent().getMinus() == node) {
|
||||
write("[-] ");
|
||||
}
|
||||
else {
|
||||
write("[+] ");
|
||||
}
|
||||
}
|
||||
|
||||
write(node.getClass().getSimpleName() + "@" + System.identityHashCode(node) + " | ");
|
||||
}
|
||||
|
||||
/** Adds the given string to the output.
|
||||
* @param str
|
||||
*/
|
||||
protected void write(String str) {
|
||||
output.append(str);
|
||||
}
|
||||
|
||||
/** Method for subclasses to provide their own string representation
|
||||
* of the given internal node.
|
||||
*/
|
||||
protected abstract void writeInternalNode(BSPTree<S> node);
|
||||
|
||||
/** Writes a leaf node. The default implementation here simply writes
|
||||
* the node attribute as a string.
|
||||
* @param node
|
||||
*/
|
||||
protected void writeLeafNode(BSPTree<S> node) {
|
||||
write(String.valueOf(node.getAttribute()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Class for creating string representations of 1D {@link BSPTree}s.
|
||||
*/
|
||||
public static class TreePrinter1D extends TreePrinter<Euclidean1D> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void writeInternalNode(BSPTree<Euclidean1D> node) {
|
||||
SubOrientedPoint cut = (SubOrientedPoint) node.getCut();
|
||||
|
||||
OrientedPoint hyper = (OrientedPoint) cut.getHyperplane();
|
||||
write("cut = { hyperplane: ");
|
||||
if (hyper.isDirect()) {
|
||||
write("[" + hyper.getLocation().getX() + ", inf)");
|
||||
}
|
||||
else {
|
||||
write("(-inf, " + hyper.getLocation().getX() + "]");
|
||||
}
|
||||
|
||||
IntervalsSet remainingRegion = (IntervalsSet) cut.getRemainingRegion();
|
||||
if (remainingRegion != null) {
|
||||
write(", remainingRegion: [");
|
||||
|
||||
boolean isFirst = true;
|
||||
for (double[] interval : remainingRegion) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
}
|
||||
else {
|
||||
write(", ");
|
||||
}
|
||||
write(Arrays.toString(interval));
|
||||
}
|
||||
|
||||
write("]");
|
||||
}
|
||||
|
||||
write("}");
|
||||
}
|
||||
}
|
||||
|
||||
/** Class for creating string representations of 2D {@link BSPTree}s.
|
||||
*/
|
||||
public static class TreePrinter2D extends TreePrinter<Euclidean2D> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void writeInternalNode(BSPTree<Euclidean2D> node) {
|
||||
SubLine cut = (SubLine) node.getCut();
|
||||
Line line = (Line) cut.getHyperplane();
|
||||
IntervalsSet remainingRegion = (IntervalsSet) cut.getRemainingRegion();
|
||||
|
||||
write("cut = { angle: " + FastMath.toDegrees(line.getAngle()) + ", origin: " + line.toSpace(Cartesian1D.ZERO) + "}");
|
||||
write(", remainingRegion: [");
|
||||
|
||||
boolean isFirst = true;
|
||||
for (double[] interval : remainingRegion) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
}
|
||||
else {
|
||||
write(", ");
|
||||
}
|
||||
write(Arrays.toString(interval));
|
||||
}
|
||||
|
||||
write("]");
|
||||
}
|
||||
}
|
||||
|
||||
/** Class for creating string representations of 3D {@link BSPTree}s.
|
||||
*/
|
||||
public static class TreePrinter3D extends TreePrinter<Euclidean3D> {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void writeInternalNode(BSPTree<Euclidean3D> node) {
|
||||
SubPlane cut = (SubPlane) node.getCut();
|
||||
Plane plane = (Plane) cut.getHyperplane();
|
||||
PolygonsSet polygon = (PolygonsSet) cut.getRemainingRegion();
|
||||
|
||||
write("cut = { normal: " + plane.getNormal() + ", origin: " + plane.getOrigin() + "}");
|
||||
write(", remainingRegion = [");
|
||||
|
||||
boolean isFirst = true;
|
||||
for (Cartesian2D[] loop : polygon.getVertices()) {
|
||||
// convert to 3-space for easier debugging
|
||||
List<Cartesian3D> loop3 = new ArrayList<>();
|
||||
for (Cartesian2D vertex : loop) {
|
||||
if (vertex != null) {
|
||||
loop3.add(plane.toSpace(vertex));
|
||||
}
|
||||
else {
|
||||
loop3.add(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
}
|
||||
else {
|
||||
write(", ");
|
||||
}
|
||||
|
||||
write(loop3.toString());
|
||||
}
|
||||
|
||||
write("]");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,165 +22,140 @@ import java.text.DecimalFormatSymbols;
|
|||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.math4.exception.DimensionMismatchException;
|
||||
import org.apache.commons.math4.exception.MathArithmeticException;
|
||||
import org.apache.commons.math4.geometry.Point;
|
||||
import org.apache.commons.math4.geometry.Space;
|
||||
import org.apache.commons.math4.geometry.Vector;
|
||||
import org.apache.commons.math4.util.FastMath;
|
||||
import org.apache.commons.numbers.core.Precision;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Cartesian1DTest {
|
||||
|
||||
private static final double TEST_TOLERANCE = 1e-15;
|
||||
|
||||
@Test
|
||||
public void testConstructors() throws DimensionMismatchException {
|
||||
checkVector(new Cartesian1D(3, new Cartesian1D(FastMath.PI / 3)),
|
||||
FastMath.PI);
|
||||
checkVector(new Cartesian1D(2, Cartesian1D.ONE, -3, new Cartesian1D(2)),
|
||||
-4);
|
||||
checkVector(new Cartesian1D(2, Cartesian1D.ONE,
|
||||
5, new Cartesian1D(2),
|
||||
-3, new Cartesian1D(3)),
|
||||
3);
|
||||
checkVector(new Cartesian1D(2, Cartesian1D.ONE,
|
||||
5, new Cartesian1D(2),
|
||||
5, new Cartesian1D(-2),
|
||||
-3, new Cartesian1D(-3)),
|
||||
11);
|
||||
public void testConstants() {
|
||||
// act/assert
|
||||
checkVector(Cartesian1D.ZERO, 0.0);
|
||||
checkVector(Cartesian1D.ONE, 1.0);
|
||||
checkVector(Cartesian1D.NaN, Double.NaN);
|
||||
checkVector(Cartesian1D.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
|
||||
checkVector(Cartesian1D.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_simple() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(2), 2);
|
||||
checkVector(new Cartesian1D(-2), -2);
|
||||
checkVector(new Cartesian1D(FastMath.PI), FastMath.PI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_multiplicative() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(2, new Cartesian1D(3)), 6);
|
||||
checkVector(new Cartesian1D(-2, new Cartesian1D(3)), -6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_linear2() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(
|
||||
2, new Cartesian1D(3),
|
||||
5, new Cartesian1D(7)), 41);
|
||||
checkVector(new Cartesian1D(
|
||||
2, new Cartesian1D(3),
|
||||
-5, new Cartesian1D(7)),-29);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_linear3() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(
|
||||
2, new Cartesian1D(3),
|
||||
5, new Cartesian1D(7),
|
||||
11, new Cartesian1D(13)), 184);
|
||||
checkVector(new Cartesian1D(
|
||||
2, new Cartesian1D(3),
|
||||
5, new Cartesian1D(7),
|
||||
-11, new Cartesian1D(13)), -102);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructor_linear4() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(
|
||||
2, new Cartesian1D(3),
|
||||
5, new Cartesian1D(7),
|
||||
11, new Cartesian1D(13),
|
||||
17, new Cartesian1D(19)), 507);
|
||||
checkVector(new Cartesian1D(
|
||||
2, new Cartesian1D(3),
|
||||
5, new Cartesian1D(7),
|
||||
11, new Cartesian1D(13),
|
||||
-17, new Cartesian1D(19)), -139);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpace() {
|
||||
// act
|
||||
Space space = new Cartesian1D(1).getSpace();
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(1, space.getDimension());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZero() {
|
||||
Assert.assertEquals(0, new Cartesian1D(1).getZero().getNorm(), 1.0e-15);
|
||||
}
|
||||
// act
|
||||
Cartesian1D zero = new Cartesian1D(1).getZero();
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
Cartesian1D u1 = new Cartesian1D(1);
|
||||
Cartesian1D u2 = new Cartesian1D(1);
|
||||
Assert.assertTrue(u1.equals(u1));
|
||||
Assert.assertTrue(u1.equals(u2));
|
||||
Assert.assertFalse(u1.equals(new Cartesian1D(1 + 10 * Precision.EPSILON)));
|
||||
Assert.assertTrue(new Cartesian1D(Double.NaN).equals(new Cartesian1D(Double.NaN)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHash() {
|
||||
Assert.assertEquals(new Cartesian1D(Double.NaN).hashCode(), new Cartesian1D(Double.NaN).hashCode());
|
||||
Cartesian1D u = new Cartesian1D(1);
|
||||
Cartesian1D v = new Cartesian1D(1 + 10 * Precision.EPSILON);
|
||||
Assert.assertTrue(u.hashCode() != v.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfinite() {
|
||||
Assert.assertTrue(new Cartesian1D(Double.NEGATIVE_INFINITY).isInfinite());
|
||||
Assert.assertTrue(new Cartesian1D(Double.POSITIVE_INFINITY).isInfinite());
|
||||
Assert.assertFalse(new Cartesian1D(1).isInfinite());
|
||||
Assert.assertFalse(new Cartesian1D(Double.NaN).isInfinite());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNaN() {
|
||||
Assert.assertTrue(new Cartesian1D(Double.NaN).isNaN());
|
||||
Assert.assertFalse(new Cartesian1D(1).isNaN());
|
||||
Assert.assertFalse(new Cartesian1D(Double.NEGATIVE_INFINITY).isNaN());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
Assert.assertEquals("{3}", new Cartesian1D(3).toString());
|
||||
NumberFormat format = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.US));
|
||||
Assert.assertEquals("{3.000}", new Cartesian1D(3).toString(format));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCoordinates() {
|
||||
Cartesian1D v = new Cartesian1D(1);
|
||||
Assert.assertTrue(FastMath.abs(v.getX() - 1) < 1.0e-12);
|
||||
// assert
|
||||
Assert.assertEquals(0, zero.getX(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNorm1() {
|
||||
Assert.assertEquals(0.0, Cartesian1D.ZERO.getNorm1(), 0);
|
||||
Assert.assertEquals(6.0, new Cartesian1D(6).getNorm1(), 0);
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, Cartesian1D.ZERO.getNorm1(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(6.0, new Cartesian1D(6).getNorm1(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(6.0, new Cartesian1D(-6).getNorm1(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNorm() {
|
||||
Assert.assertEquals(0.0, Cartesian1D.ZERO.getNorm(), 0);
|
||||
Assert.assertEquals(3.0, new Cartesian1D(-3).getNorm(), 1.0e-12);
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, Cartesian1D.ZERO.getNorm(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(3.0, new Cartesian1D(3).getNorm(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(3.0, new Cartesian1D(-3).getNorm(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormSq() {
|
||||
Assert.assertEquals(0.0, new Cartesian1D(0).getNormSq(), 0);
|
||||
Assert.assertEquals(9.0, new Cartesian1D(-3).getNormSq(), 1.0e-12);
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, new Cartesian1D(0).getNormSq(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, new Cartesian1D(3).getNormSq(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, new Cartesian1D(-3).getNormSq(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormInf() {
|
||||
Assert.assertEquals(0.0, Cartesian1D.ZERO.getNormInf(), 0);
|
||||
Assert.assertEquals(3.0, new Cartesian1D(-3).getNormInf(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistance1() {
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
Assert.assertEquals(0.0, new Cartesian1D(-1).distance1(new Cartesian1D(-1)), 0);
|
||||
Assert.assertEquals(5.0, v1.distance1(v2), 1.0e-12);
|
||||
Assert.assertEquals(v1.subtract(v2).getNorm1(), v1.distance1(v2), 1.0e-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistance() {
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
Assert.assertEquals(0.0, Cartesian1D.distance(new Cartesian1D(-1), new Cartesian1D(-1)), 0);
|
||||
Assert.assertEquals(5.0, Cartesian1D.distance(v1, v2), 1.0e-12);
|
||||
Assert.assertEquals(v1.subtract(v2).getNorm(), Cartesian1D.distance(v1, v2), 1.0e-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceSq() {
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
Assert.assertEquals(0.0, Cartesian1D.distanceSq(new Cartesian1D(-1), new Cartesian1D(-1)), 0);
|
||||
Assert.assertEquals(25.0, Cartesian1D.distanceSq(v1, v2), 1.0e-12);
|
||||
Assert.assertEquals(Cartesian1D.distance(v1, v2) * Cartesian1D.distance(v1, v2),
|
||||
Cartesian1D.distanceSq(v1, v2), 1.0e-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceInf() {
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
Assert.assertEquals(0.0, Cartesian1D.distanceInf(new Cartesian1D(-1), new Cartesian1D(-1)), 0);
|
||||
Assert.assertEquals(5.0, Cartesian1D.distanceInf(v1, v2), 1.0e-12);
|
||||
Assert.assertEquals(v1.subtract(v2).getNormInf(), Cartesian1D.distanceInf(v1, v2), 1.0e-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubtract() {
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-3);
|
||||
v1 = v1.subtract(v2);
|
||||
checkVector(v1, 4);
|
||||
|
||||
checkVector(v2.subtract(v1), -7);
|
||||
checkVector(v2.subtract(3, v1), -15);
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, Cartesian1D.ZERO.getNormInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(3.0, new Cartesian1D(3).getNormInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(3.0, new Cartesian1D(-3).getNormInf(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-3);
|
||||
|
||||
// act/assert
|
||||
v1 = v1.add(v2);
|
||||
checkVector(v1, -2);
|
||||
|
||||
|
@ -189,31 +164,224 @@ public class Cartesian1DTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testScalarProduct() {
|
||||
Cartesian1D v = new Cartesian1D(1);
|
||||
v = v.scalarMultiply(3);
|
||||
checkVector(v, 3);
|
||||
public void testSubtract() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-3);
|
||||
|
||||
checkVector(v.scalarMultiply(0.5), 1.5);
|
||||
// act/assert
|
||||
v1 = v1.subtract(v2);
|
||||
checkVector(v1, 4);
|
||||
|
||||
checkVector(v2.subtract(v1), -7);
|
||||
checkVector(v2.subtract(3, v1), -15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalize() throws MathArithmeticException {
|
||||
Assert.assertEquals(1.0, new Cartesian1D(5).normalize().getNorm(), 1.0e-12);
|
||||
try {
|
||||
Cartesian1D.ZERO.normalize();
|
||||
Assert.fail("an exception should have been thrown");
|
||||
} catch (MathArithmeticException ae) {
|
||||
// expected behavior
|
||||
}
|
||||
public void testNormalize() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(1).normalize(), 1);
|
||||
checkVector(new Cartesian1D(-1).normalize(), -1);
|
||||
checkVector(new Cartesian1D(5).normalize(), 1);
|
||||
checkVector(new Cartesian1D(-5).normalize(), -1);
|
||||
}
|
||||
|
||||
@Test(expected = MathArithmeticException.class)
|
||||
public void testNormalize_zeroNorm() {
|
||||
// act
|
||||
Cartesian1D.ZERO.normalize();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegate() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(0.1).negate(), -0.1);
|
||||
checkVector(new Cartesian1D(-0.1).negate(), 0.1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScalarMultiply() {
|
||||
// act/assert
|
||||
checkVector(new Cartesian1D(1).scalarMultiply(3), 3);
|
||||
checkVector(new Cartesian1D(1).scalarMultiply(-3), -3);
|
||||
|
||||
checkVector(new Cartesian1D(1.5).scalarMultiply(7), 10.5);
|
||||
checkVector(new Cartesian1D(-1.5).scalarMultiply(7), -10.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNaN() {
|
||||
// act/assert
|
||||
Assert.assertTrue(new Cartesian1D(Double.NaN).isNaN());
|
||||
Assert.assertFalse(new Cartesian1D(1).isNaN());
|
||||
Assert.assertFalse(new Cartesian1D(Double.NEGATIVE_INFINITY).isNaN());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfinite() {
|
||||
// act/assert
|
||||
Assert.assertTrue(new Cartesian1D(Double.NEGATIVE_INFINITY).isInfinite());
|
||||
Assert.assertTrue(new Cartesian1D(Double.POSITIVE_INFINITY).isInfinite());
|
||||
Assert.assertFalse(new Cartesian1D(1).isInfinite());
|
||||
Assert.assertFalse(new Cartesian1D(Double.NaN).isInfinite());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistance1() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, v1.distance1(v1), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(5.0, v1.distance1(v2), TEST_TOLERANCE);
|
||||
Assert.assertEquals(v1.subtract(v2).getNorm1(), v1.distance1(v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(0.0, new Cartesian1D(-1).distance1(new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistance() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, v1.distance(v1), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(5.0, v1.distance(v2), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5.0, v1.distance((Point<Euclidean1D>) v2), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5.0, v1.distance((Vector<Euclidean1D>) v2), TEST_TOLERANCE);
|
||||
Assert.assertEquals(v1.subtract(v2).getNorm(), v1.distance(v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(0.0, new Cartesian1D(-1).distance(new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistance_static() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, Cartesian1D.distance(v1, v1), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(5.0, Cartesian1D.distance(v1, v2), TEST_TOLERANCE);
|
||||
Assert.assertEquals(v1.subtract(v2).getNorm(), Cartesian1D.distance(v1, v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(0.0, Cartesian1D.distance(new Cartesian1D(-1), new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceInf() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, new Cartesian1D(-1).distanceInf(new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5.0, v1.distanceInf(v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(v1.subtract(v2).getNormInf(), v1.distanceInf(v2), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceInf_static() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, Cartesian1D.distanceInf(new Cartesian1D(-1), new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5.0, Cartesian1D.distanceInf(v1, v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(v1.subtract(v2).getNormInf(), Cartesian1D.distanceInf(v1, v2), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceSq() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, new Cartesian1D(-1).distanceSq(new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
Assert.assertEquals(25.0, v1.distanceSq(v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(Cartesian1D.distance(v1, v2) * Cartesian1D.distance(v1, v2),
|
||||
v1.distanceSq(v2), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceSq_static() {
|
||||
// arrange
|
||||
Cartesian1D v1 = new Cartesian1D(1);
|
||||
Cartesian1D v2 = new Cartesian1D(-4);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, Cartesian1D.distanceSq(new Cartesian1D(-1), new Cartesian1D(-1)), TEST_TOLERANCE);
|
||||
Assert.assertEquals(25.0, Cartesian1D.distanceSq(v1, v2), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(Cartesian1D.distance(v1, v2) * Cartesian1D.distance(v1, v2),
|
||||
Cartesian1D.distanceSq(v1, v2), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDotProduct() {
|
||||
// act/assert
|
||||
Assert.assertEquals(6.0, new Cartesian1D(2).dotProduct(new Cartesian1D(3)), TEST_TOLERANCE);
|
||||
Assert.assertEquals(-6.0, new Cartesian1D(2).dotProduct(new Cartesian1D(-3)), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
// arrange
|
||||
Cartesian1D u1 = new Cartesian1D(1);
|
||||
Cartesian1D u2 = new Cartesian1D(1);
|
||||
|
||||
// act/assert
|
||||
Assert.assertFalse(u1.equals(null));
|
||||
Assert.assertFalse(u1.equals(new Object()));
|
||||
|
||||
Assert.assertTrue(u1.equals(u1));
|
||||
Assert.assertTrue(u1.equals(u2));
|
||||
|
||||
Assert.assertFalse(u1.equals(new Cartesian1D(-1)));
|
||||
Assert.assertFalse(u1.equals(new Cartesian1D(1 + 10 * Precision.EPSILON)));
|
||||
|
||||
Assert.assertTrue(new Cartesian1D(Double.NaN).equals(new Cartesian1D(Double.NaN)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHash() {
|
||||
// arrange
|
||||
Cartesian1D u = new Cartesian1D(1);
|
||||
Cartesian1D v = new Cartesian1D(1 + 10 * Precision.EPSILON);
|
||||
|
||||
// act/assert
|
||||
Assert.assertTrue(u.hashCode() != v.hashCode());
|
||||
Assert.assertEquals(new Cartesian1D(Double.NaN).hashCode(), new Cartesian1D(Double.NaN).hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
// act/assert
|
||||
Assert.assertEquals("{3}", new Cartesian1D(3).toString());
|
||||
Assert.assertEquals("{-3}", new Cartesian1D(-3).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString_numberFormat() {
|
||||
// arrange
|
||||
NumberFormat format = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.US));
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals("{-1.000}", new Cartesian1D(-1).toString(format));
|
||||
Assert.assertEquals("{3.142}", new Cartesian1D(FastMath.PI).toString(format));
|
||||
}
|
||||
|
||||
private void checkVector(Cartesian1D v, double x) {
|
||||
Assert.assertEquals(x, v.getX(), 1.0e-12);
|
||||
Assert.assertEquals(x, v.getX(), TEST_TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,56 +26,158 @@ import org.junit.Test;
|
|||
|
||||
public class IntervalTest {
|
||||
|
||||
private static final double TEST_TOLERANCE = 1e-10;
|
||||
|
||||
@Test
|
||||
public void testInterval() {
|
||||
public void testBasicProperties() {
|
||||
// arrange
|
||||
Interval interval = new Interval(2.3, 5.7);
|
||||
Assert.assertEquals(3.4, interval.getSize(), 1.0e-10);
|
||||
Assert.assertEquals(4.0, interval.getBarycenter(), 1.0e-10);
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(2.3, 1.0e-10));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(5.7, 1.0e-10));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(1.2, 1.0e-10));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(8.7, 1.0e-10));
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(3.0, 1.0e-10));
|
||||
Assert.assertEquals(2.3, interval.getInf(), 1.0e-10);
|
||||
Assert.assertEquals(5.7, interval.getSup(), 1.0e-10);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(3.4, interval.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(4.0, interval.getBarycenter(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(2.3, interval.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5.7, interval.getSup(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTolerance() {
|
||||
Interval interval = new Interval(2.3, 5.7);
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(1.2, 1.0));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(1.2, 1.2));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(8.7, 2.9));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(8.7, 3.1));
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(3.0, 0.6));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(3.0, 0.8));
|
||||
public void testBasicProperties_negativeValues() {
|
||||
// arrange
|
||||
Interval interval = new Interval(-5.7, -2.3);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(3.4, interval.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(-4.0, interval.getBarycenter(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(-5.7, interval.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(-2.3, interval.getSup(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
// MATH-1256
|
||||
@Test(expected = NumberIsTooSmallException.class)
|
||||
public void testStrictOrdering() {
|
||||
new Interval(0, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfinite() {
|
||||
Interval interval = new Interval(9.0, Double.POSITIVE_INFINITY);
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(9.0, 1.0e-10));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(8.4, 1.0e-10));
|
||||
public void testCheckPoint() {
|
||||
// arrange
|
||||
Interval interval = new Interval(2.3, 5.7);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(1.2, TEST_TOLERANCE));
|
||||
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(2.2, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(2.3, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(2.4, TEST_TOLERANCE));
|
||||
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(3.0, TEST_TOLERANCE));
|
||||
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(5.6, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(5.7, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(5.8, TEST_TOLERANCE));
|
||||
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(8.7, TEST_TOLERANCE));
|
||||
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(Double.NEGATIVE_INFINITY, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(Double.POSITIVE_INFINITY, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(Double.NaN, TEST_TOLERANCE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckPoint_tolerance() {
|
||||
// arrange
|
||||
Interval interval = new Interval(2.3, 5.7);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(2.29, 1e-3));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(2.29, 1e-2));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(2.29, 1e-1));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(2.29, 1));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(2.29, 2));
|
||||
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(4.0, 1e-3));
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(4.0, 1e-2));
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(4.0, 1e-1));
|
||||
Assert.assertEquals(Region.Location.INSIDE, interval.checkPoint(4.0, 1));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(4.0, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfinite_inf() {
|
||||
// act
|
||||
Interval interval = new Interval(Double.NEGATIVE_INFINITY, 9);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(9.0, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(9.4, TEST_TOLERANCE));
|
||||
for (double e = 1.0; e <= 6.0; e += 1.0) {
|
||||
Assert.assertEquals(Region.Location.INSIDE,
|
||||
interval.checkPoint(FastMath.pow(10.0, e), 1.0e-10));
|
||||
interval.checkPoint(-1 * FastMath.pow(10.0, e), TEST_TOLERANCE));
|
||||
}
|
||||
Assert.assertTrue(Double.isInfinite(interval.getSize()));
|
||||
Assert.assertEquals(9.0, interval.getInf(), 1.0e-10);
|
||||
Assert.assertTrue(Double.isInfinite(interval.getSup()));
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, interval.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, interval.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, interval.getSup(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfinite_sup() {
|
||||
// act
|
||||
Interval interval = new Interval(9.0, Double.POSITIVE_INFINITY);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, interval.checkPoint(9.0, TEST_TOLERANCE));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, interval.checkPoint(8.4, TEST_TOLERANCE));
|
||||
for (double e = 1.0; e <= 6.0; e += 1.0) {
|
||||
Assert.assertEquals(Region.Location.INSIDE,
|
||||
interval.checkPoint(FastMath.pow(10.0, e), TEST_TOLERANCE));
|
||||
}
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, interval.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, interval.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, interval.getSup(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfinite_infAndSup() {
|
||||
// act
|
||||
Interval interval = new Interval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
|
||||
// assert
|
||||
for (double e = 1.0; e <= 6.0; e += 1.0) {
|
||||
Assert.assertEquals(Region.Location.INSIDE,
|
||||
interval.checkPoint(FastMath.pow(10.0, e), TEST_TOLERANCE));
|
||||
}
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, interval.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, interval.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, interval.getSup(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSinglePoint() {
|
||||
// act
|
||||
Interval interval = new Interval(1.0, 1.0);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(0.0, interval.getSize(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(1.0, interval.getBarycenter(), Precision.EPSILON);
|
||||
}
|
||||
|
||||
// MATH-1256
|
||||
@Test(expected=NumberIsTooSmallException.class)
|
||||
public void testStrictOrdering() {
|
||||
new Interval(0, -1);
|
||||
@Test
|
||||
public void testSingleInfinitePoint_positive() {
|
||||
// act
|
||||
Interval interval = new Interval(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Double.NaN, interval.getSize(), Precision.SAFE_MIN); // inf - inf = NaN according to floating point spec
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, interval.getBarycenter(), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleInfinitePoint_negative() {
|
||||
// act
|
||||
Interval interval = new Interval(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Double.NaN, interval.getSize(), Precision.SAFE_MIN); // inf - inf = NaN according to floating point spec
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, interval.getBarycenter(), Precision.EPSILON);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,15 @@
|
|||
*/
|
||||
package org.apache.commons.math4.geometry.euclidean.oned;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.math4.geometry.GeometryTestUtils;
|
||||
import org.apache.commons.math4.geometry.partitioning.BSPTree;
|
||||
import org.apache.commons.math4.geometry.partitioning.BoundaryProjection;
|
||||
import org.apache.commons.math4.geometry.partitioning.Region;
|
||||
import org.apache.commons.math4.geometry.partitioning.RegionFactory;
|
||||
import org.apache.commons.math4.geometry.partitioning.SubHyperplane;
|
||||
import org.apache.commons.math4.util.FastMath;
|
||||
import org.apache.commons.numbers.core.Precision;
|
||||
import org.junit.Assert;
|
||||
|
@ -27,6 +32,463 @@ import org.junit.Test;
|
|||
|
||||
public class IntervalsSetTest {
|
||||
|
||||
private static final double TEST_TOLERANCE = 1e-15;
|
||||
|
||||
@Test
|
||||
public void testInterval_wholeNumberLine() {
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
BSPTree<Euclidean1D> tree = set.getTree(true);
|
||||
Assert.assertEquals(Boolean.TRUE, tree.getAttribute());
|
||||
Assert.assertNull(tree.getCut());
|
||||
Assert.assertNull(tree.getMinus());
|
||||
Assert.assertNull(tree.getPlus());
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.INSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterval_doubleOpenInterval() {
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
BSPTree<Euclidean1D> tree = set.getTree(true);
|
||||
Assert.assertEquals(Boolean.TRUE, tree.getAttribute());
|
||||
Assert.assertNull(tree.getCut());
|
||||
Assert.assertNull(tree.getMinus());
|
||||
Assert.assertNull(tree.getPlus());
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.INSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterval_openInterval_positive() {
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(9.0, Double.POSITIVE_INFINITY, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(9.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(9.0, Double.POSITIVE_INFINITY, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.INSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.INSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterval_openInterval_negative() {
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(Double.NEGATIVE_INFINITY, 9.0, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, 9.0, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterval_singleClosedInterval() {
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(-1.0, 9.0, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(-1.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(10.0, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(new Cartesian1D(4.0), (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(-1.0, 9.0, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.OUTSIDE, set, -2.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterval_singlePoint() {
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(1.0, 1.0, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(1.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(1.0, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(new Cartesian1D(1.0), (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(1.0, 1.0, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 1.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 2.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_wholeNumberLine() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
BSPTree<Euclidean1D> tree = set.getTree(true);
|
||||
Assert.assertEquals(Boolean.TRUE, tree.getAttribute());
|
||||
Assert.assertNull(tree.getCut());
|
||||
Assert.assertNull(tree.getMinus());
|
||||
Assert.assertNull(tree.getPlus());
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.INSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_openInterval_positive() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(9.0, false));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(9.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(9.0, Double.POSITIVE_INFINITY, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.INSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.INSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_openInterval_negative() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(9.0, true));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, 9.0, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_singleClosedInterval() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(-1.0, false));
|
||||
boundaries.add(subOrientedPoint(9.0, true));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(-1.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(10.0, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(new Cartesian1D(4.0), (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(-1.0, 9.0, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.OUTSIDE, set, -2.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_multipleClosedIntervals() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(-1.0, false));
|
||||
boundaries.add(subOrientedPoint(2.0, true));
|
||||
boundaries.add(subOrientedPoint(5.0, false));
|
||||
boundaries.add(subOrientedPoint(9.0, true));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(-1.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(9.0, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(7.0, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(new Cartesian1D(29.5 / 7.0), (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(2, intervals.size());
|
||||
assertInterval(-1.0, 2.0, intervals.get(0), TEST_TOLERANCE);
|
||||
assertInterval(5.0, 9.0, intervals.get(1), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.OUTSIDE, set, -2.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 3.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 6.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 10.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_mixedOpenAndClosedIntervals() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(-2.0, true));
|
||||
boundaries.add(subOrientedPoint(-1.0, false));
|
||||
boundaries.add(subOrientedPoint(2.0, true));
|
||||
boundaries.add(subOrientedPoint(5.0, false));
|
||||
boundaries.add(subOrientedPoint(9.0, true));
|
||||
boundaries.add(subOrientedPoint(10.0, false));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(TEST_TOLERANCE, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(new Cartesian1D(Double.NaN), (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(4, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, -2.0, intervals.get(0), TEST_TOLERANCE);
|
||||
assertInterval(-1.0, 2.0, intervals.get(1), TEST_TOLERANCE);
|
||||
assertInterval(5.0, 9.0, intervals.get(2), TEST_TOLERANCE);
|
||||
assertInterval(10.0, Double.POSITIVE_INFINITY, intervals.get(3), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, Double.NEGATIVE_INFINITY);
|
||||
assertLocation(Region.Location.INSIDE, set, -3);
|
||||
assertLocation(Region.Location.OUTSIDE, set, -1.5);
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 3.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 6.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 - 1e-16);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 9.0 + 1e-16);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 9.5);
|
||||
assertLocation(Region.Location.INSIDE, set, 11.0);
|
||||
assertLocation(Region.Location.INSIDE, set, Double.POSITIVE_INFINITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_intervalEqualToTolerance_onlyFirstBoundaryUsed() {
|
||||
// arrange
|
||||
double tolerance = 1e-3;
|
||||
double first = 1.0;
|
||||
double second = 1.0 + tolerance;
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(first, true, tolerance));
|
||||
boundaries.add(subOrientedPoint(second, false, tolerance));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, tolerance);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(tolerance, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(first, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(Double.NEGATIVE_INFINITY, first, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.INSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 1.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 2.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromBoundaries_intervalSmallerThanTolerance_onlyFirstBoundaryUsed() {
|
||||
// arrange
|
||||
double tolerance = 1e-3;
|
||||
double first = 1.0;
|
||||
double second = 1.0 - 1e-4;
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(first, false, tolerance));
|
||||
boundaries.add(subOrientedPoint(second, true, tolerance));
|
||||
|
||||
// act
|
||||
IntervalsSet set = new IntervalsSet(boundaries, tolerance);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(tolerance, set.getTolerance(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(first, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(Cartesian1D.NaN, (Cartesian1D) set.getBarycenter(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> intervals = set.asList();
|
||||
Assert.assertEquals(1, intervals.size());
|
||||
assertInterval(first, Double.POSITIVE_INFINITY, intervals.get(0), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 1.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 2.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProjectToBoundary() {
|
||||
// arrange
|
||||
List<SubHyperplane<Euclidean1D>> boundaries = new ArrayList<>();
|
||||
boundaries.add(subOrientedPoint(-2.0, true));
|
||||
boundaries.add(subOrientedPoint(-1.0, false));
|
||||
boundaries.add(subOrientedPoint(2.0, true));
|
||||
boundaries.add(subOrientedPoint(5.0, false));
|
||||
boundaries.add(subOrientedPoint(9.0, true));
|
||||
boundaries.add(subOrientedPoint(10.0, false));
|
||||
|
||||
IntervalsSet set = new IntervalsSet(boundaries, TEST_TOLERANCE);
|
||||
|
||||
// act/assert
|
||||
assertProjection(new Cartesian1D(-2), -1, set, new Cartesian1D(-3));
|
||||
assertProjection(new Cartesian1D(-2), 0, set, new Cartesian1D(-2));
|
||||
assertProjection(new Cartesian1D(-2), 0.1, set, new Cartesian1D(-1.9));
|
||||
|
||||
assertProjection(new Cartesian1D(-1), 0.5, set, new Cartesian1D(-1.5));
|
||||
assertProjection(new Cartesian1D(-1), 0.1, set, new Cartesian1D(-1.1));
|
||||
assertProjection(new Cartesian1D(-1), 0, set, new Cartesian1D(-1));
|
||||
assertProjection(new Cartesian1D(-1), -1, set, new Cartesian1D(0));
|
||||
|
||||
assertProjection(new Cartesian1D(2), -1, set, new Cartesian1D(1));
|
||||
assertProjection(new Cartesian1D(2), 0, set, new Cartesian1D(2));
|
||||
assertProjection(new Cartesian1D(2), 1, set, new Cartesian1D(3));
|
||||
|
||||
assertProjection(new Cartesian1D(5), 1, set, new Cartesian1D(4));
|
||||
assertProjection(new Cartesian1D(5), 0, set, new Cartesian1D(5));
|
||||
|
||||
assertProjection(new Cartesian1D(5), -1, set, new Cartesian1D(6));
|
||||
assertProjection(new Cartesian1D(5), -2, set, new Cartesian1D(7));
|
||||
|
||||
assertProjection(new Cartesian1D(9), -1, set, new Cartesian1D(8));
|
||||
assertProjection(new Cartesian1D(9), 0, set, new Cartesian1D(9));
|
||||
assertProjection(new Cartesian1D(9), 0.1, set, new Cartesian1D(9.1));
|
||||
|
||||
assertProjection(new Cartesian1D(10), 0, set, new Cartesian1D(10));
|
||||
assertProjection(new Cartesian1D(10), -1, set, new Cartesian1D(11));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterval() {
|
||||
IntervalsSet set = new IntervalsSet(2.3, 5.7, 1.0e-10);
|
||||
|
@ -61,44 +523,65 @@ public class IntervalsSetTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMultiple() {
|
||||
public void testBooleanOperations() {
|
||||
// arrange
|
||||
RegionFactory<Euclidean1D> factory = new RegionFactory<>();
|
||||
|
||||
// act
|
||||
IntervalsSet set = (IntervalsSet)
|
||||
factory.intersection(factory.union(factory.difference(new IntervalsSet(1.0, 6.0, 1.0e-10),
|
||||
new IntervalsSet(3.0, 5.0, 1.0e-10)),
|
||||
new IntervalsSet(9.0, Double.POSITIVE_INFINITY, 1.0e-10)),
|
||||
new IntervalsSet(Double.NEGATIVE_INFINITY, 11.0, 1.0e-10));
|
||||
Assert.assertEquals(5.0, set.getSize(), 1.0e-10);
|
||||
Assert.assertEquals(5.9, ((Cartesian1D) set.getBarycenter()).getX(), 1.0e-10);
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new Cartesian1D(0.0)));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new Cartesian1D(4.0)));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new Cartesian1D(8.0)));
|
||||
Assert.assertEquals(Region.Location.OUTSIDE, set.checkPoint(new Cartesian1D(12.0)));
|
||||
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new Cartesian1D(1.2)));
|
||||
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new Cartesian1D(5.9)));
|
||||
Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new Cartesian1D(9.01)));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new Cartesian1D(5.0)));
|
||||
Assert.assertEquals(Region.Location.BOUNDARY, set.checkPoint(new Cartesian1D(11.0)));
|
||||
Assert.assertEquals( 1.0, set.getInf(), 1.0e-10);
|
||||
Assert.assertEquals(11.0, set.getSup(), 1.0e-10);
|
||||
factory.intersection(factory.union(factory.difference(new IntervalsSet(1.0, 6.0, TEST_TOLERANCE),
|
||||
new IntervalsSet(3.0, 5.0, TEST_TOLERANCE)),
|
||||
new IntervalsSet(9.0, Double.POSITIVE_INFINITY, TEST_TOLERANCE)),
|
||||
new IntervalsSet(Double.NEGATIVE_INFINITY, 11.0, TEST_TOLERANCE));
|
||||
|
||||
// arrange
|
||||
Assert.assertEquals(1.0, set.getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(11.0, set.getSup(), TEST_TOLERANCE);
|
||||
|
||||
Assert.assertEquals(5.0, set.getSize(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5.9, ((Cartesian1D) set.getBarycenter()).getX(), TEST_TOLERANCE);
|
||||
|
||||
assertLocation(Region.Location.OUTSIDE, set, 0.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 4.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 8.0);
|
||||
assertLocation(Region.Location.OUTSIDE, set, 12.0);
|
||||
assertLocation(Region.Location.INSIDE, set, 1.2);
|
||||
assertLocation(Region.Location.INSIDE, set, 5.9);
|
||||
assertLocation(Region.Location.INSIDE, set, 9.01);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 5.0);
|
||||
assertLocation(Region.Location.BOUNDARY, set, 11.0);
|
||||
|
||||
List<Interval> list = set.asList();
|
||||
Assert.assertEquals(3, list.size());
|
||||
Assert.assertEquals( 1.0, 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( 6.0, list.get(1).getSup(), 1.0e-10);
|
||||
Assert.assertEquals( 9.0, list.get(2).getInf(), 1.0e-10);
|
||||
Assert.assertEquals(11.0, list.get(2).getSup(), 1.0e-10);
|
||||
|
||||
assertInterval(1.0, 3.0, list.get(0), TEST_TOLERANCE);
|
||||
assertInterval(5.0, 6.0, list.get(1), TEST_TOLERANCE);
|
||||
assertInterval(9.0, 11.0, list.get(2), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSinglePoint() {
|
||||
IntervalsSet set = new IntervalsSet(1.0, 1.0, 1.0e-10);
|
||||
Assert.assertEquals(0.0, set.getSize(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(0.0, set.getBoundarySize(), Precision.SAFE_MIN);
|
||||
Assert.assertEquals(1.0, ((Cartesian1D) set.getBarycenter()).getX(), Precision.EPSILON);
|
||||
private void assertLocation(Region.Location location, IntervalsSet set, double pt) {
|
||||
Assert.assertEquals(location, set.checkPoint(new Cartesian1D(pt)));
|
||||
}
|
||||
|
||||
private void assertInterval(double expectedInf, double expectedSup, Interval actual, double tolerance) {
|
||||
Assert.assertEquals(expectedInf, actual.getInf(), tolerance);
|
||||
Assert.assertEquals(expectedSup, actual.getSup(), tolerance);
|
||||
}
|
||||
|
||||
private void assertProjection(Cartesian1D expectedProjection, double expectedOffset,
|
||||
IntervalsSet set, Cartesian1D toProject) {
|
||||
BoundaryProjection<Euclidean1D> proj = set.projectToBoundary(toProject);
|
||||
|
||||
GeometryTestUtils.assertVectorEquals(toProject, (Cartesian1D) proj.getOriginal(), TEST_TOLERANCE);
|
||||
GeometryTestUtils.assertVectorEquals(expectedProjection, (Cartesian1D) proj.getProjected(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(expectedOffset, proj.getOffset(), TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
private SubOrientedPoint subOrientedPoint(double location, boolean direct) {
|
||||
return subOrientedPoint(location, direct, TEST_TOLERANCE);
|
||||
}
|
||||
|
||||
private SubOrientedPoint subOrientedPoint(double location, boolean direct, double tolerance) {
|
||||
// the remaining region isn't necessary for creating 1D boundaries so we can set it to null here
|
||||
return new SubOrientedPoint(new OrientedPoint(new Cartesian1D(location), direct, tolerance), null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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.math4.geometry.euclidean.oned;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.apache.commons.math3.util.Precision;
|
||||
import org.apache.commons.math4.geometry.Point;
|
||||
import org.apache.commons.math4.geometry.Vector;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class OrientedPointTest {
|
||||
|
||||
@Test
|
||||
public void testConstructor() {
|
||||
// act
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(2.0), true, 1e-5);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(2.0, pt.getLocation().getX(), Precision.EPSILON);
|
||||
Assert.assertEquals(true, pt.isDirect());
|
||||
Assert.assertEquals(1e-5, pt.getTolerance(), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopySelf() {
|
||||
// arrange
|
||||
OrientedPoint orig = new OrientedPoint(new Cartesian1D(2.0), true, 1e-5);
|
||||
|
||||
// act
|
||||
OrientedPoint copy = orig.copySelf();
|
||||
|
||||
// assert
|
||||
Assert.assertSame(orig, copy);
|
||||
Assert.assertEquals(2.0, copy.getLocation().getX(), Precision.EPSILON);
|
||||
Assert.assertEquals(true, copy.isDirect());
|
||||
Assert.assertEquals(1e-5, copy.getTolerance(), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOffset_direct_point() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(-1.0), true, 1e-5);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(-99, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-100)), Precision.EPSILON);
|
||||
Assert.assertEquals(-1, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-2)), Precision.EPSILON);
|
||||
Assert.assertEquals(-0.01, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-1.01)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.0, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-1.0)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.01, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-0.99)), Precision.EPSILON);
|
||||
Assert.assertEquals(1, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(0)), Precision.EPSILON);
|
||||
Assert.assertEquals(101, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(100)), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOffset_notDirect_point() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(-1.0), false, 1e-5);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(99, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-100)), Precision.EPSILON);
|
||||
Assert.assertEquals(1, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-2)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.01, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-1.01)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.0, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-1.0)), Precision.EPSILON);
|
||||
Assert.assertEquals(-0.01, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(-0.99)), Precision.EPSILON);
|
||||
Assert.assertEquals(-1, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(0)), Precision.EPSILON);
|
||||
Assert.assertEquals(-101, pt.getOffset((Point<Euclidean1D>) new Cartesian1D(100)), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOffset_direct_vector() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(-1.0), true, 1e-5);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(-99, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-100)), Precision.EPSILON);
|
||||
Assert.assertEquals(-1, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-2)), Precision.EPSILON);
|
||||
Assert.assertEquals(-0.01, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-1.01)), Precision.EPSILON);
|
||||
Assert.assertEquals(-0.0, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-1.0)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.01, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-0.99)), Precision.EPSILON);
|
||||
Assert.assertEquals(1, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(0)), Precision.EPSILON);
|
||||
Assert.assertEquals(101, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(100)), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOffset_notDirect_vector() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(-1.0), false, 1e-5);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(99, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-100)), Precision.EPSILON);
|
||||
Assert.assertEquals(1, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-2)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.01, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-1.01)), Precision.EPSILON);
|
||||
Assert.assertEquals(0.0, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-1.0)), Precision.EPSILON);
|
||||
Assert.assertEquals(-0.01, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(-0.99)), Precision.EPSILON);
|
||||
Assert.assertEquals(-1, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(0)), Precision.EPSILON);
|
||||
Assert.assertEquals(-101, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(100)), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWholeHyperplane() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(1.0), false, 1e-5);
|
||||
|
||||
// act
|
||||
SubOrientedPoint subPt = pt.wholeHyperplane();
|
||||
|
||||
// assert
|
||||
Assert.assertSame(pt, subPt.getHyperplane());
|
||||
Assert.assertNull(subPt.getRemainingRegion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWholeSpace() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(1.0), false, 1e-5);
|
||||
|
||||
// act
|
||||
IntervalsSet set = pt.wholeSpace();
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Double.NEGATIVE_INFINITY, set.getInf(), Precision.EPSILON);
|
||||
Assert.assertEquals(Double.POSITIVE_INFINITY, set.getSup(), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameOrientationAs() {
|
||||
// arrange
|
||||
OrientedPoint notDirect1 = new OrientedPoint(new Cartesian1D(1.0), false, 1e-5);
|
||||
OrientedPoint notDirect2 = new OrientedPoint(new Cartesian1D(1.0), false, 1e-5);
|
||||
OrientedPoint direct1 = new OrientedPoint(new Cartesian1D(1.0), true, 1e-5);
|
||||
OrientedPoint direct2 = new OrientedPoint(new Cartesian1D(1.0), true, 1e-5);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(true, notDirect1.sameOrientationAs(notDirect1));
|
||||
Assert.assertEquals(true, notDirect1.sameOrientationAs(notDirect2));
|
||||
Assert.assertEquals(true, notDirect2.sameOrientationAs(notDirect1));
|
||||
|
||||
Assert.assertEquals(true, direct1.sameOrientationAs(direct1));
|
||||
Assert.assertEquals(true, direct1.sameOrientationAs(direct2));
|
||||
Assert.assertEquals(true, direct2.sameOrientationAs(direct1));
|
||||
|
||||
Assert.assertEquals(false, notDirect1.sameOrientationAs(direct1));
|
||||
Assert.assertEquals(false, direct1.sameOrientationAs(notDirect1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProject() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(1.0), true, 1e-5);
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(1.0, ((Cartesian1D) pt.project(new Cartesian1D(-1.0))).getX(), Precision.EPSILON);
|
||||
Assert.assertEquals(1.0, ((Cartesian1D) pt.project(new Cartesian1D(0.0))).getX(), Precision.EPSILON);
|
||||
Assert.assertEquals(1.0, ((Cartesian1D) pt.project(new Cartesian1D(1.0))).getX(), Precision.EPSILON);
|
||||
Assert.assertEquals(1.0, ((Cartesian1D) pt.project(new Cartesian1D(100.0))).getX(), Precision.EPSILON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevertSelf() {
|
||||
// arrange
|
||||
OrientedPoint pt = new OrientedPoint(new Cartesian1D(2.0), true, 1e-5);
|
||||
|
||||
// act
|
||||
pt.revertSelf();
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(2.0, pt.getLocation().getX(), Precision.EPSILON);
|
||||
Assert.assertEquals(false, pt.isDirect());
|
||||
Assert.assertEquals(1e-5, pt.getTolerance(), Precision.EPSILON);
|
||||
|
||||
Assert.assertEquals(1, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(1.0)), Precision.EPSILON);
|
||||
Assert.assertEquals(-1, pt.getOffset((Vector<Euclidean1D>) new Cartesian1D(3.0)), Precision.EPSILON);
|
||||
}
|
||||
}
|
|
@ -16,8 +16,6 @@
|
|||
*/
|
||||
package org.apache.commons.math4.geometry.euclidean.oned;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.math4.geometry.partitioning.Side;
|
||||
import org.apache.commons.math4.geometry.partitioning.SubHyperplane;
|
||||
import org.apache.commons.math4.geometry.partitioning.SubHyperplane.SplitSubHyperplane;
|
||||
|
@ -31,7 +29,7 @@ public class SubOrientedPointTest {
|
|||
public void testGetSize() {
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane();
|
||||
SubOrientedPoint pt = hyperplane.wholeHyperplane();
|
||||
|
||||
// act/assert
|
||||
Assert.assertEquals(0.0, pt.getSize(), TEST_TOLERANCE);
|
||||
|
@ -41,7 +39,7 @@ public class SubOrientedPointTest {
|
|||
public void testIsEmpty() {
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane();
|
||||
SubOrientedPoint pt = hyperplane.wholeHyperplane();
|
||||
|
||||
// act/assert
|
||||
Assert.assertFalse(pt.isEmpty());
|
||||
|
@ -51,7 +49,7 @@ public class SubOrientedPointTest {
|
|||
public void testBuildNew() {
|
||||
// arrange
|
||||
OrientedPoint originalHyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = (SubOrientedPoint) originalHyperplane.wholeHyperplane();
|
||||
SubOrientedPoint pt = originalHyperplane.wholeHyperplane();
|
||||
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE);
|
||||
IntervalsSet intervals = new IntervalsSet(2, 3, TEST_TOLERANCE);
|
||||
|
@ -67,86 +65,80 @@ public class SubOrientedPointTest {
|
|||
|
||||
@Test
|
||||
public void testSplit_resultOnMinusSide() {
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
IntervalsSet interval = new IntervalsSet(TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
|
||||
|
||||
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE);
|
||||
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE);
|
||||
|
||||
// act
|
||||
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
|
||||
// act
|
||||
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Side.MINUS, split.getSide());
|
||||
// assert
|
||||
Assert.assertEquals(Side.MINUS, split.getSide());
|
||||
|
||||
SubOrientedPoint minusSub = ((SubOrientedPoint) split.getMinus());
|
||||
Assert.assertNotNull(minusSub);
|
||||
SubOrientedPoint minusSub = ((SubOrientedPoint) split.getMinus());
|
||||
Assert.assertNotNull(minusSub);
|
||||
|
||||
OrientedPoint minusHyper = (OrientedPoint) minusSub.getHyperplane();
|
||||
Assert.assertEquals(1, minusHyper.getLocation().getX(), TEST_TOLERANCE);
|
||||
OrientedPoint minusHyper = (OrientedPoint) minusSub.getHyperplane();
|
||||
Assert.assertEquals(1, minusHyper.getLocation().getX(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> minusIntervals = ((IntervalsSet) minusSub.getRemainingRegion()).asList();
|
||||
Assert.assertEquals(1, minusIntervals.size());
|
||||
Assert.assertEquals(4, minusIntervals.get(0).getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5, minusIntervals.get(0).getSup(), TEST_TOLERANCE);
|
||||
Assert.assertSame(interval, minusSub.getRemainingRegion());
|
||||
|
||||
Assert.assertNull(split.getPlus());
|
||||
Assert.assertNull(split.getPlus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplit_resultOnPlusSide() {
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
IntervalsSet interval = new IntervalsSet(TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
|
||||
|
||||
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(0), true, TEST_TOLERANCE);
|
||||
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(0), true, TEST_TOLERANCE);
|
||||
|
||||
// act
|
||||
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
|
||||
// act
|
||||
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Side.PLUS, split.getSide());
|
||||
// assert
|
||||
Assert.assertEquals(Side.PLUS, split.getSide());
|
||||
|
||||
Assert.assertNull(split.getMinus());
|
||||
Assert.assertNull(split.getMinus());
|
||||
|
||||
SubOrientedPoint plusSub = ((SubOrientedPoint) split.getPlus());
|
||||
Assert.assertNotNull(plusSub);
|
||||
SubOrientedPoint plusSub = ((SubOrientedPoint) split.getPlus());
|
||||
Assert.assertNotNull(plusSub);
|
||||
|
||||
OrientedPoint plusHyper = (OrientedPoint) plusSub.getHyperplane();
|
||||
Assert.assertEquals(1, plusHyper.getLocation().getX(), TEST_TOLERANCE);
|
||||
OrientedPoint plusHyper = (OrientedPoint) plusSub.getHyperplane();
|
||||
Assert.assertEquals(1, plusHyper.getLocation().getX(), TEST_TOLERANCE);
|
||||
|
||||
List<Interval> plusIntervals = ((IntervalsSet) plusSub.getRemainingRegion()).asList();
|
||||
Assert.assertEquals(1, plusIntervals.size());
|
||||
Assert.assertEquals(4, plusIntervals.get(0).getInf(), TEST_TOLERANCE);
|
||||
Assert.assertEquals(5, plusIntervals.get(0).getSup(), TEST_TOLERANCE);
|
||||
Assert.assertSame(interval, plusSub.getRemainingRegion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplit_equivalentHyperplanes() {
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
IntervalsSet interval = new IntervalsSet(TEST_TOLERANCE);
|
||||
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
|
||||
|
||||
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
|
||||
|
||||
// act
|
||||
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
|
||||
// act
|
||||
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(Side.HYPER, split.getSide());
|
||||
// assert
|
||||
Assert.assertEquals(Side.HYPER, split.getSide());
|
||||
|
||||
Assert.assertNull(split.getMinus());
|
||||
Assert.assertNull(split.getPlus());
|
||||
Assert.assertNull(split.getMinus());
|
||||
Assert.assertNull(split.getPlus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplit_usesToleranceFromParentHyperplane() {
|
||||
// arrange
|
||||
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, 0.1);
|
||||
SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane();
|
||||
SubOrientedPoint pt = hyperplane.wholeHyperplane();
|
||||
|
||||
// act/assert
|
||||
SplitSubHyperplane<Euclidean1D> plusSplit = pt.split(new OrientedPoint(new Cartesian1D(0.899), true, 1e-10));
|
||||
|
|
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* 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.math4.geometry.euclidean.threed;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.Cartesian2D;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.Euclidean2D;
|
||||
import org.apache.commons.math4.geometry.euclidean.twod.PolygonsSet;
|
||||
import org.apache.commons.math4.geometry.partitioning.BSPTree;
|
||||
import org.apache.commons.math4.geometry.partitioning.BSPTreeVisitor;
|
||||
import org.apache.commons.math4.geometry.partitioning.BoundaryAttribute;
|
||||
|
||||
/** This class creates simple OBJ files from {@link PolyhedronsSet} instances.
|
||||
* The output files can be opened in a 3D viewer for visual debugging of 3D
|
||||
* regions. This class is only intended for use in testing.
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/Wavefront_.obj_file
|
||||
* @since 4.0
|
||||
*/
|
||||
public class OBJWriter {
|
||||
|
||||
/** Writes an OBJ file representing the given {@link PolyhedronsSet}. Only
|
||||
* finite boundaries are written. Infinite boundaries are ignored.
|
||||
* @param file The path of the file to write
|
||||
* @param poly The input PolyhedronsSet
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void write(String file, PolyhedronsSet poly) throws IOException {
|
||||
write(new File(file), poly);
|
||||
}
|
||||
|
||||
/** Writes an OBJ file representing the given {@link PolyhedronsSet}. Only
|
||||
* finite boundaries are written. Infinite boundaries are ignored.
|
||||
* @param file The file to write
|
||||
* @param poly The input PolyhedronsSet
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void write(File file, PolyhedronsSet poly) throws IOException {
|
||||
// get the vertices and faces
|
||||
MeshBuilder meshBuilder = new MeshBuilder(poly.getTolerance());
|
||||
poly.getTree(true).visit(meshBuilder);
|
||||
|
||||
// write them to the file
|
||||
try (Writer writer = Files.newBufferedWriter(file.toPath())) {
|
||||
writer.write("# Generated by " + OBJWriter.class.getName() + " on " + new Date() + "\n");
|
||||
writeVertices(writer, meshBuilder.getVertices());
|
||||
writeFaces(writer, meshBuilder.getFaces());
|
||||
}
|
||||
}
|
||||
|
||||
/** Writes the given list of vertices to the file in the OBJ format.
|
||||
* @param writer
|
||||
* @param vertices
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void writeVertices(Writer writer, List<Cartesian3D> vertices) throws IOException {
|
||||
DecimalFormat df = new DecimalFormat("0.######");
|
||||
|
||||
for (Cartesian3D v : vertices) {
|
||||
writer.write("v ");
|
||||
writer.write(df.format(v.getX()));
|
||||
writer.write(" ");
|
||||
writer.write(df.format(v.getY()));
|
||||
writer.write(" ");
|
||||
writer.write(df.format(v.getZ()));
|
||||
writer.write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/** Writes the given list of face vertex indices to the file in the OBJ format. The indices
|
||||
* are expected to be 0-based and are converted to the 1-based format used by OBJ.
|
||||
* @param writer
|
||||
* @param faces
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void writeFaces(Writer writer, List<int[]> faces) throws IOException {
|
||||
for (int[] face : faces) {
|
||||
writer.write("f ");
|
||||
for (int idx : face) {
|
||||
writer.write(String.valueOf(idx + 1)); // obj indices are 1-based
|
||||
writer.write(" ");
|
||||
}
|
||||
writer.write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/** Class used to impose a strict sorting on 3D vertices.
|
||||
* If all of the components of two vertices are within tolerance of each
|
||||
* other, then the vertices are considered equal. This helps to avoid
|
||||
* writing duplicate vertices in the OBJ output.
|
||||
*/
|
||||
private static class VertexComparator implements Comparator<Cartesian3D> {
|
||||
|
||||
/** Geometric tolerance value */
|
||||
private double tolerance;
|
||||
|
||||
/** Creates a new instance with the given tolerance value.
|
||||
* @param tolerance
|
||||
*/
|
||||
public VertexComparator(double tolerance) {
|
||||
this.tolerance = tolerance;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int compare(Cartesian3D a, Cartesian3D b) {
|
||||
int result = compareDoubles(a.getX(), b.getX());
|
||||
if (result == 0) {
|
||||
result = compareDoubles(a.getY(), b.getY());
|
||||
if (result == 0) {
|
||||
result = compareDoubles(a.getZ(), b.getZ());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Helper method to compare two double values using the
|
||||
* configured tolerance value. If the values are within
|
||||
* tolerance of each other, then they are considered equal.
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
private int compareDoubles(double a, double b) {
|
||||
double diff = a - b;
|
||||
if (diff < -tolerance) {
|
||||
return -1;
|
||||
}
|
||||
else if (diff > tolerance) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Class for converting a 3D BSPTree into a list of vertices
|
||||
* and face vertex indices.
|
||||
*/
|
||||
private static class MeshBuilder implements BSPTreeVisitor<Euclidean3D> {
|
||||
|
||||
/** Geometric tolerance */
|
||||
private final double tolerance;
|
||||
|
||||
/** Map of vertices to their index in the vertices list */
|
||||
private Map<Cartesian3D, Integer> vertexIndexMap;
|
||||
|
||||
/** List of unique vertices in the BSPTree boundary */
|
||||
private List<Cartesian3D> vertices;
|
||||
|
||||
/**
|
||||
* List of face vertex indices. Each face will have 3 indices. Indices
|
||||
* are 0-based.
|
||||
* */
|
||||
private List<int[]> faces;
|
||||
|
||||
/** Creates a new instance with the given tolerance.
|
||||
* @param tolerance
|
||||
*/
|
||||
public MeshBuilder(double tolerance) {
|
||||
this.tolerance = tolerance;
|
||||
this.vertexIndexMap = new TreeMap<>(new VertexComparator(tolerance));
|
||||
this.vertices = new ArrayList<>();
|
||||
this.faces = new ArrayList<>();
|
||||
}
|
||||
|
||||
/** Returns the list of unique vertices found in the BSPTree.
|
||||
* @return
|
||||
*/
|
||||
public List<Cartesian3D> getVertices() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
/** Returns the list of 0-based face vertex indices for the BSPTree. Each face is
|
||||
* a triangle with 3 indices.
|
||||
* @return
|
||||
*/
|
||||
public List<int[]> getFaces() {
|
||||
return faces;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Order visitOrder(BSPTree<Euclidean3D> node) {
|
||||
return Order.SUB_MINUS_PLUS;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void visitInternalNode(BSPTree<Euclidean3D> node) {
|
||||
BoundaryAttribute<Euclidean3D> attr = (BoundaryAttribute<Euclidean3D>) node.getAttribute();
|
||||
|
||||
if (attr.getPlusOutside() != null) {
|
||||
addBoundary((SubPlane) attr.getPlusOutside());
|
||||
}
|
||||
else if (attr.getPlusInside() != null) {
|
||||
addBoundary((SubPlane) attr.getPlusInside());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void visitLeafNode(BSPTree<Euclidean3D> node) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** Adds the region boundary defined by the given {@link SubPlane}
|
||||
* to the mesh.
|
||||
* @param subplane
|
||||
*/
|
||||
private void addBoundary(SubPlane subplane) {
|
||||
Plane plane = (Plane) subplane.getHyperplane();
|
||||
PolygonsSet poly = (PolygonsSet) subplane.getRemainingRegion();
|
||||
|
||||
TriangleExtractor triExtractor = new TriangleExtractor(tolerance);
|
||||
poly.getTree(true).visit(triExtractor);
|
||||
|
||||
Cartesian3D v1, v2, v3;
|
||||
for (Cartesian2D[] tri : triExtractor.getTriangles()) {
|
||||
v1 = plane.toSpace(tri[0]);
|
||||
v2 = plane.toSpace(tri[1]);
|
||||
v3 = plane.toSpace(tri[2]);
|
||||
|
||||
faces.add(new int[] {
|
||||
getVertexIndex(v1),
|
||||
getVertexIndex(v2),
|
||||
getVertexIndex(v3)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the 0-based index of the given vertex in the <code>vertices</code>
|
||||
* list. If the vertex has not been encountered before, it is added
|
||||
* to the list.
|
||||
* @param vertex
|
||||
* @return
|
||||
*/
|
||||
private int getVertexIndex(Cartesian3D vertex) {
|
||||
Integer idx = vertexIndexMap.get(vertex);
|
||||
if (idx == null) {
|
||||
idx = vertices.size();
|
||||
|
||||
vertices.add(vertex);
|
||||
vertexIndexMap.put(vertex, idx);
|
||||
}
|
||||
return idx.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
/** Visitor for extracting a collection of triangles from a 2D BSPTree.
|
||||
*/
|
||||
private static class TriangleExtractor implements BSPTreeVisitor<Euclidean2D> {
|
||||
|
||||
/** Geometric tolerance */
|
||||
private double tolerance;
|
||||
|
||||
/** List of extracted triangles */
|
||||
private List<Cartesian2D[]> triangles = new ArrayList<>();
|
||||
|
||||
/** Creates a new instance with the given geometric tolerance.
|
||||
* @param tolerance
|
||||
*/
|
||||
public TriangleExtractor(double tolerance) {
|
||||
this.tolerance = tolerance;
|
||||
}
|
||||
|
||||
/** Returns the list of extracted triangles.
|
||||
* @return
|
||||
*/
|
||||
public List<Cartesian2D[]> getTriangles() {
|
||||
return triangles;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Order visitOrder(BSPTree<Euclidean2D> node) {
|
||||
return Order.SUB_MINUS_PLUS;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void visitInternalNode(BSPTree<Euclidean2D> node) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void visitLeafNode(BSPTree<Euclidean2D> node) {
|
||||
if ((Boolean) node.getAttribute()) {
|
||||
PolygonsSet convexPoly = new PolygonsSet(node.pruneAroundConvexCell(Boolean.TRUE,
|
||||
Boolean.FALSE, null), tolerance);
|
||||
|
||||
for (Cartesian2D[] loop : convexPoly.getVertices()) {
|
||||
if (loop.length > 0 && loop[0] != null) { // skip unclosed loops
|
||||
addTriangles(loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Splits the 2D convex area defined by the given vertices into
|
||||
* triangles and adds them to the internal list.
|
||||
* @param vertices
|
||||
*/
|
||||
private void addTriangles(Cartesian2D[] vertices) {
|
||||
// use a triangle fan to add the convex region
|
||||
for (int i=2; i<vertices.length; ++i) {
|
||||
triangles.add(new Cartesian2D[] { vertices[0], vertices[i-1], vertices[i] });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue