You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2018/05/22 14:18:37 UTC
[commons-geometry] branch master updated: GEOMETRY-2: Cleaning up
API to remove necessity of internal casting of Points and Vectors;
creating separate Point and Vector types to better reflect the mathematical
domain
This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-geometry.git
The following commit(s) were added to refs/heads/master by this push:
new 09cc0fc GEOMETRY-2: Cleaning up API to remove necessity of internal casting of Points and Vectors; creating separate Point and Vector types to better reflect the mathematical domain
new 47bfec9 Merge branch 'GEOMETRY-2__matt'
09cc0fc is described below
commit 09cc0fc375464ac4839e6cbc1444b738abbf1c28
Author: Matt Juntunen <ma...@hotmail.com>
AuthorDate: Mon May 21 00:38:40 2018 -0400
GEOMETRY-2: Cleaning up API to remove necessity of internal casting of Points and Vectors; creating separate Point and Vector types to better reflect the mathematical domain
---
.../apache/commons/geometry/core/AffinePoint.java | 45 +
.../org/apache/commons/geometry/core/Geometry.java | 10 +-
.../org/apache/commons/geometry/core/Point.java | 37 +-
.../geometry/core/{Space.java => Spatial.java} | 26 +-
.../org/apache/commons/geometry/core/Vector.java | 104 +-
.../geometry/core/partitioning/AbstractRegion.java | 158 +-
.../core/partitioning/AbstractSubHyperplane.java | 70 +-
.../geometry/core/partitioning/BSPTree.java | 107 +-
.../geometry/core/partitioning/BSPTreeVisitor.java | 12 +-
.../core/partitioning/BoundaryAttribute.java | 27 +-
.../core/partitioning/BoundaryBuilder.java | 28 +-
.../core/partitioning/BoundaryProjection.java | 18 +-
.../core/partitioning/BoundaryProjector.java | 59 +-
.../core/partitioning/BoundarySizeVisitor.java | 16 +-
.../core/partitioning/Characterization.java | 42 +-
.../geometry/core/partitioning/Embedding.java | 15 +-
.../geometry/core/partitioning/Hyperplane.java | 19 +-
.../geometry/core/partitioning/InsideFinder.java | 16 +-
.../geometry/core/partitioning/NodesSet.java | 18 +-
.../commons/geometry/core/partitioning/Region.java | 25 +-
.../geometry/core/partitioning/RegionFactory.java | 123 +-
.../geometry/core/partitioning/SubHyperplane.java | 16 +-
.../geometry/core/partitioning/Transform.java | 13 +-
.../geometry/core/partitioning/TreeBuilder.java | 17 +-
.../geometry/core/partitioning/TreeDumper.java | 21 +-
.../geometry/core/partitioning/TreePrinter.java | 26 +-
.../commons/geometry/enclosing/Encloser.java | 5 +-
.../commons/geometry/enclosing/EnclosingBall.java | 3 +-
.../geometry/enclosing/SupportBallGenerator.java | 5 +-
.../commons/geometry/enclosing/WelzlEncloser.java | 27 +-
.../threed/enclosing/SphereGenerator.java | 28 +-
.../euclidean/twod/enclosing/DiskGenerator.java | 21 +-
.../geometry/enclosing/WelzlEncloser2DTest.java | 59 +-
.../geometry/enclosing/WelzlEncloser3DTest.java | 121 +-
.../threed/enclosing/SphereGeneratorTest.java | 115 +-
.../twod/enclosing/DiskGeneratorTest.java | 69 +-
.../commons/geometry/euclidean/EuclideanPoint.java | 43 +
.../{twod/Vector2D.java => EuclideanVector.java} | 26 +-
.../geometry/euclidean/oned/Cartesian1D.java | 349 +---
.../geometry/euclidean/oned/Euclidean1D.java | 80 -
.../geometry/euclidean/oned/IntervalsSet.java | 101 +-
.../geometry/euclidean/oned/OrientedPoint.java | 28 +-
.../commons/geometry/euclidean/oned/Point1D.java | 267 +++
.../geometry/euclidean/oned/SubOrientedPoint.java | 18 +-
.../commons/geometry/euclidean/oned/Vector1D.java | 305 +++-
.../{oned/Vector1D.java => package-info.java} | 20 +-
.../geometry/euclidean/threed/Cartesian3D.java | 583 +------
.../geometry/euclidean/threed/Euclidean3D.java | 75 -
.../commons/geometry/euclidean/threed/Line.java | 95 +-
.../euclidean/threed/OutlineExtractor.java | 76 +-
.../commons/geometry/euclidean/threed/Plane.java | 144 +-
.../commons/geometry/euclidean/threed/Point3D.java | 291 ++++
.../geometry/euclidean/threed/PolyhedronsSet.java | 191 ++-
.../geometry/euclidean/threed/Rotation.java | 150 +-
.../geometry/euclidean/threed/RotationOrder.java | 38 +-
.../commons/geometry/euclidean/threed/Segment.java | 10 +-
.../commons/geometry/euclidean/threed/SubLine.java | 23 +-
.../geometry/euclidean/threed/SubPlane.java | 43 +-
.../geometry/euclidean/threed/Vector3D.java | 526 +++++-
.../geometry/euclidean/twod/Cartesian2D.java | 459 +-----
.../geometry/euclidean/twod/Euclidean2D.java | 75 -
.../commons/geometry/euclidean/twod/Line.java | 136 +-
.../geometry/euclidean/twod/NestedLoops.java | 27 +-
.../commons/geometry/euclidean/twod/Point2D.java | 276 ++++
.../geometry/euclidean/twod/PolygonsSet.java | 166 +-
.../commons/geometry/euclidean/twod/Segment.java | 22 +-
.../commons/geometry/euclidean/twod/SubLine.java | 56 +-
.../commons/geometry/euclidean/twod/Vector2D.java | 433 ++++-
.../core/partitioning/CharacterizationTest.java | 190 ++-
.../geometry/euclidean/EuclideanTestUtils.java | 76 +-
.../geometry/euclidean/oned/Cartesian1DTest.java | 359 +---
.../geometry/euclidean/oned/IntervalsSetTest.java | 128 +-
.../geometry/euclidean/oned/OrientedPointTest.java | 96 +-
.../geometry/euclidean/oned/Point1DTest.java | 262 +++
.../euclidean/oned/SubOrientedPointTest.java | 38 +-
.../geometry/euclidean/oned/Vector1DTest.java | 370 +++++
.../geometry/euclidean/threed/Cartesian3DTest.java | 83 +
.../geometry/euclidean/threed/Euclidean3DTest.java | 44 -
.../geometry/euclidean/threed/LineTest.java | 76 +-
.../geometry/euclidean/threed/OBJWriter.java | 51 +-
.../geometry/euclidean/threed/PLYParser.java | 8 +-
.../geometry/euclidean/threed/PlaneTest.java | 88 +-
.../geometry/euclidean/threed/Point3DTest.java | 287 ++++
.../euclidean/threed/PolyhedronsSetTest.java | 980 +++++------
.../geometry/euclidean/threed/RotationTest.java | 248 +--
.../geometry/euclidean/threed/SubLineTest.java | 68 +-
.../geometry/euclidean/threed/Vector3DTest.java | 862 +++++++---
.../geometry/euclidean/twod/Cartesian2DTest.java | 242 +--
.../geometry/euclidean/twod/Euclidean2DTest.java | 44 -
.../commons/geometry/euclidean/twod/LineTest.java | 70 +-
.../geometry/euclidean/twod/NestedLoopsTest.java | 16 +-
.../geometry/euclidean/twod/Point2DTest.java | 262 +++
.../geometry/euclidean/twod/PolygonsSetTest.java | 1716 ++++++++++----------
.../geometry/euclidean/twod/SegmentTest.java | 12 +-
.../geometry/euclidean/twod/SubLineTest.java | 68 +-
.../geometry/euclidean/twod/Vector2DTest.java | 526 ++++++
.../twod/hull/AbstractConvexHullGenerator2D.java | 10 +-
.../euclidean/twod/hull/AklToussaintHeuristic.java | 44 +-
.../geometry/euclidean/twod/hull/ConvexHull2D.java | 38 +-
.../euclidean/twod/hull/ConvexHullGenerator2D.java | 7 +-
.../euclidean/twod/hull/MonotoneChain.java | 28 +-
.../apache/commons/geometry/hull/ConvexHull.java | 5 +-
.../commons/geometry/hull/ConvexHullGenerator.java | 5 +-
.../twod/hull/AklToussaintHeuristicTest.java | 4 +-
.../hull/ConvexHullGenerator2DAbstractTest.java | 232 +--
.../euclidean/twod/hull/MonotoneChainTest.java | 22 +-
commons-geometry-spherical/pom.xml | 16 +
.../geometry/spherical/SphericalCoordinates.java | 12 +-
.../commons/geometry/spherical/oned/ArcsSet.java | 95 +-
.../geometry/spherical/oned/LimitAngle.java | 11 +-
.../commons/geometry/spherical/oned/S1Point.java | 34 +-
.../commons/geometry/spherical/oned/Sphere1D.java | 86 -
.../geometry/spherical/oned/SubLimitAngle.java | 12 +-
.../commons/geometry/spherical/twod/Circle.java | 69 +-
.../commons/geometry/spherical/twod/Edge.java | 4 +-
.../geometry/spherical/twod/EdgesBuilder.java | 34 +-
.../spherical/twod/PropertiesComputer.java | 41 +-
.../commons/geometry/spherical/twod/S2Point.java | 50 +-
.../commons/geometry/spherical/twod/Sphere2D.java | 81 -
.../spherical/twod/SphericalPolygonsSet.java | 84 +-
.../commons/geometry/spherical/twod/SubCircle.java | 18 +-
.../spherical/SphericalCoordinatesTest.java | 26 +-
.../geometry/spherical/SphericalTestUtils.java | 19 +-
.../commons/geometry/spherical/oned/ArcTest.java | 79 +
.../geometry/spherical/oned/ArcsSetTest.java | 590 +++++++
.../geometry/spherical/oned/LimitAngleTest.java | 31 +-
.../geometry/spherical/oned/S1PointTest.java | 60 +
.../geometry/spherical/twod/CircleTest.java | 188 +++
.../geometry/spherical/twod/S2PointTest.java | 77 +
.../spherical/twod/SphericalPolygonsSetTest.java | 550 +++++++
.../geometry/spherical/twod/SubCircleTest.java | 138 ++
131 files changed, 10117 insertions(+), 6606 deletions(-)
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/AffinePoint.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/AffinePoint.java
new file mode 100644
index 0000000..80d7b22
--- /dev/null
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/AffinePoint.java
@@ -0,0 +1,45 @@
+/*
+ * 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.geometry.core;
+
+/** Interface that adds affine space operations to the base {@link Point}
+ * interface. Affine spaces consist of points and displacement vectors
+ * representing translations between points. Since this interface extends
+ * {@link Point}, the represented space is both affine and metric.
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Affine_space">Affine space</a>
+ * @see <a href="https://en.wikipedia.org/wiki/Metric_space">Metric space</a>
+ * @see Point
+ *
+ * @param <P> Point implementation type
+ * @param <V> Vector implementation type
+ */
+public interface AffinePoint<P extends AffinePoint<P, V>, V extends Vector<V>> extends Point<P> {
+
+ /** Returns the displacement vector from this point to p.
+ * @param p second point
+ * @return The displacement vector from this point to p.
+ */
+ V subtract(P p);
+
+ /** Returns the point resulting from adding the given displacement
+ * vector to this point.
+ * @param v displacement vector
+ * @return point resulting from displacing this point by v
+ */
+ P add(V v);
+}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Geometry.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Geometry.java
index adef1ab..d74d312 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Geometry.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Geometry.java
@@ -23,10 +23,18 @@ public class Geometry {
/** Alias for {@link Math#PI}, placed here for completeness. */
public static final double PI = Math.PI;
- /** Constant representing {@code 2*pi}.
+ /** Constant value for {@code 2*pi}.
*/
public static final double TWO_PI = 2.0 * Math.PI;
+ /** Constant value for {@code pi / 2}.
+ */
+ public static final double HALF_PI = 0.5 * Math.PI;
+
+ /** Constant value for {@code - pi / 2}.
+ */
+ public static final double MINUS_HALF_PI = - 0.5 * Math.PI;
+
/** Private constructor */
private Geometry() {}
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Point.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Point.java
index 9a9b2f4..191088f 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Point.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Point.java
@@ -16,30 +16,23 @@
*/
package org.apache.commons.geometry.core;
-import java.io.Serializable;
-
-/** This interface represents a generic geometrical point.
- * @param <S> Type of the space.
- * @see Space
- * @see Vector
+/** Interface representing a point in a mathematical space.
+ * Implementations of this interface are sufficient to define a
+ * space since they define both the structure of the points making up
+ * the space and the operations permitted on them. The only mathematical
+ * requirement at this level is that the represented space have a defined
+ * distance metric, meaning an operation that can compute the distance
+ * between two points (ie, the space must be a metric space).
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Metric_space">Metric space</a>
+ *
+ * @param <P> Point implementation type
*/
-public interface Point<S extends Space> extends Serializable {
-
- /** Get the space to which the point belongs.
- * @return containing space
- */
- Space getSpace();
-
- /**
- * Returns true if any coordinate of this point is NaN; false otherwise
- * @return true if any coordinate of this point is NaN; false otherwise
- */
- boolean isNaN();
+public interface Point<P extends Point<P>> extends Spatial {
- /** Compute the distance between the instance and another point.
+ /** Compute the distance between this point and another point.
* @param p second point
- * @return the distance between the instance and p
+ * @return the distance between this point and p
*/
- double distance(Point<S> p);
-
+ double distance(P p);
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Space.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Spatial.java
similarity index 57%
rename from commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Space.java
rename to commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Spatial.java
index a932550..ad72eb7 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Space.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Spatial.java
@@ -18,22 +18,26 @@ package org.apache.commons.geometry.core;
import java.io.Serializable;
-/** This interface represents a generic space, with affine and vectorial counterparts.
- * @see Vector
+/** Interface representing a generic element in a mathematical space.
*/
-public interface Space extends Serializable {
+public interface Spatial extends Serializable {
- /** Get the dimension of the space.
- * @return dimension of the space
+ /** Returns the number of dimensions in the space that this element
+ * belongs to.
+ * @return the number of dimensions in the element's space
*/
int getDimension();
- /** Get the n-1 dimension subspace of this space.
- * @return n-1 dimension sub-space of this space
- * @see #getDimension()
- * @exception UnsupportedOperationException for dimension-1 spaces
- * which do not have sub-spaces
+ /** Returns true if any value in this element is NaN; otherwise
+ * returns false.
+ * @return true if any value in this element is NaN
*/
- Space getSubSpace() throws UnsupportedOperationException;
+ boolean isNaN();
+ /** Returns true if any value in this element is infinite and none
+ * are NaN; otherwise, returns false.
+ * @return true if any value in this element is infinite and none
+ * are NaN
+ */
+ boolean isInfinite();
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Vector.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Vector.java
index e13799c..1d0269d 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Vector.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/Vector.java
@@ -16,41 +16,50 @@
*/
package org.apache.commons.geometry.core;
-import java.text.NumberFormat;
-
-/** This interface represents a generic vector in a vectorial space or a point in an affine space.
- * @param <S> Type of the space.
- * @see Space
- * @see Point
+/** Interface representing a vector in a vector space. The most common
+ * use of this interface is to represent displacement vectors in an affine
+ * space.
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Vector_space">Vector space</a>
+ * @see <a href="https://en.wikipedia.org/wiki/Affine_space">Affine space</a>
+ *
+ * @see AffinePoint
+ *
+ * @param <V> Vector implementation type
*/
-public interface Vector<S extends Space> {
+public interface Vector<V extends Vector<V>> extends Spatial {
- /** Get the space to which the point belongs.
- * @return containing space
+ /** Get the zero (null) vector of the space.
+ * @return zero vector of the space
*/
- Space getSpace();
+ V getZero();
- /** Get the null vector of the vectorial space or origin point of the affine space.
- * @return null vector of the vectorial space or origin point of the affine space
- */
- Vector<S> getZero();
-
- /** Get the L<sub>1</sub> norm for the vector.
+ /** Get the L<sub>1</sub> norm for the vector. This is defined as the
+ * sum of the absolute values of all vector components.
+ *
+ * @see <a href="http://mathworld.wolfram.com/L1-Norm.html">L1 Norm</a>
* @return L<sub>1</sub> norm for the vector
*/
double getNorm1();
- /** Get the L<sub>2</sub> norm for the vector.
+ /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector.
+ * This corresponds to the common notion of vector magnitude or length.
+ * This is defined as the square root of the sum of the squares of all vector components.
+ * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
* @return Euclidean norm for the vector
*/
double getNorm();
- /** Get the square of the norm for the vector.
+ /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
+ * for the vector. This is equal to the sum of the squares of all vector components.
+ * @see #getNorm()
* @return square of the Euclidean norm for the vector
*/
double getNormSq();
- /** Get the L<sub>∞</sub> norm for the vector.
+ /** Get the L<sub>∞</sub> norm for the vector. This is defined as the
+ * maximum of the absolute values of all vector components.
+ * @see <a href="http://mathworld.wolfram.com/L-Infinity-Norm.html">L<sub>∞</sub> Norm</a>
* @return L<sub>∞</sub> norm for the vector
*/
double getNormInf();
@@ -59,102 +68,85 @@ public interface Vector<S extends Space> {
* @param v vector to add
* @return a new vector
*/
- Vector<S> add(Vector<S> v);
+ V add(V v);
/** Add a scaled vector to the instance.
* @param factor scale factor to apply to v before adding it
* @param v vector to add
* @return a new vector
*/
- Vector<S> add(double factor, Vector<S> v);
+ V add(double factor, V v);
/** Subtract a vector from the instance.
* @param v vector to subtract
* @return a new vector
*/
- Vector<S> subtract(Vector<S> v);
+ V subtract(V v);
/** Subtract a scaled vector from the instance.
* @param factor scale factor to apply to v before subtracting it
* @param v vector to subtract
* @return a new vector
*/
- Vector<S> subtract(double factor, Vector<S> v);
+ V subtract(double factor, V v);
- /** Get the opposite of the instance.
- * @return a new vector which is opposite to the instance
+ /** Get the negation of the instance.
+ * @return a new vector which is the negation of the instance
*/
- Vector<S> negate();
+ V negate();
- /** Get a normalized vector aligned with the instance.
+ /** Get a normalized vector aligned with the instance. The returned
+ * vector has a magnitude of 1.
* @return a new normalized vector
* @exception IllegalStateException if the norm is zero
*/
- Vector<S> normalize() throws IllegalStateException;
+ V normalize() throws IllegalStateException;
/** Multiply the instance by a scalar.
* @param a scalar
* @return a new vector
*/
- Vector<S> scalarMultiply(double a);
-
- /**
- * Returns true if any coordinate of this point is NaN; false otherwise
- * @return true if any coordinate of this point is NaN; false otherwise
- */
- boolean isNaN();
-
- /**
- * Returns true if any coordinate of this vector is infinite and none are NaN;
- * false otherwise
- * @return true if any coordinate of this vector is infinite and none are NaN;
- * false otherwise
- */
- boolean isInfinite();
+ V scalarMultiply(double a);
/** Compute the distance between the instance and another vector according to the L<sub>1</sub> norm.
* <p>Calling this method is equivalent to calling:
* <code>q.subtract(p).getNorm1()</code> except that no intermediate
* vector is built</p>
+ * @see #getNorm1()
* @param v second vector
* @return the distance between the instance and p according to the L<sub>1</sub> norm
*/
- double distance1(Vector<S> v);
+ double distance1(V v);
/** Compute the distance between the instance and another vector.
* @param v second vector
* @return the distance between the instance and v
*/
- double distance(Vector<S> v);
+ double distance(V v);
/** Compute the distance between the instance and another vector according to the L<sub>∞</sub> norm.
* <p>Calling this method is equivalent to calling:
* <code>q.subtract(p).getNormInf()</code> except that no intermediate
* vector is built</p>
+ * @see #getNormInf()
* @param v second vector
* @return the distance between the instance and p according to the L<sub>∞</sub> norm
*/
- double distanceInf(Vector<S> v);
+ double distanceInf(V v);
/** Compute the square of the distance between the instance and another vector.
* <p>Calling this method is equivalent to calling:
* <code>q.subtract(p).getNormSq()</code> except that no intermediate
* vector is built</p>
+ * @see #getNormSq()
* @param v second vector
* @return the square of the distance between the instance and p
*/
- double distanceSq(Vector<S> v);
+ double distanceSq(V v);
/** Compute the dot-product of the instance and another vector.
* @param v second vector
- * @return the dot product this.v
+ * @return the dot product this · v
*/
- double dotProduct(Vector<S> v);
-
- /** Get a string representation of this vector.
- * @param format the custom format for components
- * @return a string representation of this vector
- */
- String toString(final NumberFormat format);
-
+ double dotProduct(V v);
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractRegion.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractRegion.java
index bc23114..ff923d6 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractRegion.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractRegion.java
@@ -25,18 +25,16 @@ import java.util.Map;
import java.util.TreeSet;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.Vector;
-/** Abstract class for all regions, independently of geometry type or dimension.
+/** Abstract class for all regions, independent of geometry type or dimension.
- * @param <S> Type of the space.
- * @param <T> Type of the sub-space.
+ * @param <P> Point type defining the space
+ * @param <S> Point type defining the sub-space
*/
-public abstract class AbstractRegion<S extends Space, T extends Space> implements Region<S> {
+public abstract class AbstractRegion<P extends Point<P>, S extends Point<S>> implements Region<P> {
/** Inside/Outside BSP tree. */
- private BSPTree<S> tree;
+ private BSPTree<P> tree;
/** Tolerance below which points are considered to belong to hyperplanes. */
private final double tolerance;
@@ -45,7 +43,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
private double size;
/** Barycenter. */
- private Point<S> barycenter;
+ private P barycenter;
/** Build a region representing the whole space.
* @param tolerance tolerance below which points are considered identical.
@@ -68,7 +66,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* @param tree inside/outside BSP tree representing the region
* @param tolerance tolerance below which points are considered identical.
*/
- protected AbstractRegion(final BSPTree<S> tree, final double tolerance) {
+ protected AbstractRegion(final BSPTree<P> tree, final double tolerance) {
this.tree = tree;
this.tolerance = tolerance;
}
@@ -93,7 +91,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* collection of {@link SubHyperplane SubHyperplane} objects
* @param tolerance tolerance below which points are considered identical.
*/
- protected AbstractRegion(final Collection<SubHyperplane<S>> boundary, final double tolerance) {
+ protected AbstractRegion(final Collection<SubHyperplane<P>> boundary, final double tolerance) {
this.tolerance = tolerance;
@@ -107,10 +105,10 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
// sort the boundary elements in decreasing size order
// (we don't want equal size elements to be removed, so
// we use a trick to fool the TreeSet)
- final TreeSet<SubHyperplane<S>> ordered = new TreeSet<>(new Comparator<SubHyperplane<S>>() {
+ final TreeSet<SubHyperplane<P>> ordered = new TreeSet<>(new Comparator<SubHyperplane<P>>() {
/** {@inheritDoc} */
@Override
- public int compare(final SubHyperplane<S> o1, final SubHyperplane<S> o2) {
+ public int compare(final SubHyperplane<P> o1, final SubHyperplane<P> o2) {
final double size1 = o1.getSize();
final double size2 = o2.getSize();
return (size2 < size1) ? -1 : ((o1 == o2) ? 0 : +1);
@@ -123,22 +121,22 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
insertCuts(tree, ordered);
// set up the inside/outside flags
- tree.visit(new BSPTreeVisitor<S>() {
+ tree.visit(new BSPTreeVisitor<P>() {
/** {@inheritDoc} */
@Override
- public Order visitOrder(final BSPTree<S> node) {
+ public Order visitOrder(final BSPTree<P> node) {
return Order.PLUS_SUB_MINUS;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(final BSPTree<S> node) {
+ public void visitInternalNode(final BSPTree<P> node) {
}
/** {@inheritDoc} */
@Override
- public void visitLeafNode(final BSPTree<S> node) {
+ public void visitLeafNode(final BSPTree<P> node) {
if (node.getParent() == null || node == node.getParent().getMinus()) {
node.setAttribute(Boolean.TRUE);
} else {
@@ -156,7 +154,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* empty region will be built)
* @param tolerance tolerance below which points are considered identical.
*/
- public AbstractRegion(final Hyperplane<S>[] hyperplanes, final double tolerance) {
+ public AbstractRegion(final Hyperplane<P>[] hyperplanes, final double tolerance) {
this.tolerance = tolerance;
if ((hyperplanes == null) || (hyperplanes.length == 0)) {
tree = new BSPTree<>(Boolean.FALSE);
@@ -166,9 +164,9 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
tree = hyperplanes[0].wholeSpace().getTree(false);
// chop off parts of the space
- BSPTree<S> node = tree;
+ BSPTree<P> node = tree;
node.setAttribute(Boolean.TRUE);
- for (final Hyperplane<S> hyperplane : hyperplanes) {
+ for (final Hyperplane<P> hyperplane : hyperplanes) {
if (node.insertCut(hyperplane)) {
node.setAttribute(null);
node.getPlus().setAttribute(Boolean.FALSE);
@@ -183,7 +181,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public abstract AbstractRegion<S, T> buildNew(BSPTree<S> newTree);
+ public abstract AbstractRegion<P, S> buildNew(BSPTree<P> newTree);
/** Get the tolerance below which points are considered to belong to hyperplanes.
* @return tolerance below which points are considered to belong to hyperplanes
@@ -198,12 +196,12 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* @param boundary collection of edges belonging to the cell defined
* by the node
*/
- private void insertCuts(final BSPTree<S> node, final Collection<SubHyperplane<S>> boundary) {
+ private void insertCuts(final BSPTree<P> node, final Collection<SubHyperplane<P>> boundary) {
- final Iterator<SubHyperplane<S>> iterator = boundary.iterator();
+ final Iterator<SubHyperplane<P>> iterator = boundary.iterator();
// build the current level
- Hyperplane<S> inserted = null;
+ Hyperplane<P> inserted = null;
while ((inserted == null) && iterator.hasNext()) {
inserted = iterator.next().getHyperplane();
if (!node.insertCut(inserted.copySelf())) {
@@ -216,11 +214,11 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
}
// distribute the remaining edges in the two sub-trees
- final ArrayList<SubHyperplane<S>> plusList = new ArrayList<>();
- final ArrayList<SubHyperplane<S>> minusList = new ArrayList<>();
+ final ArrayList<SubHyperplane<P>> plusList = new ArrayList<>();
+ final ArrayList<SubHyperplane<P>> minusList = new ArrayList<>();
while (iterator.hasNext()) {
- final SubHyperplane<S> other = iterator.next();
- final SubHyperplane.SplitSubHyperplane<S> split = other.split(inserted);
+ final SubHyperplane<P> other = iterator.next();
+ final SubHyperplane.SplitSubHyperplane<P> split = other.split(inserted);
switch (split.getSide()) {
case PLUS:
plusList.add(other);
@@ -245,7 +243,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public AbstractRegion<S, T> copySelf() {
+ public AbstractRegion<P, S> copySelf() {
return buildNew(tree.copySelf());
}
@@ -257,7 +255,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public boolean isEmpty(final BSPTree<S> node) {
+ public boolean isEmpty(final BSPTree<P> node) {
// we use a recursive function rather than the BSPTreeVisitor
// interface because we can stop visiting the tree as soon as we
@@ -281,7 +279,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public boolean isFull(final BSPTree<S> node) {
+ public boolean isFull(final BSPTree<P> node) {
// we use a recursive function rather than the BSPTreeVisitor
// interface because we can stop visiting the tree as soon as we
@@ -299,32 +297,22 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public boolean contains(final Region<S> region) {
- return new RegionFactory<S>().difference(region, this).isEmpty();
+ public boolean contains(final Region<P> region) {
+ return new RegionFactory<P>().difference(region, this).isEmpty();
}
/** {@inheritDoc}
*/
@Override
- public BoundaryProjection<S> projectToBoundary(final Point<S> point) {
- final BoundaryProjector<S, T> projector = new BoundaryProjector<>(point);
+ public BoundaryProjection<P> projectToBoundary(final P point) {
+ final BoundaryProjector<P, S> projector = new BoundaryProjector<>(point);
getTree(true).visit(projector);
return projector.getProjection();
}
- /** Check a point with respect to the region.
- * @param point point to check
- * @return a code representing the point status: either {@link
- * Region.Location#INSIDE}, {@link Region.Location#OUTSIDE} or
- * {@link Region.Location#BOUNDARY}
- */
-// public Location checkPoint(final Vector<S> point) {
-// return checkPoint((Point<S>) point);
-// }
-
/** {@inheritDoc} */
@Override
- public Location checkPoint(final Point<S> point) {
+ public Location checkPoint(final P point) {
return checkPoint(tree, point);
}
@@ -335,19 +323,8 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* Region.Location#INSIDE INSIDE}, {@link Region.Location#OUTSIDE
* OUTSIDE} or {@link Region.Location#BOUNDARY BOUNDARY}
*/
- protected Location checkPoint(final BSPTree<S> node, final Vector<S> point) {
- return checkPoint(node, (Point<S>) point);
- }
-
- /** Check a point with respect to the region starting at a given node.
- * @param node root node of the region
- * @param point point to check
- * @return a code representing the point status: either {@link
- * Region.Location#INSIDE INSIDE}, {@link Region.Location#OUTSIDE
- * OUTSIDE} or {@link Region.Location#BOUNDARY BOUNDARY}
- */
- protected Location checkPoint(final BSPTree<S> node, final Point<S> point) {
- final BSPTree<S> cell = node.getCell(point, tolerance);
+ protected Location checkPoint(final BSPTree<P> node, final P point) {
+ final BSPTree<P> cell = node.getCell(point, tolerance);
if (cell.getCut() == null) {
// the point is in the interior of a cell, just check the attribute
return ((Boolean) cell.getAttribute()) ? Location.INSIDE : Location.OUTSIDE;
@@ -362,10 +339,10 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public BSPTree<S> getTree(final boolean includeBoundaryAttributes) {
+ public BSPTree<P> getTree(final boolean includeBoundaryAttributes) {
if (includeBoundaryAttributes && (tree.getCut() != null) && (tree.getAttribute() == null)) {
// compute the boundary attributes
- tree.visit(new BoundaryBuilder<S>());
+ tree.visit(new BoundaryBuilder<P>());
}
return tree;
}
@@ -373,7 +350,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
public double getBoundarySize() {
- final BoundarySizeVisitor<S> visitor = new BoundarySizeVisitor<>();
+ final BoundarySizeVisitor<P> visitor = new BoundarySizeVisitor<>();
getTree(true).visit(visitor);
return visitor.getSize();
}
@@ -396,7 +373,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public Point<S> getBarycenter() {
+ public P getBarycenter() {
if (barycenter == null) {
computeGeometricalProperties();
}
@@ -406,14 +383,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** Set the barycenter of the instance.
* @param barycenter barycenter of the instance
*/
- protected void setBarycenter(final Vector<S> barycenter) {
- setBarycenter((Point<S>) barycenter);
- }
-
- /** Set the barycenter of the instance.
- * @param barycenter barycenter of the instance
- */
- protected void setBarycenter(final Point<S> barycenter) {
+ protected void setBarycenter(final P barycenter) {
this.barycenter = barycenter;
}
@@ -424,7 +394,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
/** {@inheritDoc} */
@Override
- public SubHyperplane<S> intersection(final SubHyperplane<S> sub) {
+ public SubHyperplane<P> intersection(final SubHyperplane<P> sub) {
return recurseIntersection(tree, sub);
}
@@ -434,19 +404,19 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* @param sub sub-hyperplane traversing the region
* @return filtered sub-hyperplane
*/
- private SubHyperplane<S> recurseIntersection(final BSPTree<S> node, final SubHyperplane<S> sub) {
+ private SubHyperplane<P> recurseIntersection(final BSPTree<P> node, final SubHyperplane<P> sub) {
if (node.getCut() == null) {
return (Boolean) node.getAttribute() ? sub.copySelf() : null;
}
- final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
- final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
+ final Hyperplane<P> hyperplane = node.getCut().getHyperplane();
+ final SubHyperplane.SplitSubHyperplane<P> split = sub.split(hyperplane);
if (split.getPlus() != null) {
if (split.getMinus() != null) {
// both sides
- final SubHyperplane<S> plus = recurseIntersection(node.getPlus(), split.getPlus());
- final SubHyperplane<S> minus = recurseIntersection(node.getMinus(), split.getMinus());
+ final SubHyperplane<P> plus = recurseIntersection(node.getPlus(), split.getPlus());
+ final SubHyperplane<P> minus = recurseIntersection(node.getMinus(), split.getMinus());
if (plus == null) {
return minus;
} else if (minus == null) {
@@ -479,21 +449,21 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* @return a new region, resulting from the application of the
* transform to the instance
*/
- public AbstractRegion<S, T> applyTransform(final Transform<S, T> transform) {
+ public AbstractRegion<P, S> applyTransform(final Transform<P, S> transform) {
// transform the tree, except for boundary attribute splitters
- final Map<BSPTree<S>, BSPTree<S>> map = new HashMap<>();
- final BSPTree<S> transformedTree = recurseTransform(getTree(false), transform, map);
+ final Map<BSPTree<P>, BSPTree<P>> map = new HashMap<>();
+ final BSPTree<P> transformedTree = recurseTransform(getTree(false), transform, map);
// set up the boundary attributes splitters
- for (final Map.Entry<BSPTree<S>, BSPTree<S>> entry : map.entrySet()) {
+ for (final Map.Entry<BSPTree<P>, BSPTree<P>> entry : map.entrySet()) {
if (entry.getKey().getCut() != null) {
@SuppressWarnings("unchecked")
- BoundaryAttribute<S> original = (BoundaryAttribute<S>) entry.getKey().getAttribute();
+ BoundaryAttribute<P> original = (BoundaryAttribute<P>) entry.getKey().getAttribute();
if (original != null) {
@SuppressWarnings("unchecked")
- BoundaryAttribute<S> transformed = (BoundaryAttribute<S>) entry.getValue().getAttribute();
- for (final BSPTree<S> splitter : original.getSplitters()) {
+ BoundaryAttribute<P> transformed = (BoundaryAttribute<P>) entry.getValue().getAttribute();
+ for (final BSPTree<P> splitter : original.getSplitters()) {
transformed.getSplitters().add(map.get(splitter));
}
}
@@ -511,24 +481,24 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* @return a new tree
*/
@SuppressWarnings("unchecked")
- private BSPTree<S> recurseTransform(final BSPTree<S> node, final Transform<S, T> transform,
- final Map<BSPTree<S>, BSPTree<S>> map) {
+ private BSPTree<P> recurseTransform(final BSPTree<P> node, final Transform<P, S> transform,
+ final Map<BSPTree<P>, BSPTree<P>> map) {
- final BSPTree<S> transformedNode;
+ final BSPTree<P> transformedNode;
if (node.getCut() == null) {
transformedNode = new BSPTree<>(node.getAttribute());
} else {
- final SubHyperplane<S> sub = node.getCut();
- final SubHyperplane<S> tSub = ((AbstractSubHyperplane<S, T>) sub).applyTransform(transform);
- BoundaryAttribute<S> attribute = (BoundaryAttribute<S>) node.getAttribute();
+ final SubHyperplane<P> sub = node.getCut();
+ final SubHyperplane<P> tSub = ((AbstractSubHyperplane<P, S>) sub).applyTransform(transform);
+ BoundaryAttribute<P> attribute = (BoundaryAttribute<P>) node.getAttribute();
if (attribute != null) {
- final SubHyperplane<S> tPO = (attribute.getPlusOutside() == null) ?
- null : ((AbstractSubHyperplane<S, T>) attribute.getPlusOutside()).applyTransform(transform);
- final SubHyperplane<S> tPI = (attribute.getPlusInside() == null) ?
- null : ((AbstractSubHyperplane<S, T>) attribute.getPlusInside()).applyTransform(transform);
+ final SubHyperplane<P> tPO = (attribute.getPlusOutside() == null) ?
+ null : ((AbstractSubHyperplane<P, S>) attribute.getPlusOutside()).applyTransform(transform);
+ final SubHyperplane<P> tPI = (attribute.getPlusInside() == null) ?
+ null : ((AbstractSubHyperplane<P, S>) attribute.getPlusInside()).applyTransform(transform);
// we start with an empty list of splitters, it will be filled in out of recursion
- attribute = new BoundaryAttribute<>(tPO, tPI, new NodesSet<S>());
+ attribute = new BoundaryAttribute<>(tPO, tPI, new NodesSet<P>());
}
transformedNode = new BSPTree<>(tSub,
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractSubHyperplane.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractSubHyperplane.java
index 08d885e..6c07722 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractSubHyperplane.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractSubHyperplane.java
@@ -19,7 +19,7 @@ package org.apache.commons.geometry.core.partitioning;
import java.util.HashMap;
import java.util.Map;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** This class implements the dimension-independent parts of {@link SubHyperplane}.
@@ -30,24 +30,24 @@ import org.apache.commons.geometry.core.Space;
* hyperplane with the convex region which it splits, the chopping
* hyperplanes are the cut hyperplanes closer to the tree root.</p>
- * @param <S> Type of the embedding space.
- * @param <T> Type of the embedded sub-space.
+ * @param <P> Point type defining the space
+ * @param <S> Point type defining the sub-space
*/
-public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
- implements SubHyperplane<S> {
+public abstract class AbstractSubHyperplane<P extends Point<P>, S extends Point<S>>
+ implements SubHyperplane<P> {
/** Underlying hyperplane. */
- private final Hyperplane<S> hyperplane;
+ private final Hyperplane<P> hyperplane;
/** Remaining region of the hyperplane. */
- private final Region<T> remainingRegion;
+ private final Region<S> remainingRegion;
/** Build a sub-hyperplane from an hyperplane and a region.
* @param hyperplane underlying hyperplane
* @param remainingRegion remaining region of the hyperplane
*/
- protected AbstractSubHyperplane(final Hyperplane<S> hyperplane,
- final Region<T> remainingRegion) {
+ protected AbstractSubHyperplane(final Hyperplane<P> hyperplane,
+ final Region<S> remainingRegion) {
this.hyperplane = hyperplane;
this.remainingRegion = remainingRegion;
}
@@ -57,12 +57,12 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
* @param remaining remaining region of the hyperplane
* @return a new sub-hyperplane
*/
- protected abstract AbstractSubHyperplane<S, T> buildNew(final Hyperplane<S> hyper,
- final Region<T> remaining);
+ protected abstract AbstractSubHyperplane<P, S> buildNew(final Hyperplane<P> hyper,
+ final Region<S> remaining);
/** {@inheritDoc} */
@Override
- public AbstractSubHyperplane<S, T> copySelf() {
+ public AbstractSubHyperplane<P, S> copySelf() {
return buildNew(hyperplane.copySelf(), remainingRegion);
}
@@ -70,7 +70,7 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
* @return underlying hyperplane
*/
@Override
- public Hyperplane<S> getHyperplane() {
+ public Hyperplane<P> getHyperplane() {
return hyperplane;
}
@@ -81,7 +81,7 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
* corresponding region is a convex 2D polygon.</p>
* @return remaining region of the hyperplane
*/
- public Region<T> getRemainingRegion() {
+ public Region<S> getRemainingRegion() {
return remainingRegion;
}
@@ -93,11 +93,11 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
/** {@inheritDoc} */
@Override
- public AbstractSubHyperplane<S, T> reunite(final SubHyperplane<S> other) {
+ public AbstractSubHyperplane<P, S> reunite(final SubHyperplane<P> other) {
@SuppressWarnings("unchecked")
- AbstractSubHyperplane<S, T> o = (AbstractSubHyperplane<S, T>) other;
+ AbstractSubHyperplane<P, S> o = (AbstractSubHyperplane<P, S>) other;
return buildNew(hyperplane,
- new RegionFactory<T>().union(remainingRegion, o.remainingRegion));
+ new RegionFactory<S>().union(remainingRegion, o.remainingRegion));
}
/** Apply a transform to the instance.
@@ -110,23 +110,23 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
* @param transform D-dimension transform to apply
* @return the transformed instance
*/
- public AbstractSubHyperplane<S, T> applyTransform(final Transform<S, T> transform) {
- final Hyperplane<S> tHyperplane = transform.apply(hyperplane);
+ public AbstractSubHyperplane<P, S> applyTransform(final Transform<P, S> transform) {
+ final Hyperplane<P> tHyperplane = transform.apply(hyperplane);
// transform the tree, except for boundary attribute splitters
- final Map<BSPTree<T>, BSPTree<T>> map = new HashMap<>();
- final BSPTree<T> tTree =
+ final Map<BSPTree<S>, BSPTree<S>> map = new HashMap<>();
+ final BSPTree<S> tTree =
recurseTransform(remainingRegion.getTree(false), tHyperplane, transform, map);
// set up the boundary attributes splitters
- for (final Map.Entry<BSPTree<T>, BSPTree<T>> entry : map.entrySet()) {
+ for (final Map.Entry<BSPTree<S>, BSPTree<S>> entry : map.entrySet()) {
if (entry.getKey().getCut() != null) {
@SuppressWarnings("unchecked")
- BoundaryAttribute<T> original = (BoundaryAttribute<T>) entry.getKey().getAttribute();
+ BoundaryAttribute<S> original = (BoundaryAttribute<S>) entry.getKey().getAttribute();
if (original != null) {
@SuppressWarnings("unchecked")
- BoundaryAttribute<T> transformed = (BoundaryAttribute<T>) entry.getValue().getAttribute();
- for (final BSPTree<T> splitter : original.getSplitters()) {
+ BoundaryAttribute<S> transformed = (BoundaryAttribute<S>) entry.getValue().getAttribute();
+ for (final BSPTree<S> splitter : original.getSplitters()) {
transformed.getSplitters().add(map.get(splitter));
}
}
@@ -144,25 +144,25 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
* @param map transformed nodes map
* @return a new tree
*/
- private BSPTree<T> recurseTransform(final BSPTree<T> node,
- final Hyperplane<S> transformed,
- final Transform<S, T> transform,
- final Map<BSPTree<T>, BSPTree<T>> map) {
+ private BSPTree<S> recurseTransform(final BSPTree<S> node,
+ final Hyperplane<P> transformed,
+ final Transform<P, S> transform,
+ final Map<BSPTree<S>, BSPTree<S>> map) {
- final BSPTree<T> transformedNode;
+ final BSPTree<S> transformedNode;
if (node.getCut() == null) {
transformedNode = new BSPTree<>(node.getAttribute());
} else {
@SuppressWarnings("unchecked")
- BoundaryAttribute<T> attribute = (BoundaryAttribute<T>) node.getAttribute();
+ BoundaryAttribute<S> attribute = (BoundaryAttribute<S>) node.getAttribute();
if (attribute != null) {
- final SubHyperplane<T> tPO = (attribute.getPlusOutside() == null) ?
+ final SubHyperplane<S> tPO = (attribute.getPlusOutside() == null) ?
null : transform.apply(attribute.getPlusOutside(), hyperplane, transformed);
- final SubHyperplane<T> tPI = (attribute.getPlusInside() == null) ?
+ final SubHyperplane<S> tPI = (attribute.getPlusInside() == null) ?
null : transform.apply(attribute.getPlusInside(), hyperplane, transformed);
// we start with an empty list of splitters, it will be filled in out of recursion
- attribute = new BoundaryAttribute<>(tPO, tPI, new NodesSet<T>());
+ attribute = new BoundaryAttribute<>(tPO, tPI, new NodesSet<S>());
}
transformedNode = new BSPTree<>(transform.apply(node.getCut(), hyperplane, transformed),
@@ -178,7 +178,7 @@ public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
/** {@inheritDoc} */
@Override
- public abstract SplitSubHyperplane<S> split(Hyperplane<S> hyper);
+ public abstract SplitSubHyperplane<P> split(Hyperplane<P> hyper);
/** {@inheritDoc} */
@Override
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTree.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTree.java
index cd57774..4a6a407 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTree.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTree.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** This class represent a Binary Space Partition tree.
@@ -56,21 +55,21 @@ import org.apache.commons.geometry.core.Space;
* Computer Graphics 24(4), August 1990, pp 115-124, published by the
* Association for Computing Machinery (ACM).</p>
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public class BSPTree<S extends Space> {
+public class BSPTree<P extends Point<P>> {
/** Cut sub-hyperplane. */
- private SubHyperplane<S> cut;
+ private SubHyperplane<P> cut;
/** Tree at the plus side of the cut hyperplane. */
- private BSPTree<S> plus;
+ private BSPTree<P> plus;
/** Tree at the minus side of the cut hyperplane. */
- private BSPTree<S> minus;
+ private BSPTree<P> minus;
/** Parent tree. */
- private BSPTree<S> parent;
+ private BSPTree<P> parent;
/** Application-defined attribute. */
private Object attribute;
@@ -109,7 +108,7 @@ public class BSPTree<S extends Space> {
* @param attribute attribute associated with the node (may be null)
* @see #insertCut
*/
- public BSPTree(final SubHyperplane<S> cut, final BSPTree<S> plus, final BSPTree<S> minus,
+ public BSPTree(final SubHyperplane<P> cut, final BSPTree<P> plus, final BSPTree<P> minus,
final Object attribute) {
this.cut = cut;
this.plus = plus;
@@ -143,14 +142,14 @@ public class BSPTree<S extends Space> {
* the cell now has two leaf child nodes)
* @see #BSPTree(SubHyperplane, BSPTree, BSPTree, Object)
*/
- public boolean insertCut(final Hyperplane<S> hyperplane) {
+ public boolean insertCut(final Hyperplane<P> hyperplane) {
if (cut != null) {
plus.parent = null;
minus.parent = null;
}
- final SubHyperplane<S> chopped = fitToCell(hyperplane.wholeHyperplane());
+ final SubHyperplane<P> chopped = fitToCell(hyperplane.wholeHyperplane());
if (chopped == null || chopped.isEmpty()) {
cut = null;
plus = null;
@@ -174,7 +173,7 @@ public class BSPTree<S extends Space> {
* objects).</p>
* @return a new tree, copy of the instance
*/
- public BSPTree<S> copySelf() {
+ public BSPTree<P> copySelf() {
if (cut == null) {
return new BSPTree<>(attribute);
@@ -188,7 +187,7 @@ public class BSPTree<S extends Space> {
/** Get the cut sub-hyperplane.
* @return cut sub-hyperplane, null if this is a leaf tree
*/
- public SubHyperplane<S> getCut() {
+ public SubHyperplane<P> getCut() {
return cut;
}
@@ -196,7 +195,7 @@ public class BSPTree<S extends Space> {
* @return tree on the plus side of the cut hyperplane, null if this
* is a leaf tree
*/
- public BSPTree<S> getPlus() {
+ public BSPTree<P> getPlus() {
return plus;
}
@@ -204,14 +203,14 @@ public class BSPTree<S extends Space> {
* @return tree on the minus side of the cut hyperplane, null if this
* is a leaf tree
*/
- public BSPTree<S> getMinus() {
+ public BSPTree<P> getMinus() {
return minus;
}
/** Get the parent node.
* @return parent node, null if the node has no parents
*/
- public BSPTree<S> getParent() {
+ public BSPTree<P> getParent() {
return parent;
}
@@ -236,7 +235,7 @@ public class BSPTree<S extends Space> {
/** Visit the BSP tree nodes.
* @param visitor object visiting the tree nodes
*/
- public void visit(final BSPTreeVisitor<S> visitor) {
+ public void visit(final BSPTreeVisitor<P> visitor) {
if (cut == null) {
visitor.visitLeafNode(this);
} else {
@@ -284,9 +283,9 @@ public class BSPTree<S extends Space> {
* @return a new sub-hyperplane, guaranteed to have no part outside
* of the instance cell
*/
- private SubHyperplane<S> fitToCell(final SubHyperplane<S> sub) {
- SubHyperplane<S> s = sub;
- for (BSPTree<S> tree = this; tree.parent != null && s != null; tree = tree.parent) {
+ private SubHyperplane<P> fitToCell(final SubHyperplane<P> sub) {
+ SubHyperplane<P> s = sub;
+ for (BSPTree<P> tree = this; tree.parent != null && s != null; tree = tree.parent) {
if (tree == tree.parent.plus) {
s = s.split(tree.parent.cut.getHyperplane()).getPlus();
} else {
@@ -305,7 +304,7 @@ public class BSPTree<S extends Space> {
* are considered to belong to the hyperplane itself
* @return the tree cell to which the point belongs
*/
- public BSPTree<S> getCell(final Point<S> point, final double tolerance) {
+ public BSPTree<P> getCell(final P point, final double tolerance) {
if (cut == null) {
return this;
@@ -333,8 +332,8 @@ public class BSPTree<S extends Space> {
* @return close cells (may be empty if all cut sub-hyperplanes are farther
* than maxOffset from the point)
*/
- public List<BSPTree<S>> getCloseCuts(final Point<S> point, final double maxOffset) {
- final List<BSPTree<S>> close = new ArrayList<>();
+ public List<BSPTree<P>> getCloseCuts(final P point, final double maxOffset) {
+ final List<BSPTree<P>> close = new ArrayList<>();
recurseCloseCuts(point, maxOffset, close);
return close;
}
@@ -345,8 +344,8 @@ public class BSPTree<S extends Space> {
* close to the point (in absolute value)
* @param close list to fill
*/
- private void recurseCloseCuts(final Point<S> point, final double maxOffset,
- final List<BSPTree<S>> close) {
+ private void recurseCloseCuts(final P point, final double maxOffset,
+ final List<BSPTree<P>> close) {
if (cut != null) {
// position of the point with respect to the cut hyperplane
@@ -401,7 +400,7 @@ public class BSPTree<S extends Space> {
* tree</code>, this value can be ignored if parentTree is not null
* since all connections have already been established
*/
- public BSPTree<S> merge(final BSPTree<S> tree, final LeafMerger<S> leafMerger) {
+ public BSPTree<P> merge(final BSPTree<P> tree, final LeafMerger<P> leafMerger) {
return merge(tree, leafMerger, null, false);
}
@@ -420,8 +419,8 @@ public class BSPTree<S extends Space> {
* tree</code>, this value can be ignored if parentTree is not null
* since all connections have already been established
*/
- private BSPTree<S> merge(final BSPTree<S> tree, final LeafMerger<S> leafMerger,
- final BSPTree<S> parentTree, final boolean isPlusChild) {
+ private BSPTree<P> merge(final BSPTree<P> tree, final LeafMerger<P> leafMerger,
+ final BSPTree<P> parentTree, final boolean isPlusChild) {
if (cut == null) {
// cell/tree operation
return leafMerger.merge(this, tree, parentTree, isPlusChild, true);
@@ -430,7 +429,7 @@ public class BSPTree<S extends Space> {
return leafMerger.merge(tree, this, parentTree, isPlusChild, false);
} else {
// tree/tree operation
- final BSPTree<S> merged = tree.split(cut);
+ final BSPTree<P> merged = tree.split(cut);
if (parentTree != null) {
merged.parent = parentTree;
if (isPlusChild) {
@@ -469,7 +468,7 @@ public class BSPTree<S extends Space> {
* difference and symmetric difference (exclusive or).</p>
* @param <S> Type of the space.
*/
- public interface LeafMerger<S extends Space> {
+ public interface LeafMerger<S extends Point<S>> {
/** Merge a leaf node and a tree node.
* <p>This method is called at the end of a recursive merging
@@ -516,7 +515,7 @@ public class BSPTree<S extends Space> {
* </p>
* @param <S> Type of the space.
*/
- public interface VanishingCutHandler<S extends Space> {
+ public interface VanishingCutHandler<S extends Point<S>> {
/** Fix a node with both vanished cut and children.
* @param node node to fix
@@ -544,19 +543,19 @@ public class BSPTree<S extends Space> {
* sub-hyperplane, the two parts of the split instance as its two
* sub-trees and a null parent
*/
- public BSPTree<S> split(final SubHyperplane<S> sub) {
+ public BSPTree<P> split(final SubHyperplane<P> sub) {
if (cut == null) {
- return new BSPTree<>(sub, copySelf(), new BSPTree<S>(attribute), null);
+ return new BSPTree<>(sub, copySelf(), new BSPTree<P>(attribute), null);
}
- final Hyperplane<S> cHyperplane = cut.getHyperplane();
- final Hyperplane<S> sHyperplane = sub.getHyperplane();
- final SubHyperplane.SplitSubHyperplane<S> subParts = sub.split(cHyperplane);
+ final Hyperplane<P> cHyperplane = cut.getHyperplane();
+ final Hyperplane<P> sHyperplane = sub.getHyperplane();
+ final SubHyperplane.SplitSubHyperplane<P> subParts = sub.split(cHyperplane);
switch (subParts.getSide()) {
case PLUS :
{ // the partitioning sub-hyperplane is entirely in the plus sub-tree
- final BSPTree<S> split = plus.split(sub);
+ final BSPTree<P> split = plus.split(sub);
if (cut.split(sHyperplane).getSide() == Side.PLUS) {
split.plus =
new BSPTree<>(cut.copySelf(), split.plus, minus.copySelf(), attribute);
@@ -572,7 +571,7 @@ public class BSPTree<S extends Space> {
}
case MINUS :
{ // the partitioning sub-hyperplane is entirely in the minus sub-tree
- final BSPTree<S> split = minus.split(sub);
+ final BSPTree<P> split = minus.split(sub);
if (cut.split(sHyperplane).getSide() == Side.PLUS) {
split.plus =
new BSPTree<>(cut.copySelf(), plus.copySelf(), split.plus, attribute);
@@ -588,13 +587,13 @@ public class BSPTree<S extends Space> {
}
case BOTH :
{
- final SubHyperplane.SplitSubHyperplane<S> cutParts = cut.split(sHyperplane);
- final BSPTree<S> split =
+ final SubHyperplane.SplitSubHyperplane<P> cutParts = cut.split(sHyperplane);
+ final BSPTree<P> split =
new BSPTree<>(sub, plus.split(subParts.getPlus()), minus.split(subParts.getMinus()),
null);
split.plus.cut = cutParts.getPlus();
split.minus.cut = cutParts.getMinus();
- final BSPTree<S> tmp = split.plus.minus;
+ final BSPTree<P> tmp = split.plus.minus;
split.plus.minus = split.minus.plus;
split.plus.minus.parent = split.plus;
split.minus.plus = tmp;
@@ -622,8 +621,8 @@ public class BSPTree<S extends Space> {
* cases of vanishing cut sub-hyperplanes in internal nodes during merging
* @see LeafMerger
*/
- public void insertInTree(final BSPTree<S> parentTree, final boolean isPlusChild,
- final VanishingCutHandler<S> vanishingHandler) {
+ public void insertInTree(final BSPTree<P> parentTree, final boolean isPlusChild,
+ final VanishingCutHandler<P> vanishingHandler) {
// set up parent/child links
parent = parentTree;
@@ -639,10 +638,10 @@ public class BSPTree<S extends Space> {
if (cut != null) {
// explore the parent nodes from here towards tree root
- for (BSPTree<S> tree = this; tree.parent != null; tree = tree.parent) {
+ for (BSPTree<P> tree = this; tree.parent != null; tree = tree.parent) {
// this is an hyperplane of some parent node
- final Hyperplane<S> hyperplane = tree.parent.cut.getHyperplane();
+ final Hyperplane<P> hyperplane = tree.parent.cut.getHyperplane();
// chop off the parts of the inserted tree that extend
// on the wrong side of this parent hyperplane
@@ -658,7 +657,7 @@ public class BSPTree<S extends Space> {
if (cut == null) {
// the cut sub-hyperplane has vanished
- final BSPTree<S> fixed = vanishingHandler.fixNode(this);
+ final BSPTree<P> fixed = vanishingHandler.fixNode(this);
cut = fixed.cut;
plus = fixed.plus;
minus = fixed.minus;
@@ -696,17 +695,17 @@ public class BSPTree<S extends Space> {
* a single branch with the cell as a leaf node, and other leaf nodes
* as the remnants of the pruned branches
*/
- public BSPTree<S> pruneAroundConvexCell(final Object cellAttribute,
+ public BSPTree<P> pruneAroundConvexCell(final Object cellAttribute,
final Object otherLeafsAttributes,
final Object internalAttributes) {
// build the current cell leaf
- BSPTree<S> tree = new BSPTree<>(cellAttribute);
+ BSPTree<P> tree = new BSPTree<>(cellAttribute);
// build the pruned tree bottom-up
- for (BSPTree<S> current = this; current.parent != null; current = current.parent) {
- final SubHyperplane<S> parentCut = current.parent.cut.copySelf();
- final BSPTree<S> sibling = new BSPTree<>(otherLeafsAttributes);
+ for (BSPTree<P> current = this; current.parent != null; current = current.parent) {
+ final SubHyperplane<P> parentCut = current.parent.cut.copySelf();
+ final BSPTree<P> sibling = new BSPTree<>(otherLeafsAttributes);
if (current == current.parent.plus) {
tree = new BSPTree<>(parentCut, tree, sibling, internalAttributes);
} else {
@@ -726,7 +725,7 @@ public class BSPTree<S extends Space> {
* @param vanishingHandler handler to use for handling very rare corner
* cases of vanishing cut sub-hyperplanes in internal nodes during merging
*/
- private void chopOffMinus(final Hyperplane<S> hyperplane, final VanishingCutHandler<S> vanishingHandler) {
+ private void chopOffMinus(final Hyperplane<P> hyperplane, final VanishingCutHandler<P> vanishingHandler) {
if (cut != null) {
cut = cut.split(hyperplane).getPlus();
@@ -735,7 +734,7 @@ public class BSPTree<S extends Space> {
if (cut == null) {
// the cut sub-hyperplane has vanished
- final BSPTree<S> fixed = vanishingHandler.fixNode(this);
+ final BSPTree<P> fixed = vanishingHandler.fixNode(this);
cut = fixed.cut;
plus = fixed.plus;
minus = fixed.minus;
@@ -753,7 +752,7 @@ public class BSPTree<S extends Space> {
* @param vanishingHandler handler to use for handling very rare corner
* cases of vanishing cut sub-hyperplanes in internal nodes during merging
*/
- private void chopOffPlus(final Hyperplane<S> hyperplane, final VanishingCutHandler<S> vanishingHandler) {
+ private void chopOffPlus(final Hyperplane<P> hyperplane, final VanishingCutHandler<P> vanishingHandler) {
if (cut != null) {
cut = cut.split(hyperplane).getMinus();
@@ -762,7 +761,7 @@ public class BSPTree<S extends Space> {
if (cut == null) {
// the cut sub-hyperplane has vanished
- final BSPTree<S> fixed = vanishingHandler.fixNode(this);
+ final BSPTree<P> fixed = vanishingHandler.fixNode(this);
cut = fixed.cut;
plus = fixed.plus;
minus = fixed.minus;
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTreeVisitor.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTreeVisitor.java
index f7bbdbb..52d0eee 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTreeVisitor.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BSPTreeVisitor.java
@@ -16,7 +16,7 @@
*/
package org.apache.commons.geometry.core.partitioning;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** This interface is used to visit {@link BSPTree BSP tree} nodes.
@@ -40,12 +40,12 @@ import org.apache.commons.geometry.core.Space;
* </li>
* </ul>
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
* @see BSPTree
* @see SubHyperplane
*/
-public interface BSPTreeVisitor<S extends Space> {
+public interface BSPTreeVisitor<P extends Point<P>> {
/** Enumerate for visit order with respect to plus sub-tree, minus sub-tree and cut sub-hyperplane. */
enum Order {
@@ -92,7 +92,7 @@ public interface BSPTreeVisitor<S extends Space> {
* {@link Order#MINUS_PLUS_SUB}, {@link Order#MINUS_SUB_PLUS},
* {@link Order#SUB_PLUS_MINUS}, {@link Order#SUB_MINUS_PLUS}
*/
- Order visitOrder(BSPTree<S> node);
+ Order visitOrder(BSPTree<P> node);
/** Visit a BSP tree node node having a non-null sub-hyperplane.
* <p>It is guaranteed that this method will be called after {@link
@@ -101,12 +101,12 @@ public interface BSPTreeVisitor<S extends Space> {
* @param node BSP node guaranteed to have a non null cut sub-hyperplane
* @see #visitLeafNode
*/
- void visitInternalNode(BSPTree<S> node);
+ void visitInternalNode(BSPTree<P> node);
/** Visit a leaf BSP tree node node having a null sub-hyperplane.
* @param node leaf BSP node having a null sub-hyperplane
* @see #visitInternalNode
*/
- void visitLeafNode(BSPTree<S> node);
+ void visitLeafNode(BSPTree<P> node);
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryAttribute.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryAttribute.java
index ad6a365..0476c34 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryAttribute.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryAttribute.java
@@ -16,36 +16,39 @@
*/
package org.apache.commons.geometry.core.partitioning;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** Class holding boundary attributes.
+ *
* <p>This class is used for the attributes associated with the
* nodes of region boundary shell trees returned by the {@link
* Region#getTree(boolean) Region.getTree(includeBoundaryAttributes)}
* when the boolean {@code includeBoundaryAttributes} parameter is
* set to {@code true}. It contains the parts of the node cut
* sub-hyperplane that belong to the boundary.</p>
+ *
* <p>This class is a simple placeholder, it does not provide any
* processing methods.</p>
- * @param <S> Type of the space.
+ *
+ * @param <P> Point type defining the space
* @see Region#getTree
*/
-public class BoundaryAttribute<S extends Space> {
+public class BoundaryAttribute<P extends Point<P>> {
/** Part of the node cut sub-hyperplane that belongs to the
* boundary and has the outside of the region on the plus side of
* its underlying hyperplane (may be null).
*/
- private final SubHyperplane<S> plusOutside;
+ private final SubHyperplane<P> plusOutside;
/** Part of the node cut sub-hyperplane that belongs to the
* boundary and has the inside of the region on the plus side of
* its underlying hyperplane (may be null).
*/
- private final SubHyperplane<S> plusInside;
+ private final SubHyperplane<P> plusInside;
/** Sub-hyperplanes that were used to split the boundary part. */
- private final NodesSet<S> splitters;
+ private final NodesSet<P> splitters;
/** Simple constructor.
* @param plusOutside part of the node cut sub-hyperplane that
@@ -57,9 +60,9 @@ public class BoundaryAttribute<S extends Space> {
* @param splitters sub-hyperplanes that were used to
* split the boundary part (may be null)
*/
- BoundaryAttribute(final SubHyperplane<S> plusOutside,
- final SubHyperplane<S> plusInside,
- final NodesSet<S> splitters) {
+ BoundaryAttribute(final SubHyperplane<P> plusOutside,
+ final SubHyperplane<P> plusInside,
+ final NodesSet<P> splitters) {
this.plusOutside = plusOutside;
this.plusInside = plusInside;
this.splitters = splitters;
@@ -72,7 +75,7 @@ public class BoundaryAttribute<S extends Space> {
* boundary and has the outside of the region on the plus side of
* its underlying hyperplane
*/
- public SubHyperplane<S> getPlusOutside() {
+ public SubHyperplane<P> getPlusOutside() {
return plusOutside;
}
@@ -83,14 +86,14 @@ public class BoundaryAttribute<S extends Space> {
* boundary and has the inside of the region on the plus side of
* its underlying hyperplane
*/
- public SubHyperplane<S> getPlusInside() {
+ public SubHyperplane<P> getPlusInside() {
return plusInside;
}
/** Get the sub-hyperplanes that were used to split the boundary part.
* @return sub-hyperplanes that were used to split the boundary part
*/
- public NodesSet<S> getSplitters() {
+ public NodesSet<P> getSplitters() {
return splitters;
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryBuilder.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryBuilder.java
index 816d3c2..63d19b8 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryBuilder.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryBuilder.java
@@ -16,40 +16,42 @@
*/
package org.apache.commons.geometry.core.partitioning;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** Visitor building boundary shell tree.
+ *
* <p>
* The boundary shell is represented as {@link BoundaryAttribute boundary attributes}
* at each internal node.
* </p>
- * @param <S> Type of the space.
+ *
+ * @param <P> Point type defining the space.
*/
-class BoundaryBuilder<S extends Space> implements BSPTreeVisitor<S> {
+class BoundaryBuilder<P extends Point<P>> implements BSPTreeVisitor<P> {
/** {@inheritDoc} */
@Override
- public Order visitOrder(BSPTree<S> node) {
+ public Order visitOrder(BSPTree<P> node) {
return Order.PLUS_MINUS_SUB;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(BSPTree<S> node) {
+ public void visitInternalNode(BSPTree<P> node) {
- SubHyperplane<S> plusOutside = null;
- SubHyperplane<S> plusInside = null;
- NodesSet<S> splitters = null;
+ SubHyperplane<P> plusOutside = null;
+ SubHyperplane<P> plusInside = null;
+ NodesSet<P> splitters = null;
// characterize the cut sub-hyperplane,
// first with respect to the plus sub-tree
- final Characterization<S> plusChar = new Characterization<>(node.getPlus(), node.getCut().copySelf());
+ final Characterization<P> plusChar = new Characterization<>(node.getPlus(), node.getCut().copySelf());
if (plusChar.touchOutside()) {
// plusChar.outsideTouching() corresponds to a subset of the cut sub-hyperplane
// known to have outside cells on its plus side, we want to check if parts
// of this subset do have inside cells on their minus side
- final Characterization<S> minusChar = new Characterization<>(node.getMinus(), plusChar.outsideTouching());
+ final Characterization<P> minusChar = new Characterization<>(node.getMinus(), plusChar.outsideTouching());
if (minusChar.touchInside()) {
// this part belongs to the boundary,
// it has the outside on its plus side and the inside on its minus side
@@ -64,7 +66,7 @@ class BoundaryBuilder<S extends Space> implements BSPTreeVisitor<S> {
// plusChar.insideTouching() corresponds to a subset of the cut sub-hyperplane
// known to have inside cells on its plus side, we want to check if parts
// of this subset do have outside cells on their minus side
- final Characterization<S> minusChar = new Characterization<>(node.getMinus(), plusChar.insideTouching());
+ final Characterization<P> minusChar = new Characterization<>(node.getMinus(), plusChar.insideTouching());
if (minusChar.touchOutside()) {
// this part belongs to the boundary,
// it has the inside on its plus side and the outside on its minus side
@@ -79,7 +81,7 @@ class BoundaryBuilder<S extends Space> implements BSPTreeVisitor<S> {
if (splitters != null) {
// the parent nodes are natural splitters for boundary sub-hyperplanes
- for (BSPTree<S> up = node.getParent(); up != null; up = up.getParent()) {
+ for (BSPTree<P> up = node.getParent(); up != null; up = up.getParent()) {
splitters.add(up);
}
}
@@ -91,7 +93,7 @@ class BoundaryBuilder<S extends Space> implements BSPTreeVisitor<S> {
/** {@inheritDoc} */
@Override
- public void visitLeafNode(BSPTree<S> node) {
+ public void visitLeafNode(BSPTree<P> node) {
}
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjection.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjection.java
index 1d5254d..27709c2 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjection.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjection.java
@@ -17,22 +17,24 @@
package org.apache.commons.geometry.core.partitioning;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** Class holding the result of point projection on region boundary.
+ *
* <p>This class is a simple placeholder, it does not provide any
* processing methods.</p>
+ *
* <p>Instances of this class are guaranteed to be immutable</p>
- * @param <S> Type of the space.
+ *
+ * @param <P> Point type defining the space
* @see AbstractRegion#projectToBoundary(Point)
*/
-public class BoundaryProjection<S extends Space> {
+public class BoundaryProjection<P extends Point<P>> {
/** Original point. */
- private final Point<S> original;
+ private final P original;
/** Projected point. */
- private final Point<S> projected;
+ private final P projected;
/** Offset of the point with respect to the boundary it is projected on. */
private final double offset;
@@ -42,7 +44,7 @@ public class BoundaryProjection<S extends Space> {
* @param projected projected point
* @param offset offset of the point with respect to the boundary it is projected on
*/
- public BoundaryProjection(final Point<S> original, final Point<S> projected, final double offset) {
+ public BoundaryProjection(final P original, final P projected, final double offset) {
this.original = original;
this.projected = projected;
this.offset = offset;
@@ -51,14 +53,14 @@ public class BoundaryProjection<S extends Space> {
/** Get the original point.
* @return original point
*/
- public Point<S> getOriginal() {
+ public P getOriginal() {
return original;
}
/** Projected point.
* @return projected point, or null if there are no boundary
*/
- public Point<S> getProjected() {
+ public P getProjected() {
return projected;
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjector.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjector.java
index 390695c..f694a89 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjector.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryProjector.java
@@ -20,23 +20,22 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
import org.apache.commons.geometry.core.partitioning.Region.Location;
/** Local tree visitor to compute projection on boundary.
- * @param <S> Type of the space.
- * @param <T> Type of the sub-space.
+ * @param <P> Point type defining the space
+ * @param <S> Point type defining the sub-space
*/
-class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisitor<S> {
+class BoundaryProjector<P extends Point<P>, S extends Point<S>> implements BSPTreeVisitor<P> {
/** Original point. */
- private final Point<S> original;
+ private final P original;
/** Current best projected point. */
- private Point<S> projected;
+ private P projected;
/** Leaf node closest to the test point. */
- private BSPTree<S> leaf;
+ private BSPTree<P> leaf;
/** Current offset. */
private double offset;
@@ -44,7 +43,7 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
/** Simple constructor.
* @param original original point
*/
- BoundaryProjector(final Point<S> original) {
+ BoundaryProjector(final P original) {
this.original = original;
this.projected = null;
this.leaf = null;
@@ -53,7 +52,7 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
/** {@inheritDoc} */
@Override
- public Order visitOrder(final BSPTree<S> node) {
+ public Order visitOrder(final BSPTree<P> node) {
// we want to visit the tree so that the first encountered
// leaf is the one closest to the test point
if (node.getCut().getHyperplane().getOffset(original) <= 0) {
@@ -65,22 +64,22 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
/** {@inheritDoc} */
@Override
- public void visitInternalNode(final BSPTree<S> node) {
+ public void visitInternalNode(final BSPTree<P> node) {
// project the point on the cut sub-hyperplane
- final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
+ final Hyperplane<P> hyperplane = node.getCut().getHyperplane();
final double signedOffset = hyperplane.getOffset(original);
if (Math.abs(signedOffset) < offset) {
// project point
- final Point<S> regular = hyperplane.project(original);
+ final P regular = hyperplane.project(original);
// get boundary parts
- final List<Region<T>> boundaryParts = boundaryRegions(node);
+ final List<Region<S>> boundaryParts = boundaryRegions(node);
// check if regular projection really belongs to the boundary
boolean regularFound = false;
- for (final Region<T> part : boundaryParts) {
+ for (final Region<S> part : boundaryParts) {
if (!regularFound && belongsToPart(regular, hyperplane, part)) {
// the projected point lies in the boundary
projected = regular;
@@ -93,8 +92,8 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
// the regular projected point is not on boundary,
// so we have to check further if a singular point
// (i.e. a vertex in 2D case) is a possible projection
- for (final Region<T> part : boundaryParts) {
- final Point<S> spI = singularProjection(regular, hyperplane, part);
+ for (final Region<S> part : boundaryParts) {
+ final P spI = singularProjection(regular, hyperplane, part);
if (spI != null) {
final double distance = original.distance(spI);
if (distance < offset) {
@@ -112,7 +111,7 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
/** {@inheritDoc} */
@Override
- public void visitLeafNode(final BSPTree<S> node) {
+ public void visitLeafNode(final BSPTree<P> node) {
if (leaf == null) {
// this is the first leaf we visit,
// it is the closest one to the original point
@@ -123,7 +122,7 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
/** Get the projection.
* @return projection
*/
- public BoundaryProjection<S> getProjection() {
+ public BoundaryProjection<P> getProjection() {
// fix offset sign
offset = Math.copySign(offset, (Boolean) leaf.getAttribute() ? -1 : +1);
@@ -136,12 +135,12 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
* @param node internal node
* @return regions in the node sub-hyperplane
*/
- private List<Region<T>> boundaryRegions(final BSPTree<S> node) {
+ private List<Region<S>> boundaryRegions(final BSPTree<P> node) {
- final List<Region<T>> regions = new ArrayList<>(2);
+ final List<Region<S>> regions = new ArrayList<>(2);
@SuppressWarnings("unchecked")
- final BoundaryAttribute<S> ba = (BoundaryAttribute<S>) node.getAttribute();
+ final BoundaryAttribute<P> ba = (BoundaryAttribute<P>) node.getAttribute();
addRegion(ba.getPlusInside(), regions);
addRegion(ba.getPlusOutside(), regions);
@@ -153,10 +152,10 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
* @param sub sub-hyperplane defining the region
* @param list to fill up
*/
- private void addRegion(final SubHyperplane<S> sub, final List<Region<T>> list) {
+ private void addRegion(final SubHyperplane<P> sub, final List<Region<S>> list) {
if (sub != null) {
@SuppressWarnings("unchecked")
- final Region<T> region = ((AbstractSubHyperplane<S, T>) sub).getRemainingRegion();
+ final Region<S> region = ((AbstractSubHyperplane<P, S>) sub).getRemainingRegion();
if (region != null) {
list.add(region);
}
@@ -169,12 +168,12 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
* @param part boundary part
* @return true if point lies on the boundary part
*/
- private boolean belongsToPart(final Point<S> point, final Hyperplane<S> hyperplane,
- final Region<T> part) {
+ private boolean belongsToPart(final P point, final Hyperplane<P> hyperplane,
+ final Region<S> part) {
// there is a non-null sub-space, we can dive into smaller dimensions
@SuppressWarnings("unchecked")
- final Embedding<S, T> embedding = (Embedding<S, T>) hyperplane;
+ final Embedding<P, S> embedding = (Embedding<P, S>) hyperplane;
return part.checkPoint(embedding.toSubSpace(point)) != Location.OUTSIDE;
}
@@ -185,13 +184,13 @@ class BoundaryProjector<S extends Space, T extends Space> implements BSPTreeVisi
* @param part boundary part
* @return projection to a singular point of boundary part (may be null)
*/
- private Point<S> singularProjection(final Point<S> point, final Hyperplane<S> hyperplane,
- final Region<T> part) {
+ private P singularProjection(final P point, final Hyperplane<P> hyperplane,
+ final Region<S> part) {
// there is a non-null sub-space, we can dive into smaller dimensions
@SuppressWarnings("unchecked")
- final Embedding<S, T> embedding = (Embedding<S, T>) hyperplane;
- final BoundaryProjection<T> bp = part.projectToBoundary(embedding.toSubSpace(point));
+ final Embedding<P, S> embedding = (Embedding<P, S>) hyperplane;
+ final BoundaryProjection<S> bp = part.projectToBoundary(embedding.toSubSpace(point));
// back to initial dimension
return (bp.getProjected() == null) ? null : embedding.toSpace(bp.getProjected());
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundarySizeVisitor.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundarySizeVisitor.java
index b305a36..e84c70a 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundarySizeVisitor.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundarySizeVisitor.java
@@ -16,12 +16,12 @@
*/
package org.apache.commons.geometry.core.partitioning;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** Visitor computing the boundary size.
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-class BoundarySizeVisitor<S extends Space> implements BSPTreeVisitor<S> {
+class BoundarySizeVisitor<P extends Point<P>> implements BSPTreeVisitor<P> {
/** Size of the boundary. */
private double boundarySize;
@@ -34,16 +34,16 @@ class BoundarySizeVisitor<S extends Space> implements BSPTreeVisitor<S> {
/** {@inheritDoc}*/
@Override
- public Order visitOrder(final BSPTree<S> node) {
+ public Order visitOrder(final BSPTree<P> node) {
return Order.MINUS_SUB_PLUS;
}
/** {@inheritDoc}*/
@Override
- public void visitInternalNode(final BSPTree<S> node) {
+ public void visitInternalNode(final BSPTree<P> node) {
@SuppressWarnings("unchecked")
- final BoundaryAttribute<S> attribute =
- (BoundaryAttribute<S>) node.getAttribute();
+ final BoundaryAttribute<P> attribute =
+ (BoundaryAttribute<P>) node.getAttribute();
if (attribute.getPlusOutside() != null) {
boundarySize += attribute.getPlusOutside().getSize();
}
@@ -54,7 +54,7 @@ class BoundarySizeVisitor<S extends Space> implements BSPTreeVisitor<S> {
/** {@inheritDoc}*/
@Override
- public void visitLeafNode(final BSPTree<S> node) {
+ public void visitLeafNode(final BSPTree<P> node) {
}
/** Get the size of the boundary.
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Characterization.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Characterization.java
index 7184c96..d9ec6e7 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Characterization.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Characterization.java
@@ -19,25 +19,25 @@ package org.apache.commons.geometry.core.partitioning;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** Cut sub-hyperplanes characterization with respect to inside/outside cells.
* @see BoundaryBuilder
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-class Characterization<S extends Space> {
+class Characterization<P extends Point<P>> {
/** Part of the cut sub-hyperplane that touch outside cells. */
- private SubHyperplane<S> outsideTouching;
+ private SubHyperplane<P> outsideTouching;
/** Part of the cut sub-hyperplane that touch inside cells. */
- private SubHyperplane<S> insideTouching;
+ private SubHyperplane<P> insideTouching;
/** Nodes that were used to split the outside touching part. */
- private final NodesSet<S> outsideSplitters;
+ private final NodesSet<P> outsideSplitters;
/** Nodes that were used to split the outside touching part. */
- private final NodesSet<S> insideSplitters;
+ private final NodesSet<P> insideSplitters;
/** Simple constructor.
* <p>Characterization consists in splitting the specified
@@ -51,12 +51,12 @@ class Characterization<S extends Space> {
* @param node current BSP tree node
* @param sub sub-hyperplane to characterize
*/
- Characterization(final BSPTree<S> node, final SubHyperplane<S> sub) {
+ Characterization(final BSPTree<P> node, final SubHyperplane<P> sub) {
outsideTouching = null;
insideTouching = null;
outsideSplitters = new NodesSet<>();
insideSplitters = new NodesSet<>();
- characterize(node, sub, new ArrayList<BSPTree<S>>());
+ characterize(node, sub, new ArrayList<BSPTree<P>>());
}
/** Filter the parts of an hyperplane belonging to the boundary.
@@ -72,8 +72,8 @@ class Characterization<S extends Space> {
* @param sub sub-hyperplane to characterize
* @param splitters nodes that did split the current one
*/
- private void characterize(final BSPTree<S> node, final SubHyperplane<S> sub,
- final List<BSPTree<S>> splitters) {
+ private void characterize(final BSPTree<P> node, final SubHyperplane<P> sub,
+ final List<BSPTree<P>> splitters) {
if (node.getCut() == null) {
// we have reached a leaf node
final boolean inside = (Boolean) node.getAttribute();
@@ -83,8 +83,8 @@ class Characterization<S extends Space> {
addOutsideTouching(sub, splitters);
}
} else {
- final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
- final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
+ final Hyperplane<P> hyperplane = node.getCut().getHyperplane();
+ final SubHyperplane.SplitSubHyperplane<P> split = sub.split(hyperplane);
switch (split.getSide()) {
case PLUS:
characterize(node.getPlus(), sub, splitters);
@@ -117,8 +117,8 @@ class Characterization<S extends Space> {
* @param sub part of the cut sub-hyperplane known to touch an outside cell
* @param splitters sub-hyperplanes that did split the current one
*/
- private void addOutsideTouching(final SubHyperplane<S> sub,
- final List<BSPTree<S>> splitters) {
+ private void addOutsideTouching(final SubHyperplane<P> sub,
+ final List<BSPTree<P>> splitters) {
if (outsideTouching == null) {
outsideTouching = sub;
} else {
@@ -131,8 +131,8 @@ class Characterization<S extends Space> {
* @param sub part of the cut sub-hyperplane known to touch an inside cell
* @param splitters sub-hyperplanes that did split the current one
*/
- private void addInsideTouching(final SubHyperplane<S> sub,
- final List<BSPTree<S>> splitters) {
+ private void addInsideTouching(final SubHyperplane<P> sub,
+ final List<BSPTree<P>> splitters) {
if (insideTouching == null) {
insideTouching = sub;
} else {
@@ -152,7 +152,7 @@ class Characterization<S extends Space> {
* @return parts of the cut sub-hyperplane known to touch outside cells
* (may be null or empty)
*/
- public SubHyperplane<S> outsideTouching() {
+ public SubHyperplane<P> outsideTouching() {
return outsideTouching;
}
@@ -163,7 +163,7 @@ class Characterization<S extends Space> {
* </p>
* @return nodes that were used to split the outside touching part
*/
- public NodesSet<S> getOutsideSplitters() {
+ public NodesSet<P> getOutsideSplitters() {
return outsideSplitters;
}
@@ -178,7 +178,7 @@ class Characterization<S extends Space> {
* @return parts of the cut sub-hyperplane known to touch inside cells
* (may be null or empty)
*/
- public SubHyperplane<S> insideTouching() {
+ public SubHyperplane<P> insideTouching() {
return insideTouching;
}
@@ -189,7 +189,7 @@ class Characterization<S extends Space> {
* </p>
* @return nodes that were used to split the inside touching part
*/
- public NodesSet<S> getInsideSplitters() {
+ public NodesSet<P> getInsideSplitters() {
return insideSplitters;
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Embedding.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Embedding.java
index 7ed9ef5..f4ebd50 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Embedding.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Embedding.java
@@ -17,7 +17,6 @@
package org.apache.commons.geometry.core.partitioning;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** This interface defines mappers between a space and one of its sub-spaces.
@@ -27,8 +26,8 @@ import org.apache.commons.geometry.core.Space;
* of the dimensions differences. As an example, {@link
* org.apache.commons.geometry.euclidean.threed.Line Line} in 3D
* implements Embedding<{@link
- * org.apache.commons.geometry.euclidean.threed.Cartesian3D Cartesian3D}, {@link
- * org.apache.commons.geometry.euclidean.oned.Cartesian1D Cartesian1D}>, i.e. it
+ * org.apache.commons.geometry.euclidean.threed.Point3D Point3D}, {@link
+ * org.apache.commons.geometry.euclidean.oned.Point1D Point1D}>, i.e. it
* maps directly dimensions 3 and 1.</p>
* <p>In the 3D euclidean space, hyperplanes are 2D planes, and the 1D
@@ -41,12 +40,12 @@ import org.apache.commons.geometry.core.Space;
* versions, which breaks compatibility for external implementations.
* </p>
- * @param <S> Type of the embedding space.
- * @param <T> Type of the embedded sub-space.
+ * @param <P> Point type defining the embedding space.
+ * @param <S> Point type defining the embedded sub-space.
* @see Hyperplane
*/
-public interface Embedding<S extends Space, T extends Space> {
+public interface Embedding<P extends Point<P>, S extends Point<S>> {
/** Transform a space point into a sub-space point.
* @param point n-dimension point of the space
@@ -54,7 +53,7 @@ public interface Embedding<S extends Space, T extends Space> {
* the specified space point
* @see #toSpace
*/
- Point<T> toSubSpace(Point<S> point);
+ S toSubSpace(P point);
/** Transform a sub-space point into a space point.
* @param point (n-1)-dimension point of the sub-space
@@ -62,6 +61,6 @@ public interface Embedding<S extends Space, T extends Space> {
* specified sub-space point
* @see #toSubSpace
*/
- Point<S> toSpace(Point<T> point);
+ P toSpace(S point);
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Hyperplane.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Hyperplane.java
index 8041658..9a29432 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Hyperplane.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Hyperplane.java
@@ -17,7 +17,6 @@
package org.apache.commons.geometry.core.partitioning;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** This interface represents an hyperplane of a space.
@@ -32,14 +31,14 @@ import org.apache.commons.geometry.core.Space;
* <p>
* Note that this interface is <em>not</em> intended to be implemented
- * by Apache Commons Math users, it is only intended to be implemented
+ * by Apache Commons Geometry users, it is only intended to be implemented
* within the library itself. New methods may be added even for minor
* versions, which breaks compatibility for external implementations.
* </p>
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public interface Hyperplane<S extends Space> {
+public interface Hyperplane<P extends Point<P>> {
/** Copy the instance.
* <p>The instance created is completely independant of the original
@@ -47,7 +46,7 @@ public interface Hyperplane<S extends Space> {
* shared (except for immutable objects).</p>
* @return a new hyperplane, copy of the instance
*/
- Hyperplane<S> copySelf();
+ Hyperplane<P> copySelf();
/** Get the offset (oriented distance) of a point.
* <p>The offset is 0 if the point is on the underlying hyperplane,
@@ -57,13 +56,13 @@ public interface Hyperplane<S extends Space> {
* @param point point to check
* @return offset of the point
*/
- double getOffset(Point<S> point);
+ double getOffset(P point);
/** Project a point to the hyperplane.
* @param point point to project
* @return projected point
*/
- Point<S> project(Point<S> point);
+ P project(P point);
/** Get the tolerance below which points are considered to belong to the hyperplane.
* @return tolerance below which points are considered to belong to the hyperplane
@@ -79,16 +78,16 @@ public interface Hyperplane<S extends Space> {
* @return true if the instance and the other hyperplane have
* the same orientation
*/
- boolean sameOrientationAs(Hyperplane<S> other);
+ boolean sameOrientationAs(Hyperplane<P> other);
/** Build a sub-hyperplane covering the whole hyperplane.
* @return a sub-hyperplane covering the whole hyperplane
*/
- SubHyperplane<S> wholeHyperplane();
+ SubHyperplane<P> wholeHyperplane();
/** Build a region covering the whole space.
* @return a region containing the instance
*/
- Region<S> wholeSpace();
+ Region<P> wholeSpace();
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/InsideFinder.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/InsideFinder.java
index aec8a41..cb384d9 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/InsideFinder.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/InsideFinder.java
@@ -16,16 +16,16 @@
*/
package org.apache.commons.geometry.core.partitioning;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** Utility class checking if inside nodes can be found
* on the plus and minus sides of an hyperplane.
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-class InsideFinder<S extends Space> {
+class InsideFinder<P extends Point<P>> {
/** Region on which to operate. */
- private final Region<S> region;
+ private final Region<P> region;
/** Indicator of inside leaf nodes found on the plus side. */
private boolean plusFound;
@@ -36,7 +36,7 @@ class InsideFinder<S extends Space> {
/** Simple constructor.
* @param region region on which to operate
*/
- InsideFinder(final Region<S> region) {
+ InsideFinder(final Region<P> region) {
this.region = region;
plusFound = false;
minusFound = false;
@@ -56,7 +56,7 @@ class InsideFinder<S extends Space> {
* @param node current BSP tree node
* @param sub sub-hyperplane
*/
- public void recurseSides(final BSPTree<S> node, final SubHyperplane<S> sub) {
+ public void recurseSides(final BSPTree<P> node, final SubHyperplane<P> sub) {
if (node.getCut() == null) {
if ((Boolean) node.getAttribute()) {
@@ -67,8 +67,8 @@ class InsideFinder<S extends Space> {
return;
}
- final Hyperplane<S> hyperplane = node.getCut().getHyperplane();
- final SubHyperplane.SplitSubHyperplane<S> split = sub.split(hyperplane);
+ final Hyperplane<P> hyperplane = node.getCut().getHyperplane();
+ final SubHyperplane.SplitSubHyperplane<P> split = sub.split(hyperplane);
switch (split.getSide()) {
case PLUS :
// the sub-hyperplane is entirely in the plus sub-tree
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/NodesSet.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/NodesSet.java
index 20ef6b7..54e0c3d 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/NodesSet.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/NodesSet.java
@@ -20,16 +20,16 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** Set of {@link BSPTree BSP tree} nodes.
* @see BoundaryAttribute
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public class NodesSet<S extends Space> implements Iterable<BSPTree<S>> {
+public class NodesSet<P extends Point<P>> implements Iterable<BSPTree<P>> {
/** List of sub-hyperplanes. */
- private final List<BSPTree<S>> list;
+ private final List<BSPTree<P>> list;
/** Simple constructor.
*/
@@ -40,9 +40,9 @@ public class NodesSet<S extends Space> implements Iterable<BSPTree<S>> {
/** Add a node if not already known.
* @param node node to add
*/
- public void add(final BSPTree<S> node) {
+ public void add(final BSPTree<P> node) {
- for (final BSPTree<S> existing : list) {
+ for (final BSPTree<P> existing : list) {
if (node == existing) {
// the node is already known, don't add it
return;
@@ -57,15 +57,15 @@ public class NodesSet<S extends Space> implements Iterable<BSPTree<S>> {
/** Add nodes if they are not already known.
* @param iterator nodes iterator
*/
- public void addAll(final Iterable<BSPTree<S>> iterator) {
- for (final BSPTree<S> node : iterator) {
+ public void addAll(final Iterable<BSPTree<P>> iterator) {
+ for (final BSPTree<P> node : iterator) {
add(node);
}
}
/** {@inheritDoc} */
@Override
- public Iterator<BSPTree<S>> iterator() {
+ public Iterator<BSPTree<P>> iterator() {
return list.iterator();
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Region.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Region.java
index 63155a5..4fef7e3 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Region.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Region.java
@@ -17,7 +17,6 @@
package org.apache.commons.geometry.core.partitioning;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** This interface represents a region of a space as a partition.
@@ -46,9 +45,9 @@ import org.apache.commons.geometry.core.Space;
* versions, which breaks compatibility for external implementations.
* </p>
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public interface Region<S extends Space> {
+public interface Region<P extends Point<P>> {
/** Enumerate for the location of a point with respect to the region. */
enum Location {
@@ -78,7 +77,7 @@ public interface Region<S extends Space> {
* @param newTree inside/outside BSP tree representing the new region
* @return the built region
*/
- Region<S> buildNew(BSPTree<S> newTree);
+ Region<P> buildNew(BSPTree<P> newTree);
/** Copy the instance.
* <p>The instance created is completely independant of the original
@@ -87,7 +86,7 @@ public interface Region<S extends Space> {
* attributes and immutable objects).</p>
* @return a new region, copy of the instance
*/
- Region<S> copySelf();
+ Region<P> copySelf();
/** Check if the instance is empty.
* @return true if the instance is empty
@@ -101,7 +100,7 @@ public interface Region<S extends Space> {
* property)
* @return true if the sub-tree starting at the given node is empty
*/
- boolean isEmpty(final BSPTree<S> node);
+ boolean isEmpty(final BSPTree<P> node);
/** Check if the instance covers the full space.
* @return true if the instance covers the full space
@@ -115,26 +114,26 @@ public interface Region<S extends Space> {
* property)
* @return true if the sub-tree starting at the given node covers the full space
*/
- boolean isFull(final BSPTree<S> node);
+ boolean isFull(final BSPTree<P> node);
/** Check if the instance entirely contains another region.
* @param region region to check against the instance
* @return true if the instance contains the specified tree
*/
- boolean contains(final Region<S> region);
+ boolean contains(final Region<P> region);
/** Check a point with respect to the region.
* @param point point to check
* @return a code representing the point status: either {@link
* Location#INSIDE}, {@link Location#OUTSIDE} or {@link Location#BOUNDARY}
*/
- Location checkPoint(final Point<S> point);
+ Location checkPoint(final P point);
/** Project a point on the boundary of the region.
* @param point point to check
* @return projection of the point on the boundary
*/
- BoundaryProjection<S> projectToBoundary(final Point<S> point);
+ BoundaryProjection<P> projectToBoundary(final P point);
/** Get the underlying BSP tree.
@@ -175,7 +174,7 @@ public interface Region<S extends Space> {
* @return underlying BSP tree
* @see BoundaryAttribute
*/
- BSPTree<S> getTree(final boolean includeBoundaryAttributes);
+ BSPTree<P> getTree(final boolean includeBoundaryAttributes);
/** Get the size of the boundary.
* @return the size of the boundary (this is 0 in 1D, a length in
@@ -192,7 +191,7 @@ public interface Region<S extends Space> {
/** Get the barycenter of the instance.
* @return an object representing the barycenter
*/
- Point<S> getBarycenter();
+ P getBarycenter();
/** Get the parts of a sub-hyperplane that are contained in the region.
* <p>The parts of the sub-hyperplane that belong to the boundary are
@@ -200,6 +199,6 @@ public interface Region<S extends Space> {
* @param sub sub-hyperplane traversing the region
* @return filtered sub-hyperplane
*/
- SubHyperplane<S> intersection(final SubHyperplane<S> sub);
+ SubHyperplane<P> intersection(final SubHyperplane<P> sub);
}
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/RegionFactory.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/RegionFactory.java
index 61a888a..c15676c 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/RegionFactory.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/RegionFactory.java
@@ -20,16 +20,15 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
import org.apache.commons.geometry.core.partitioning.BSPTree.VanishingCutHandler;
import org.apache.commons.geometry.core.partitioning.Region.Location;
import org.apache.commons.geometry.core.partitioning.SubHyperplane.SplitSubHyperplane;
/** This class is a factory for {@link Region}.
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public class RegionFactory<S extends Space> {
+public class RegionFactory<P extends Point<P>> {
/** Visitor removing internal nodes attributes. */
private final NodesCleaner nodeCleaner;
@@ -45,18 +44,18 @@ public class RegionFactory<S extends Space> {
* @return a new convex region, or null if the collection is empty
*/
@SafeVarargs
- public final Region<S> buildConvex(final Hyperplane<S> ... hyperplanes) {
+ public final Region<P> buildConvex(final Hyperplane<P> ... hyperplanes) {
if ((hyperplanes == null) || (hyperplanes.length == 0)) {
return null;
}
// use the first hyperplane to build the right class
- final Region<S> region = hyperplanes[0].wholeSpace();
+ final Region<P> region = hyperplanes[0].wholeSpace();
// chop off parts of the space
- BSPTree<S> node = region.getTree(false);
+ BSPTree<P> node = region.getTree(false);
node.setAttribute(Boolean.TRUE);
- for (final Hyperplane<S> hyperplane : hyperplanes) {
+ for (final Hyperplane<P> hyperplane : hyperplanes) {
if (node.insertCut(hyperplane)) {
node.setAttribute(null);
node.getPlus().setAttribute(Boolean.FALSE);
@@ -66,10 +65,10 @@ public class RegionFactory<S extends Space> {
// the hyperplane could not be inserted in the current leaf node
// either it is completely outside (which means the input hyperplanes
// are wrong), or it is parallel to a previous hyperplane
- SubHyperplane<S> s = hyperplane.wholeHyperplane();
- for (BSPTree<S> tree = node; tree.getParent() != null && s != null; tree = tree.getParent()) {
- final Hyperplane<S> other = tree.getParent().getCut().getHyperplane();
- final SplitSubHyperplane<S> split = s.split(other);
+ SubHyperplane<P> s = hyperplane.wholeHyperplane();
+ for (BSPTree<P> tree = node; tree.getParent() != null && s != null; tree = tree.getParent()) {
+ final Hyperplane<P> other = tree.getParent().getCut().getHyperplane();
+ final SplitSubHyperplane<P> split = s.split(other);
switch (split.getSide()) {
case HYPER :
// the hyperplane is parallel to a previous hyperplane
@@ -102,8 +101,8 @@ public class RegionFactory<S extends Space> {
* parts of it will be reused in the new region)
* @return a new region, result of {@code region1 union region2}
*/
- public Region<S> union(final Region<S> region1, final Region<S> region2) {
- final BSPTree<S> tree =
+ public Region<P> union(final Region<P> region1, final Region<P> region2) {
+ final BSPTree<P> tree =
region1.getTree(false).merge(region2.getTree(false), new UnionMerger());
tree.visit(nodeCleaner);
return region1.buildNew(tree);
@@ -116,8 +115,8 @@ public class RegionFactory<S extends Space> {
* parts of it will be reused in the new region)
* @return a new region, result of {@code region1 intersection region2}
*/
- public Region<S> intersection(final Region<S> region1, final Region<S> region2) {
- final BSPTree<S> tree =
+ public Region<P> intersection(final Region<P> region1, final Region<P> region2) {
+ final BSPTree<P> tree =
region1.getTree(false).merge(region2.getTree(false), new IntersectionMerger());
tree.visit(nodeCleaner);
return region1.buildNew(tree);
@@ -130,8 +129,8 @@ public class RegionFactory<S extends Space> {
* parts of it will be reused in the new region)
* @return a new region, result of {@code region1 xor region2}
*/
- public Region<S> xor(final Region<S> region1, final Region<S> region2) {
- final BSPTree<S> tree =
+ public Region<P> xor(final Region<P> region1, final Region<P> region2) {
+ final BSPTree<P> tree =
region1.getTree(false).merge(region2.getTree(false), new XorMerger());
tree.visit(nodeCleaner);
return region1.buildNew(tree);
@@ -144,8 +143,8 @@ public class RegionFactory<S extends Space> {
* parts of it will be reused in the new region)
* @return a new region, result of {@code region1 minus region2}
*/
- public Region<S> difference(final Region<S> region1, final Region<S> region2) {
- final BSPTree<S> tree =
+ public Region<P> difference(final Region<P> region1, final Region<P> region2) {
+ final BSPTree<P> tree =
region1.getTree(false).merge(region2.getTree(false), new DifferenceMerger(region1, region2));
tree.visit(nodeCleaner);
return region1.buildNew(tree);
@@ -161,7 +160,7 @@ public class RegionFactory<S extends Space> {
* region independent region will be built
* @return a new region, complement of the specified one
*/
- public Region<S> getComplement(final Region<S> region) {
+ public Region<P> getComplement(final Region<P> region) {
return region.buildNew(recurseComplement(region.getTree(false)));
}
@@ -169,21 +168,21 @@ public class RegionFactory<S extends Space> {
* @param node current node of the original tree
* @return new tree, complement of the node
*/
- private BSPTree<S> recurseComplement(final BSPTree<S> node) {
+ private BSPTree<P> recurseComplement(final BSPTree<P> node) {
// transform the tree, except for boundary attribute splitters
- final Map<BSPTree<S>, BSPTree<S>> map = new HashMap<>();
- final BSPTree<S> transformedTree = recurseComplement(node, map);
+ final Map<BSPTree<P>, BSPTree<P>> map = new HashMap<>();
+ final BSPTree<P> transformedTree = recurseComplement(node, map);
// set up the boundary attributes splitters
- for (final Map.Entry<BSPTree<S>, BSPTree<S>> entry : map.entrySet()) {
+ for (final Map.Entry<BSPTree<P>, BSPTree<P>> entry : map.entrySet()) {
if (entry.getKey().getCut() != null) {
@SuppressWarnings("unchecked")
- BoundaryAttribute<S> original = (BoundaryAttribute<S>) entry.getKey().getAttribute();
+ BoundaryAttribute<P> original = (BoundaryAttribute<P>) entry.getKey().getAttribute();
if (original != null) {
@SuppressWarnings("unchecked")
- BoundaryAttribute<S> transformed = (BoundaryAttribute<S>) entry.getValue().getAttribute();
- for (final BSPTree<S> splitter : original.getSplitters()) {
+ BoundaryAttribute<P> transformed = (BoundaryAttribute<P>) entry.getValue().getAttribute();
+ for (final BSPTree<P> splitter : original.getSplitters()) {
transformed.getSplitters().add(map.get(splitter));
}
}
@@ -199,23 +198,23 @@ public class RegionFactory<S extends Space> {
* @param map transformed nodes map
* @return new tree, complement of the node
*/
- private BSPTree<S> recurseComplement(final BSPTree<S> node,
- final Map<BSPTree<S>, BSPTree<S>> map) {
+ private BSPTree<P> recurseComplement(final BSPTree<P> node,
+ final Map<BSPTree<P>, BSPTree<P>> map) {
- final BSPTree<S> transformedNode;
+ final BSPTree<P> transformedNode;
if (node.getCut() == null) {
transformedNode = new BSPTree<>(((Boolean) node.getAttribute()) ? Boolean.FALSE : Boolean.TRUE);
} else {
@SuppressWarnings("unchecked")
- BoundaryAttribute<S> attribute = (BoundaryAttribute<S>) node.getAttribute();
+ BoundaryAttribute<P> attribute = (BoundaryAttribute<P>) node.getAttribute();
if (attribute != null) {
- final SubHyperplane<S> plusOutside =
+ final SubHyperplane<P> plusOutside =
(attribute.getPlusInside() == null) ? null : attribute.getPlusInside().copySelf();
- final SubHyperplane<S> plusInside =
+ final SubHyperplane<P> plusInside =
(attribute.getPlusOutside() == null) ? null : attribute.getPlusOutside().copySelf();
// we start with an empty list of splitters, it will be filled in out of recursion
- attribute = new BoundaryAttribute<>(plusOutside, plusInside, new NodesSet<S>());
+ attribute = new BoundaryAttribute<>(plusOutside, plusInside, new NodesSet<P>());
}
transformedNode = new BSPTree<>(node.getCut().copySelf(),
@@ -230,11 +229,11 @@ public class RegionFactory<S extends Space> {
}
/** BSP tree leaf merger computing union of two regions. */
- private class UnionMerger implements BSPTree.LeafMerger<S> {
+ private class UnionMerger implements BSPTree.LeafMerger<P> {
/** {@inheritDoc} */
@Override
- public BSPTree<S> merge(final BSPTree<S> leaf, final BSPTree<S> tree,
- final BSPTree<S> parentTree,
+ public BSPTree<P> merge(final BSPTree<P> leaf, final BSPTree<P> tree,
+ final BSPTree<P> parentTree,
final boolean isPlusChild, final boolean leafFromInstance) {
if ((Boolean) leaf.getAttribute()) {
// the leaf node represents an inside cell
@@ -248,11 +247,11 @@ public class RegionFactory<S extends Space> {
}
/** BSP tree leaf merger computing intersection of two regions. */
- private class IntersectionMerger implements BSPTree.LeafMerger<S> {
+ private class IntersectionMerger implements BSPTree.LeafMerger<P> {
/** {@inheritDoc} */
@Override
- public BSPTree<S> merge(final BSPTree<S> leaf, final BSPTree<S> tree,
- final BSPTree<S> parentTree,
+ public BSPTree<P> merge(final BSPTree<P> leaf, final BSPTree<P> tree,
+ final BSPTree<P> parentTree,
final boolean isPlusChild, final boolean leafFromInstance) {
if ((Boolean) leaf.getAttribute()) {
// the leaf node represents an inside cell
@@ -266,13 +265,13 @@ public class RegionFactory<S extends Space> {
}
/** BSP tree leaf merger computing symmetric difference (exclusive or) of two regions. */
- private class XorMerger implements BSPTree.LeafMerger<S> {
+ private class XorMerger implements BSPTree.LeafMerger<P> {
/** {@inheritDoc} */
@Override
- public BSPTree<S> merge(final BSPTree<S> leaf, final BSPTree<S> tree,
- final BSPTree<S> parentTree, final boolean isPlusChild,
+ public BSPTree<P> merge(final BSPTree<P> leaf, final BSPTree<P> tree,
+ final BSPTree<P> parentTree, final boolean isPlusChild,
final boolean leafFromInstance) {
- BSPTree<S> t = tree;
+ BSPTree<P> t = tree;
if ((Boolean) leaf.getAttribute()) {
// the leaf node represents an inside cell
t = recurseComplement(t);
@@ -283,37 +282,37 @@ public class RegionFactory<S extends Space> {
}
/** BSP tree leaf merger computing difference of two regions. */
- private class DifferenceMerger implements BSPTree.LeafMerger<S>, VanishingCutHandler<S> {
+ private class DifferenceMerger implements BSPTree.LeafMerger<P>, VanishingCutHandler<P> {
/** Region to subtract from. */
- private final Region<S> region1;
+ private final Region<P> region1;
/** Region to subtract. */
- private final Region<S> region2;
+ private final Region<P> region2;
/** Simple constructor.
* @param region1 region to subtract from
* @param region2 region to subtract
*/
- DifferenceMerger(final Region<S> region1, final Region<S> region2) {
+ DifferenceMerger(final Region<P> region1, final Region<P> region2) {
this.region1 = region1.copySelf();
this.region2 = region2.copySelf();
}
/** {@inheritDoc} */
@Override
- public BSPTree<S> merge(final BSPTree<S> leaf, final BSPTree<S> tree,
- final BSPTree<S> parentTree, final boolean isPlusChild,
+ public BSPTree<P> merge(final BSPTree<P> leaf, final BSPTree<P> tree,
+ final BSPTree<P> parentTree, final boolean isPlusChild,
final boolean leafFromInstance) {
if ((Boolean) leaf.getAttribute()) {
// the leaf node represents an inside cell
- final BSPTree<S> argTree =
+ final BSPTree<P> argTree =
recurseComplement(leafFromInstance ? tree : leaf);
argTree.insertInTree(parentTree, isPlusChild, this);
return argTree;
}
// the leaf node represents an outside cell
- final BSPTree<S> instanceTree =
+ final BSPTree<P> instanceTree =
leafFromInstance ? leaf : tree;
instanceTree.insertInTree(parentTree, isPlusChild, this);
return instanceTree;
@@ -321,11 +320,11 @@ public class RegionFactory<S extends Space> {
/** {@inheritDoc} */
@Override
- public BSPTree<S> fixNode(final BSPTree<S> node) {
+ public BSPTree<P> fixNode(final BSPTree<P> node) {
// get a representative point in the degenerate cell
- final BSPTree<S> cell = node.pruneAroundConvexCell(Boolean.TRUE, Boolean.FALSE, null);
- final Region<S> r = region1.buildNew(cell);
- final Point<S> p = r.getBarycenter();
+ final BSPTree<P> cell = node.pruneAroundConvexCell(Boolean.TRUE, Boolean.FALSE, null);
+ final Region<P> r = region1.buildNew(cell);
+ final P p = r.getBarycenter();
return new BSPTree<>(region1.checkPoint(p) == Location.INSIDE &&
region2.checkPoint(p) == Location.OUTSIDE);
}
@@ -333,29 +332,29 @@ public class RegionFactory<S extends Space> {
}
/** Visitor removing internal nodes attributes. */
- private class NodesCleaner implements BSPTreeVisitor<S> {
+ private class NodesCleaner implements BSPTreeVisitor<P> {
/** {@inheritDoc} */
@Override
- public Order visitOrder(final BSPTree<S> node) {
+ public Order visitOrder(final BSPTree<P> node) {
return Order.PLUS_SUB_MINUS;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(final BSPTree<S> node) {
+ public void visitInternalNode(final BSPTree<P> node) {
node.setAttribute(null);
}
/** {@inheritDoc} */
@Override
- public void visitLeafNode(final BSPTree<S> node) {
+ public void visitLeafNode(final BSPTree<P> node) {
}
}
/** Handler replacing nodes with vanishing cuts with leaf nodes. */
- private class VanishingToLeaf implements VanishingCutHandler<S> {
+ private class VanishingToLeaf implements VanishingCutHandler<P> {
/** Inside/outside indocator to use for ambiguous nodes. */
private final boolean inside;
@@ -369,7 +368,7 @@ public class RegionFactory<S extends Space> {
/** {@inheritDoc} */
@Override
- public BSPTree<S> fixNode(final BSPTree<S> node) {
+ public BSPTree<P> fixNode(final BSPTree<P> node) {
if (node.getPlus().getAttribute().equals(node.getMinus().getAttribute())) {
// no ambiguity
return new BSPTree<>(node.getPlus().getAttribute());
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/SubHyperplane.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/SubHyperplane.java
index da8b24d..7237bb7 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/SubHyperplane.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/SubHyperplane.java
@@ -16,7 +16,7 @@
*/
package org.apache.commons.geometry.core.partitioning;
-import org.apache.commons.geometry.core.Space;
+import org.apache.commons.geometry.core.Point;
/** This interface represents the remaining parts of an hyperplane after
* other parts have been chopped off.
@@ -35,9 +35,9 @@ import org.apache.commons.geometry.core.Space;
* versions, which breaks compatibility for external implementations.
* </p>
- * @param <S> Type of the embedding space.
+ * @param <P> Point type defining the embedding space.
*/
-public interface SubHyperplane<S extends Space> {
+public interface SubHyperplane<P extends Point<P>> {
/** Copy the instance.
* <p>The instance created is completely independent of the original
@@ -46,12 +46,12 @@ public interface SubHyperplane<S extends Space> {
* objects).</p>
* @return a new sub-hyperplane, copy of the instance
*/
- SubHyperplane<S> copySelf();
+ SubHyperplane<P> copySelf();
/** Get the underlying hyperplane.
* @return underlying hyperplane
*/
- Hyperplane<S> getHyperplane();
+ Hyperplane<P> getHyperplane();
/** Check if the instance is empty.
* @return true if the instance is empty
@@ -70,19 +70,19 @@ public interface SubHyperplane<S extends Space> {
* on the plus side of the hyperplane and the part of the
* instance on the minus side of the hyperplane
*/
- SplitSubHyperplane<S> split(Hyperplane<S> hyperplane);
+ SplitSubHyperplane<P> split(Hyperplane<P> hyperplane);
/** Compute the union of the instance and another sub-hyperplane.
* @param other other sub-hyperplane to union (<em>must</em> be in the
* same hyperplane as the instance)
* @return a new sub-hyperplane, union of the instance and other
*/
- SubHyperplane<S> reunite(SubHyperplane<S> other);
+ SubHyperplane<P> reunite(SubHyperplane<P> other);
/** Class holding the results of the {@link #split split} method.
* @param <U> Type of the embedding space.
*/
- class SplitSubHyperplane<U extends Space> {
+ class SplitSubHyperplane<U extends Point<U>> {
/** Part of the sub-hyperplane on the plus side of the splitting hyperplane. */
private final SubHyperplane<U> plus;
diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Transform.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Transform.java
index a034d6c..53cb056 100644
--- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Transform.java
+++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/Transform.java
@@ -17,7 +17,6 @@
package org.apache.commons.geometry.core.partitioning;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** This interface represents an inversible affine transform in a space.
@@ -46,22 +45,22 @@ import org.apache.commons.geometry.core.Space;
* </li>
* </ul>
- * @param <S> Type of the embedding space.
- * @param <T> Type of the embedded sub-space.
+ * @param <P> Point type defining the embedding space.
+ * @param <S> Point type defining the embedded sub-space.
*/
-public interface Transform<S extends Space, T extends Space> {
+public interface Transform<P extends Point<P>, S extends Point<S>> {
/** Transform a point of a space.
* @param point point to transform
* @return a new object representing the transformed point
*/
- Point<S> apply(Point<S> point);
+ P apply(P point);
/** Transform an hyperplane of a space.
* @param hyperplane hyperplane to transform
* @return a new object representing the transformed hyperplane
*/
- Hyperplane<S> apply(Hyperplane<S> hyperplane);
+ Hyperplane<P> apply(Hyperplane<P> hyperplane);
/** Transform a sub-hyperplane embedded in an hyperplane.
* @param sub sub-hyperplane to transform
@@ -73,6 +72,6 @@ public interface Transform<S extends Space, T extends Space> {
* <em>has</em> been applied to it)
* @return a new object representing the transformed sub-hyperplane
*/
- SubHyperplane<T> apply(SubHyperplane<T> sub, Hyperplane<S> original, Hyperplane<S> transformed);
+ SubHyperplane<S> apply(SubHyperplane<S> sub, Hyperplane<P> original, Hyperplane<P> transformed);
}
diff --git a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeBuilder.java b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeBuilder.java
index 364d702..3ad8e8e 100644
--- a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeBuilder.java
+++ b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeBuilder.java
@@ -20,15 +20,12 @@ import java.io.IOException;
import java.text.ParseException;
import java.util.StringTokenizer;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.partitioning.AbstractRegion;
-import org.apache.commons.geometry.core.partitioning.BSPTree;
-import org.apache.commons.geometry.core.partitioning.Hyperplane;
+import org.apache.commons.geometry.core.Point;
/** Local class for building an {@link AbstractRegion} tree.
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public abstract class TreeBuilder<S extends Space> {
+public abstract class TreeBuilder<P extends Point<P>> {
/** Keyword for tolerance. */
private static final String TOLERANCE = "tolerance";
@@ -52,7 +49,7 @@ public abstract class TreeBuilder<S extends Space> {
private static final String FALSE = "false";
/** Tree root. */
- private BSPTree<S> root;
+ private BSPTree<P> root;
/** Tolerance. */
private final double tolerance;
@@ -86,7 +83,7 @@ public abstract class TreeBuilder<S extends Space> {
* @exception IOException if the string cannot be read
* @exception ParseException if the string cannot be parsed
*/
- private void parseTree(final BSPTree<S> node)
+ private void parseTree(final BSPTree<P> node)
throws IOException, ParseException {
if (INTERNAL.equals(getWord(INTERNAL, LEAF))) {
// this is an internal node, it has a cut sub-hyperplane (stored as a whole hyperplane)
@@ -142,7 +139,7 @@ public abstract class TreeBuilder<S extends Space> {
/** Get the built tree.
* @return built tree
*/
- public BSPTree<S> getTree() {
+ public BSPTree<P> getTree() {
return root;
}
@@ -158,7 +155,7 @@ public abstract class TreeBuilder<S extends Space> {
* @exception IOException if the string cannot be read
* @exception ParseException if the string cannot be parsed
*/
- protected abstract Hyperplane<S> parseHyperplane()
+ protected abstract Hyperplane<P> parseHyperplane()
throws IOException, ParseException;
}
\ No newline at end of file
diff --git a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeDumper.java b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeDumper.java
index 532b9f9..6c1285f 100644
--- a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeDumper.java
+++ b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreeDumper.java
@@ -19,15 +19,12 @@ package org.apache.commons.geometry.core.partitioning;
import java.util.Formatter;
import java.util.Locale;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.partitioning.BSPTree;
-import org.apache.commons.geometry.core.partitioning.BSPTreeVisitor;
-import org.apache.commons.geometry.core.partitioning.Hyperplane;
+import org.apache.commons.geometry.core.Point;
/** Dumping visitor.
- * @param <S> Type of the space.
+ * @param <P> Point type defining the space
*/
-public abstract class TreeDumper<S extends Space> implements BSPTreeVisitor<S> {
+public abstract class TreeDumper<P extends Point<P>> implements BSPTreeVisitor<P> {
/** Builder for the string representation of the dumped tree. */
private final StringBuilder dump;
@@ -66,17 +63,17 @@ public abstract class TreeDumper<S extends Space> implements BSPTreeVisitor<S> {
/** Format a string representation of the hyperplane underlying a cut sub-hyperplane.
* @param hyperplane hyperplane to format
*/
- protected abstract void formatHyperplane(Hyperplane<S> hyperplane);
+ protected abstract void formatHyperplane(Hyperplane<P> hyperplane);
/** {@inheritDoc} */
@Override
- public Order visitOrder(final BSPTree<S> node) {
+ public Order visitOrder(final BSPTree<P> node) {
return Order.SUB_MINUS_PLUS;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(final BSPTree<S> node) {
+ public void visitInternalNode(final BSPTree<P> node) {
formatter.format("%s %s internal ", prefix, type(node));
formatHyperplane(node.getCut().getHyperplane());
formatter.format("%n");
@@ -85,10 +82,10 @@ public abstract class TreeDumper<S extends Space> implements BSPTreeVisitor<S> {
/** {@inheritDoc} */
@Override
- public void visitLeafNode(final BSPTree<S> node) {
+ public void visitLeafNode(final BSPTree<P> node) {
formatter.format("%s %s leaf %s%n",
prefix, type(node), node.getAttribute());
- for (BSPTree<S> n = node;
+ for (BSPTree<P> n = node;
n.getParent() != null && n == n.getParent().getPlus();
n = n.getParent()) {
prefix = prefix.substring(0, prefix.length() - 2);
@@ -100,7 +97,7 @@ public abstract class TreeDumper<S extends Space> implements BSPTreeVisitor<S> {
* @return "plus " or "minus" depending on the node being the plus or minus
* child of its parent ("plus " is arbitrarily returned for the root node)
*/
- private String type(final BSPTree<S> node) {
+ private String type(final BSPTree<P> node) {
return (node.getParent() != null && node == node.getParent().getMinus()) ? "minus" : "plus ";
}
}
diff --git a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreePrinter.java b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreePrinter.java
index 6f79537..75acd92 100644
--- a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreePrinter.java
+++ b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/TreePrinter.java
@@ -18,14 +18,12 @@ package org.apache.commons.geometry.core.partitioning;
import java.util.Objects;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.partitioning.BSPTree;
-import org.apache.commons.geometry.core.partitioning.BSPTreeVisitor;
+import org.apache.commons.geometry.core.Point;
/** Base for classes that create string representations of {@link BSPTree}s.
- * @param <S>
+ * @param <P> Point type defining the space
*/
-public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S> {
+public abstract class TreePrinter<P extends Point<P>> implements BSPTreeVisitor<P> {
/** Indent per tree level */
protected static final String INDENT = " ";
@@ -40,7 +38,7 @@ public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S>
* @param tree
* @return
*/
- public String writeAsString(BSPTree<S> tree) {
+ public String writeAsString(BSPTree<P> tree) {
output.delete(0, output.length());
tree.visit(this);
@@ -50,13 +48,13 @@ public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S>
/** {@inheritDoc} */
@Override
- public Order visitOrder(BSPTree<S> node) {
+ public Order visitOrder(BSPTree<P> node) {
return Order.SUB_MINUS_PLUS;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(BSPTree<S> node) {
+ public void visitInternalNode(BSPTree<P> node) {
writeLinePrefix(node);
writeInternalNode(node);
@@ -67,13 +65,13 @@ public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S>
/** {@inheritDoc} */
@Override
- public void visitLeafNode(BSPTree<S> node) {
+ public void visitLeafNode(BSPTree<P> node) {
writeLinePrefix(node);
writeLeafNode(node);
write("\n");
- BSPTree<S> cur = node;
+ BSPTree<P> cur = node;
while (cur.getParent() != null && cur.getParent().getPlus() == cur) {
--depth;
cur = cur.getParent();
@@ -85,7 +83,7 @@ public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S>
* for the node itself.
* @param node
*/
- protected void writeLinePrefix(BSPTree<S> node) {
+ protected void writeLinePrefix(BSPTree<P> node) {
for (int i=0; i<depth; ++i) {
write(INDENT);
}
@@ -106,7 +104,7 @@ public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S>
* @param node
* @return
*/
- protected String nodeIdString(BSPTree<S> node) {
+ protected String nodeIdString(BSPTree<P> node) {
String str = Objects.toString(node);
int idx = str.lastIndexOf('.');
if (idx > -1) {
@@ -125,13 +123,13 @@ public abstract class TreePrinter<S extends Space> implements BSPTreeVisitor<S>
/** Method for subclasses to provide their own string representation
* of the given internal node.
*/
- protected abstract void writeInternalNode(BSPTree<S> node);
+ protected abstract void writeInternalNode(BSPTree<P> 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) {
+ protected void writeLeafNode(BSPTree<P> node) {
write(String.valueOf(node.getAttribute()));
}
}
\ No newline at end of file
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/Encloser.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/Encloser.java
index a99023a..7fd1f18 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/Encloser.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/Encloser.java
@@ -17,19 +17,18 @@
package org.apache.commons.geometry.enclosing;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** Interface for algorithms computing enclosing balls.
* @param <S> Space type.
* @param <P> Point type.
* @see EnclosingBall
*/
-public interface Encloser<S extends Space, P extends Point<S>> {
+public interface Encloser<P extends Point<P>> {
/** Find a ball enclosing a list of points.
* @param points points to enclose
* @return enclosing ball
*/
- EnclosingBall<S, P> enclose(Iterable<P> points);
+ EnclosingBall<P> enclose(Iterable<P> points);
}
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/EnclosingBall.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/EnclosingBall.java
index b269747..7ed537b 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/EnclosingBall.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/EnclosingBall.java
@@ -19,7 +19,6 @@ package org.apache.commons.geometry.enclosing;
import java.io.Serializable;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** This class represents a ball enclosing some points.
* @param <S> Space type.
@@ -28,7 +27,7 @@ import org.apache.commons.geometry.core.Space;
* @see Point
* @see Encloser
*/
-public class EnclosingBall<S extends Space, P extends Point<S>> implements Serializable {
+public class EnclosingBall<P extends Point<P>> implements Serializable {
/** Serializable UID. */
private static final long serialVersionUID = 20140126L;
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/SupportBallGenerator.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/SupportBallGenerator.java
index 53a9229..6d0e603 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/SupportBallGenerator.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/SupportBallGenerator.java
@@ -19,7 +19,6 @@ package org.apache.commons.geometry.enclosing;
import java.util.List;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** Interface for generating balls based on support points.
* <p>
@@ -30,12 +29,12 @@ import org.apache.commons.geometry.core.Space;
* @param <P> Point type.
* @see EnclosingBall
*/
-public interface SupportBallGenerator<S extends Space, P extends Point<S>> {
+public interface SupportBallGenerator<P extends Point<P>> {
/** Create a ball whose boundary lies on prescribed support points.
* @param support support points (may be empty)
* @return ball whose boundary lies on the prescribed support points
*/
- EnclosingBall<S, P> ballOnSupport(List<P> support);
+ EnclosingBall<P> ballOnSupport(List<P> support);
}
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java
index c20c706..f825ade 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/enclosing/WelzlEncloser.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
/** Class implementing Emo Welzl algorithm to find the smallest enclosing ball in linear time.
* <p>
@@ -38,26 +37,26 @@ import org.apache.commons.geometry.core.Space;
* @param <S> Space type.
* @param <P> Point type.
*/
-public class WelzlEncloser<S extends Space, P extends Point<S>> implements Encloser<S, P> {
+public class WelzlEncloser<P extends Point<P>> implements Encloser<P> {
/** Tolerance below which points are consider to be identical. */
private final double tolerance;
/** Generator for balls on support. */
- private final SupportBallGenerator<S, P> generator;
+ private final SupportBallGenerator<P> generator;
/** Simple constructor.
* @param tolerance below which points are consider to be identical
* @param generator generator for balls on support
*/
- public WelzlEncloser(final double tolerance, final SupportBallGenerator<S, P> generator) {
+ public WelzlEncloser(final double tolerance, final SupportBallGenerator<P> generator) {
this.tolerance = tolerance;
this.generator = generator;
}
/** {@inheritDoc} */
@Override
- public EnclosingBall<S, P> enclose(final Iterable<P> points) {
+ public EnclosingBall<P> enclose(final Iterable<P> points) {
if (points == null || !points.iterator().hasNext()) {
// return an empty ball
@@ -73,15 +72,15 @@ public class WelzlEncloser<S extends Space, P extends Point<S>> implements Enclo
* @param points points to be enclosed
* @return enclosing ball
*/
- private EnclosingBall<S, P> pivotingBall(final Iterable<P> points) {
+ private EnclosingBall<P> pivotingBall(final Iterable<P> points) {
final P first = points.iterator().next();
- final List<P> extreme = new ArrayList<>(first.getSpace().getDimension() + 1);
- final List<P> support = new ArrayList<>(first.getSpace().getDimension() + 1);
+ final List<P> extreme = new ArrayList<>(first.getDimension() + 1);
+ final List<P> support = new ArrayList<>(first.getDimension() + 1);
// start with only first point selected as a candidate support
extreme.add(first);
- EnclosingBall<S, P> ball = moveToFrontBall(extreme, extreme.size(), support);
+ EnclosingBall<P> ball = moveToFrontBall(extreme, extreme.size(), support);
while (true) {
@@ -96,7 +95,7 @@ public class WelzlEncloser<S extends Space, P extends Point<S>> implements Enclo
// recurse search, restricted to the small subset containing support and farthest point
support.clear();
support.add(farthest);
- EnclosingBall<S, P> savedBall = ball;
+ EnclosingBall<P> savedBall = ball;
ball = moveToFrontBall(extreme, extreme.size(), support);
if (ball.getRadius() < savedBall.getRadius()) {
// this should never happen
@@ -120,13 +119,13 @@ public class WelzlEncloser<S extends Space, P extends Point<S>> implements Enclo
* @param support points that must belong to the ball support
* @return enclosing ball, for the extreme subset only
*/
- private EnclosingBall<S, P> moveToFrontBall(final List<P> extreme, final int nbExtreme,
+ private EnclosingBall<P> moveToFrontBall(final List<P> extreme, final int nbExtreme,
final List<P> support) {
// create a new ball on the prescribed support
- EnclosingBall<S, P> ball = generator.ballOnSupport(support);
+ EnclosingBall<P> ball = generator.ballOnSupport(support);
- if (ball.getSupportSize() <= ball.getCenter().getSpace().getDimension()) {
+ if (ball.getSupportSize() <= ball.getCenter().getDimension()) {
for (int i = 0; i < nbExtreme; ++i) {
final P pi = extreme.get(i);
@@ -159,7 +158,7 @@ public class WelzlEncloser<S extends Space, P extends Point<S>> implements Enclo
* @param ball current ball
* @return farthest point
*/
- public P selectFarthest(final Iterable<P> points, final EnclosingBall<S, P> ball) {
+ public P selectFarthest(final Iterable<P> points, final EnclosingBall<P> ball) {
final P center = ball.getCenter();
P farthest = null;
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGenerator.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGenerator.java
index 5bdc69c..a124cf3 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGenerator.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGenerator.java
@@ -21,42 +21,40 @@ import java.util.List;
import org.apache.commons.geometry.enclosing.EnclosingBall;
import org.apache.commons.geometry.enclosing.SupportBallGenerator;
-import org.apache.commons.geometry.euclidean.threed.Cartesian3D;
-import org.apache.commons.geometry.euclidean.threed.Euclidean3D;
import org.apache.commons.geometry.euclidean.threed.Plane;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
+import org.apache.commons.geometry.euclidean.threed.Point3D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
import org.apache.commons.geometry.euclidean.twod.enclosing.DiskGenerator;
import org.apache.commons.numbers.fraction.BigFraction;
/** Class generating an enclosing ball from its support points.
*/
-public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Cartesian3D> {
+public class SphereGenerator implements SupportBallGenerator<Point3D> {
/** {@inheritDoc} */
@Override
- public EnclosingBall<Euclidean3D, Cartesian3D> ballOnSupport(final List<Cartesian3D> support) {
+ public EnclosingBall<Point3D> ballOnSupport(final List<Point3D> support) {
if (support.size() < 1) {
- return new EnclosingBall<>(Cartesian3D.ZERO, Double.NEGATIVE_INFINITY);
+ return new EnclosingBall<>(Point3D.ZERO, Double.NEGATIVE_INFINITY);
} else {
- final Cartesian3D vA = support.get(0);
+ final Point3D vA = support.get(0);
if (support.size() < 2) {
return new EnclosingBall<>(vA, 0, vA);
} else {
- final Cartesian3D vB = support.get(1);
+ final Point3D vB = support.get(1);
if (support.size() < 3) {
- return new EnclosingBall<>(new Cartesian3D(0.5, vA, 0.5, vB),
+ return new EnclosingBall<>(Point3D.vectorCombination(0.5, vA, 0.5, vB),
0.5 * vA.distance(vB),
vA, vB);
} else {
- final Cartesian3D vC = support.get(2);
+ final Point3D vC = support.get(2);
if (support.size() < 4) {
// delegate to 2D disk generator
final Plane p = new Plane(vA, vB, vC,
- 1.0e-10 * (vA.getNorm1() + vB.getNorm1() + vC.getNorm1()));
- final EnclosingBall<Euclidean2D, Cartesian2D> disk =
+ 1.0e-10 * (vA.asVector().getNorm1() + vB.asVector().getNorm1() + vC.asVector().getNorm1()));
+ final EnclosingBall<Point2D> disk =
new DiskGenerator().ballOnSupport(Arrays.asList(p.toSubSpace(vA),
p.toSubSpace(vB),
p.toSubSpace(vC)));
@@ -66,7 +64,7 @@ public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Cartes
disk.getRadius(), vA, vB, vC);
} else {
- final Cartesian3D vD = support.get(3);
+ final Point3D vD = support.get(3);
// a sphere is 3D can be defined as:
// (1) (x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 = r^2
// which can be written:
@@ -119,7 +117,7 @@ public class SphereGenerator implements SupportBallGenerator<Euclidean3D, Cartes
final BigFraction dy = c3[0].subtract(centerY);
final BigFraction dz = c4[0].subtract(centerZ);
final BigFraction r2 = dx.multiply(dx).add(dy.multiply(dy)).add(dz.multiply(dz));
- return new EnclosingBall<>(new Cartesian3D(centerX.doubleValue(),
+ return new EnclosingBall<>(new Point3D(centerX.doubleValue(),
centerY.doubleValue(),
centerZ.doubleValue()),
Math.sqrt(r2.doubleValue()),
diff --git a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGenerator.java b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGenerator.java
index 52b5626..c2b9acc 100644
--- a/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGenerator.java
+++ b/commons-geometry-enclosing/src/main/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGenerator.java
@@ -18,34 +18,33 @@ package org.apache.commons.geometry.euclidean.twod.enclosing;
import java.util.List;
-import org.apache.commons.numbers.fraction.BigFraction;
import org.apache.commons.geometry.enclosing.EnclosingBall;
import org.apache.commons.geometry.enclosing.SupportBallGenerator;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
+import org.apache.commons.numbers.fraction.BigFraction;
/** Class generating an enclosing ball from its support points.
*/
-public class DiskGenerator implements SupportBallGenerator<Euclidean2D, Cartesian2D> {
+public class DiskGenerator implements SupportBallGenerator<Point2D> {
/** {@inheritDoc} */
@Override
- public EnclosingBall<Euclidean2D, Cartesian2D> ballOnSupport(final List<Cartesian2D> support) {
+ public EnclosingBall<Point2D> ballOnSupport(final List<Point2D> support) {
if (support.size() < 1) {
- return new EnclosingBall<>(Cartesian2D.ZERO, Double.NEGATIVE_INFINITY);
+ return new EnclosingBall<>(Point2D.ZERO, Double.NEGATIVE_INFINITY);
} else {
- final Cartesian2D vA = support.get(0);
+ final Point2D vA = support.get(0);
if (support.size() < 2) {
return new EnclosingBall<>(vA, 0, vA);
} else {
- final Cartesian2D vB = support.get(1);
+ final Point2D vB = support.get(1);
if (support.size() < 3) {
- return new EnclosingBall<>(new Cartesian2D(0.5, vA, 0.5, vB),
+ return new EnclosingBall<>(Point2D.vectorCombination(0.5, vA, 0.5, vB),
0.5 * vA.distance(vB),
vA, vB);
} else {
- final Cartesian2D vC = support.get(2);
+ final Point2D vC = support.get(2);
// a disk is 2D can be defined as:
// (1) (x - x_0)^2 + (y - y_0)^2 = r^2
// which can be written:
@@ -86,7 +85,7 @@ public class DiskGenerator implements SupportBallGenerator<Euclidean2D, Cartesia
final BigFraction dx = c2[0].subtract(centerX);
final BigFraction dy = c3[0].subtract(centerY);
final BigFraction r2 = dx.multiply(dx).add(dy.multiply(dy));
- return new EnclosingBall<>(new Cartesian2D(centerX.doubleValue(),
+ return new EnclosingBall<>(new Point2D(centerX.doubleValue(),
centerY.doubleValue()),
Math.sqrt(r2.doubleValue()),
vA, vB, vC);
diff --git a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser2DTest.java b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser2DTest.java
index 21d9cd6..8a975e1 100644
--- a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser2DTest.java
+++ b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser2DTest.java
@@ -20,11 +20,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.apache.commons.geometry.enclosing.EnclosingBall;
-import org.apache.commons.geometry.enclosing.WelzlEncloser;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
import org.apache.commons.geometry.euclidean.twod.enclosing.DiskGenerator;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.simple.RandomSource;
import org.junit.Assert;
@@ -36,36 +33,36 @@ public class WelzlEncloser2DTest {
@Test
public void testNullList() {
DiskGenerator generator = new DiskGenerator();
- WelzlEncloser<Euclidean2D, Cartesian2D> encloser =
+ WelzlEncloser<Point2D> encloser =
new WelzlEncloser<>(1.0e-10, generator);
- EnclosingBall<Euclidean2D, Cartesian2D> ball = encloser.enclose(null);
+ EnclosingBall<Point2D> ball = encloser.enclose(null);
Assert.assertTrue(ball.getRadius() < 0);
}
@Test
public void testNoPoints() {
DiskGenerator generator = new DiskGenerator();
- WelzlEncloser<Euclidean2D, Cartesian2D> encloser =
+ WelzlEncloser<Point2D> encloser =
new WelzlEncloser<>(1.0e-10, generator);
- EnclosingBall<Euclidean2D, Cartesian2D> ball = encloser.enclose(new ArrayList<Cartesian2D>());
+ EnclosingBall<Point2D> ball = encloser.enclose(new ArrayList<Point2D>());
Assert.assertTrue(ball.getRadius() < 0);
}
@Test
public void testRegularPoints() {
- List<Cartesian2D> list = buildList(22, 26, 30, 38, 64, 28, 8, 54, 11, 15);
+ List<Point2D> list = buildList(22, 26, 30, 38, 64, 28, 8, 54, 11, 15);
checkDisk(list, Arrays.asList(list.get(2), list.get(3), list.get(4)));
}
@Test
public void testSolutionOnDiameter() {
- List<Cartesian2D> list = buildList(22, 26, 30, 38, 64, 28, 8, 54);
+ List<Point2D> list = buildList(22, 26, 30, 38, 64, 28, 8, 54);
checkDisk(list, Arrays.asList(list.get(2), list.get(3)));
}
@Test
public void testReducingBall1() {
- List<Cartesian2D> list = buildList(0.05380958511396061, 0.57332359658700000,
+ List<Point2D> list = buildList(0.05380958511396061, 0.57332359658700000,
0.99348810731127870, 0.02056421361521466,
0.01203950647796437, 0.99779675042261860,
0.00810189987706078, 0.00589246003827815,
@@ -75,7 +72,7 @@ public class WelzlEncloser2DTest {
@Test
public void testReducingBall2() {
- List<Cartesian2D> list = buildList(0.016930586154703, 0.333955448537779,
+ List<Point2D> list = buildList(0.016930586154703, 0.333955448537779,
0.987189104892331, 0.969778855274507,
0.983696889599935, 0.012904580013266,
0.013114499572905, 0.034740156356895);
@@ -87,39 +84,39 @@ public class WelzlEncloser2DTest {
UniformRandomProvider random = RandomSource.create(RandomSource.WELL_1024_A, 0xa2a63cad12c01fb2l);
for (int k = 0; k < 100; ++k) {
int nbPoints = random.nextInt(10000);
- List<Cartesian2D> points = new ArrayList<>();
+ List<Point2D> points = new ArrayList<>();
for (int i = 0; i < nbPoints; ++i) {
double x = random.nextDouble();
double y = random.nextDouble();
- points.add(new Cartesian2D(x, y));
+ points.add(new Point2D(x, y));
}
checkDisk(points);
}
}
- private List<Cartesian2D> buildList(final double ... coordinates) {
- List<Cartesian2D> list = new ArrayList<>(coordinates.length / 2);
+ private List<Point2D> buildList(final double ... coordinates) {
+ List<Point2D> list = new ArrayList<>(coordinates.length / 2);
for (int i = 0; i < coordinates.length; i += 2) {
- list.add(new Cartesian2D(coordinates[i], coordinates[i + 1]));
+ list.add(new Point2D(coordinates[i], coordinates[i + 1]));
}
return list;
}
- private void checkDisk(List<Cartesian2D> points, List<Cartesian2D> refSupport) {
+ private void checkDisk(List<Point2D> points, List<Point2D> refSupport) {
- EnclosingBall<Euclidean2D, Cartesian2D> disk = checkDisk(points);
+ EnclosingBall<Point2D> disk = checkDisk(points);
// compare computed disk with expected disk
DiskGenerator generator = new DiskGenerator();
- EnclosingBall<Euclidean2D, Cartesian2D> expected = generator.ballOnSupport(refSupport);
+ EnclosingBall<Point2D> expected = generator.ballOnSupport(refSupport);
Assert.assertEquals(refSupport.size(), disk.getSupportSize());
Assert.assertEquals(expected.getRadius(), disk.getRadius(), 1.0e-10);
Assert.assertEquals(expected.getCenter().getX(), disk.getCenter().getX(), 1.0e-10);
Assert.assertEquals(expected.getCenter().getY(), disk.getCenter().getY(), 1.0e-10);
- for (Cartesian2D s : disk.getSupport()) {
+ for (Point2D s : disk.getSupport()) {
boolean found = false;
- for (Cartesian2D rs : refSupport) {
+ for (Point2D rs : refSupport) {
if (s == rs) {
found = true;
}
@@ -129,14 +126,14 @@ public class WelzlEncloser2DTest {
// check removing any point of the support disk fails to enclose the point
for (int i = 0; i < disk.getSupportSize(); ++i) {
- List<Cartesian2D> reducedSupport = new ArrayList<>();
+ List<Point2D> reducedSupport = new ArrayList<>();
int count = 0;
- for (Cartesian2D s : disk.getSupport()) {
+ for (Point2D s : disk.getSupport()) {
if (count++ != i) {
reducedSupport.add(s);
}
}
- EnclosingBall<Euclidean2D, Cartesian2D> reducedDisk = generator.ballOnSupport(reducedSupport);
+ EnclosingBall<Point2D> reducedDisk = generator.ballOnSupport(reducedSupport);
boolean foundOutside = false;
for (int j = 0; j < points.size() && !foundOutside; ++j) {
if (!reducedDisk.contains(points.get(j), 1.0e-10)) {
@@ -148,20 +145,20 @@ public class WelzlEncloser2DTest {
}
- private EnclosingBall<Euclidean2D, Cartesian2D> checkDisk(List<Cartesian2D> points) {
+ private EnclosingBall<Point2D> checkDisk(List<Point2D> points) {
- WelzlEncloser<Euclidean2D, Cartesian2D> encloser =
+ WelzlEncloser<Point2D> encloser =
new WelzlEncloser<>(1.0e-10, new DiskGenerator());
- EnclosingBall<Euclidean2D, Cartesian2D> disk = encloser.enclose(points);
+ EnclosingBall<Point2D> disk = encloser.enclose(points);
// all points are enclosed
- for (Cartesian2D v : points) {
+ for (Point2D v : points) {
Assert.assertTrue(disk.contains(v, 1.0e-10));
}
- for (Cartesian2D v : points) {
+ for (Point2D v : points) {
boolean inSupport = false;
- for (Cartesian2D s : disk.getSupport()) {
+ for (Point2D s : disk.getSupport()) {
if (v == s) {
inSupport = true;
}
diff --git a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser3DTest.java b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser3DTest.java
index 0466b48..e874ca7 100644
--- a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser3DTest.java
+++ b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/enclosing/WelzlEncloser3DTest.java
@@ -21,16 +21,13 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
+import org.apache.commons.geometry.euclidean.threed.Point3D;
+import org.apache.commons.geometry.euclidean.threed.enclosing.SphereGenerator;
import org.apache.commons.rng.UniformRandomProvider;
-import org.apache.commons.rng.simple.RandomSource;
import org.apache.commons.rng.sampling.UnitSphereSampler;
-import org.apache.commons.geometry.enclosing.EnclosingBall;
-import org.apache.commons.geometry.enclosing.WelzlEncloser;
-import org.apache.commons.geometry.euclidean.threed.Euclidean3D;
-import org.apache.commons.geometry.euclidean.threed.enclosing.SphereGenerator;
-import org.apache.commons.geometry.euclidean.threed.Cartesian3D;
+import org.apache.commons.rng.simple.RandomSource;
+import org.junit.Assert;
+import org.junit.Test;
public class WelzlEncloser3DTest {
@@ -38,67 +35,67 @@ public class WelzlEncloser3DTest {
@Test
public void testNullList() {
SphereGenerator generator = new SphereGenerator();
- WelzlEncloser<Euclidean3D, Cartesian3D> encloser =
+ WelzlEncloser<Point3D> encloser =
new WelzlEncloser<>(1.0e-10, generator);
- EnclosingBall<Euclidean3D, Cartesian3D> ball = encloser.enclose(null);
+ EnclosingBall<Point3D> ball = encloser.enclose(null);
Assert.assertTrue(ball.getRadius() < 0);
}
@Test
public void testNoPoints() {
SphereGenerator generator = new SphereGenerator();
- WelzlEncloser<Euclidean3D, Cartesian3D> encloser =
+ WelzlEncloser<Point3D> encloser =
new WelzlEncloser<>(1.0e-10, generator);
- EnclosingBall<Euclidean3D, Cartesian3D> ball = encloser.enclose(new ArrayList<Cartesian3D>());
+ EnclosingBall<Point3D> ball = encloser.enclose(new ArrayList<Point3D>());
Assert.assertTrue(ball.getRadius() < 0);
}
@Test
public void testReducingBall() {
- List<Cartesian3D> list =
- Arrays.asList(new Cartesian3D(-7.140397329568118, -16.571661242582177, 11.714458961735405),
- new Cartesian3D(-7.137986707455888, -16.570767323375720, 11.708602108715928),
- new Cartesian3D(-7.139185068549035, -16.570891204702250, 11.715554057357394),
- new Cartesian3D(-7.142682716997507, -16.571609818234290, 11.710787934580328),
- new Cartesian3D(-7.139018392423351, -16.574405614157020, 11.710518716711425),
- new Cartesian3D(-7.140870659936730, -16.567993074240455, 11.710914678204503),
- new Cartesian3D(-7.136350173659562, -16.570498228820930, 11.713965225900928),
- new Cartesian3D(-7.141675762759172, -16.572852471407028, 11.714033471449508),
- new Cartesian3D(-7.140453077221105, -16.570212820780647, 11.708624578004980),
- new Cartesian3D(-7.140322188726825, -16.574152894557717, 11.710305611121410),
- new Cartesian3D(-7.141116131477088, -16.574061164624560, 11.712938509321699));
- WelzlEncloser<Euclidean3D, Cartesian3D> encloser =
+ List<Point3D> list =
+ Arrays.asList(new Point3D(-7.140397329568118, -16.571661242582177, 11.714458961735405),
+ new Point3D(-7.137986707455888, -16.570767323375720, 11.708602108715928),
+ new Point3D(-7.139185068549035, -16.570891204702250, 11.715554057357394),
+ new Point3D(-7.142682716997507, -16.571609818234290, 11.710787934580328),
+ new Point3D(-7.139018392423351, -16.574405614157020, 11.710518716711425),
+ new Point3D(-7.140870659936730, -16.567993074240455, 11.710914678204503),
+ new Point3D(-7.136350173659562, -16.570498228820930, 11.713965225900928),
+ new Point3D(-7.141675762759172, -16.572852471407028, 11.714033471449508),
+ new Point3D(-7.140453077221105, -16.570212820780647, 11.708624578004980),
+ new Point3D(-7.140322188726825, -16.574152894557717, 11.710305611121410),
+ new Point3D(-7.141116131477088, -16.574061164624560, 11.712938509321699));
+ WelzlEncloser<Point3D> encloser =
new WelzlEncloser<>(1.0e-10, new SphereGenerator());
- EnclosingBall<Euclidean3D, Cartesian3D> ball = encloser.enclose(list);
+ EnclosingBall<Point3D> ball = encloser.enclose(list);
Assert.assertTrue(ball.getRadius() > 0);
}
@Test
public void testInfiniteLoop() {
// this test used to generate an infinite loop
- List<Cartesian3D> list =
- Arrays.asList(new Cartesian3D( -0.89227075512164380, -2.89317694645713900, 14.84572323743355500),
- new Cartesian3D( -0.92099498940693580, -2.31086108263908940, 12.92071026467688300),
- new Cartesian3D( -0.85227999411005200, -3.06314731441320730, 15.40163831651287000),
- new Cartesian3D( -1.77399413020785970, -3.65630391378114260, 14.13190097751873400),
- new Cartesian3D( 0.33157833272465354, -2.22813591757792160, 14.21225234159008200),
- new Cartesian3D( -1.53065579165484400, -1.65692084770139570, 14.61483055714788500),
- new Cartesian3D( -1.08457093941217140, -1.96100325935602980, 13.09265170575555000),
- new Cartesian3D( 0.30029469589708850, -3.05470831395667370, 14.56352400426342600),
- new Cartesian3D( -0.95007443938638460, -1.86810946486118360, 15.14491234340057000),
- new Cartesian3D( -1.89661503804130830, -2.17004080885185860, 14.81235128513927000),
- new Cartesian3D( -0.72193328761607530, -1.44513142833618270, 14.52355724218561800),
- new Cartesian3D( -0.26895980939606550, -3.69512371522084140, 14.72272846327652000),
- new Cartesian3D( -1.53501693431786170, -3.25055166611021900, 15.15509062584274800),
- new Cartesian3D( -0.71727553535519410, -3.62284279460799100, 13.26256700929380700),
- new Cartesian3D( -0.30220950676137365, -3.25410412500779070, 13.13682612771606000),
- new Cartesian3D( -0.04543996608267075, -1.93081853923797750, 14.79497997883171400),
- new Cartesian3D( -1.53348892951571640, -3.66688919703524900, 14.73095600812074200),
- new Cartesian3D( -0.98034899533935820, -3.34004481162763960, 13.03245014017556800));
-
- WelzlEncloser<Euclidean3D, Cartesian3D> encloser =
+ List<Point3D> list =
+ Arrays.asList(new Point3D( -0.89227075512164380, -2.89317694645713900, 14.84572323743355500),
+ new Point3D( -0.92099498940693580, -2.31086108263908940, 12.92071026467688300),
+ new Point3D( -0.85227999411005200, -3.06314731441320730, 15.40163831651287000),
+ new Point3D( -1.77399413020785970, -3.65630391378114260, 14.13190097751873400),
+ new Point3D( 0.33157833272465354, -2.22813591757792160, 14.21225234159008200),
+ new Point3D( -1.53065579165484400, -1.65692084770139570, 14.61483055714788500),
+ new Point3D( -1.08457093941217140, -1.96100325935602980, 13.09265170575555000),
+ new Point3D( 0.30029469589708850, -3.05470831395667370, 14.56352400426342600),
+ new Point3D( -0.95007443938638460, -1.86810946486118360, 15.14491234340057000),
+ new Point3D( -1.89661503804130830, -2.17004080885185860, 14.81235128513927000),
+ new Point3D( -0.72193328761607530, -1.44513142833618270, 14.52355724218561800),
+ new Point3D( -0.26895980939606550, -3.69512371522084140, 14.72272846327652000),
+ new Point3D( -1.53501693431786170, -3.25055166611021900, 15.15509062584274800),
+ new Point3D( -0.71727553535519410, -3.62284279460799100, 13.26256700929380700),
+ new Point3D( -0.30220950676137365, -3.25410412500779070, 13.13682612771606000),
+ new Point3D( -0.04543996608267075, -1.93081853923797750, 14.79497997883171400),
+ new Point3D( -1.53348892951571640, -3.66688919703524900, 14.73095600812074200),
+ new Point3D( -0.98034899533935820, -3.34004481162763960, 13.03245014017556800));
+
+ WelzlEncloser<Point3D> encloser =
new WelzlEncloser<>(1.0e-10, new SphereGenerator());
- EnclosingBall<Euclidean3D, Cartesian3D> ball = encloser.enclose(list);
+ EnclosingBall<Point3D> ball = encloser.enclose(list);
Assert.assertTrue(ball.getRadius() > 0);
}
@@ -112,13 +109,13 @@ public class WelzlEncloser3DTest {
// define the reference sphere we want to compute
double d = 25 * random.nextDouble();
double refRadius = 10 * random.nextDouble();
- Cartesian3D refCenter = new Cartesian3D(d, new Cartesian3D(sr.nextVector()));
+ Point3D refCenter = Point3D.vectorCombination(d, Point3D.of(sr.nextVector()));
// set up a large sample inside the reference sphere
int nbPoints = random.nextInt(1000);
- List<Cartesian3D> points = new ArrayList<>();
+ List<Point3D> points = new ArrayList<>();
for (int i = 0; i < nbPoints; ++i) {
double r = refRadius * random.nextDouble();
- points.add(new Cartesian3D(1.0, refCenter, r, new Cartesian3D(sr.nextVector())));
+ points.add(Point3D.vectorCombination(1.0, refCenter, r, Point3D.of(sr.nextVector())));
}
// test we find a sphere at most as large as the one used for random drawings
@@ -127,23 +124,23 @@ public class WelzlEncloser3DTest {
}
}
- private void checkSphere(List<Cartesian3D> points, double refRadius) {
+ private void checkSphere(List<Point3D> points, double refRadius) {
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = checkSphere(points);
+ EnclosingBall<Point3D> sphere = checkSphere(points);
// compare computed sphere with bounding sphere
Assert.assertTrue(sphere.getRadius() <= refRadius);
// check removing any point of the support Sphere fails to enclose the point
for (int i = 0; i < sphere.getSupportSize(); ++i) {
- List<Cartesian3D> reducedSupport = new ArrayList<>();
+ List<Point3D> reducedSupport = new ArrayList<>();
int count = 0;
- for (Cartesian3D s : sphere.getSupport()) {
+ for (Point3D s : sphere.getSupport()) {
if (count++ != i) {
reducedSupport.add(s);
}
}
- EnclosingBall<Euclidean3D, Cartesian3D> reducedSphere =
+ EnclosingBall<Point3D> reducedSphere =
new SphereGenerator().ballOnSupport(reducedSupport);
boolean foundOutside = false;
for (int j = 0; j < points.size() && !foundOutside; ++j) {
@@ -156,20 +153,20 @@ public class WelzlEncloser3DTest {
}
- private EnclosingBall<Euclidean3D, Cartesian3D> checkSphere(List<Cartesian3D> points) {
+ private EnclosingBall<Point3D> checkSphere(List<Point3D> points) {
- WelzlEncloser<Euclidean3D, Cartesian3D> encloser =
+ WelzlEncloser<Point3D> encloser =
new WelzlEncloser<>(1.0e-10, new SphereGenerator());
- EnclosingBall<Euclidean3D, Cartesian3D> Sphere = encloser.enclose(points);
+ EnclosingBall<Point3D> Sphere = encloser.enclose(points);
// all points are enclosed
- for (Cartesian3D v : points) {
+ for (Point3D v : points) {
Assert.assertTrue(Sphere.contains(v, 1.0e-10));
}
- for (Cartesian3D v : points) {
+ for (Point3D v : points) {
boolean inSupport = false;
- for (Cartesian3D s : Sphere.getSupport()) {
+ for (Point3D s : Sphere.getSupport()) {
if (v == s) {
inSupport = true;
}
diff --git a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGeneratorTest.java b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGeneratorTest.java
index 1adbaa5..a1bf60b 100644
--- a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGeneratorTest.java
+++ b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/threed/enclosing/SphereGeneratorTest.java
@@ -21,8 +21,7 @@ import java.util.Arrays;
import java.util.List;
import org.apache.commons.geometry.enclosing.EnclosingBall;
-import org.apache.commons.geometry.euclidean.threed.Cartesian3D;
-import org.apache.commons.geometry.euclidean.threed.Euclidean3D;
+import org.apache.commons.geometry.euclidean.threed.Point3D;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.UnitSphereSampler;
import org.apache.commons.rng.simple.RandomSource;
@@ -33,8 +32,8 @@ public class SphereGeneratorTest {
@Test
public void testSupport0Point() {
- List<Cartesian3D> support = Arrays.asList(new Cartesian3D[0]);
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ List<Point3D> support = Arrays.asList(new Point3D[0]);
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
Assert.assertTrue(sphere.getRadius() < 0);
Assert.assertEquals(0, sphere.getSupportSize());
Assert.assertEquals(0, sphere.getSupport().length);
@@ -42,16 +41,16 @@ public class SphereGeneratorTest {
@Test
public void testSupport1Point() {
- List<Cartesian3D> support = Arrays.asList(new Cartesian3D(1, 2, 3));
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ List<Point3D> support = Arrays.asList(new Point3D(1, 2, 3));
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
Assert.assertEquals(0.0, sphere.getRadius(), 1.0e-10);
Assert.assertTrue(sphere.contains(support.get(0)));
Assert.assertTrue(sphere.contains(support.get(0), 0.5));
- Assert.assertFalse(sphere.contains(new Cartesian3D(support.get(0).getX() + 0.1,
+ Assert.assertFalse(sphere.contains(new Point3D(support.get(0).getX() + 0.1,
support.get(0).getY() + 0.1,
support.get(0).getZ() + 0.1),
0.001));
- Assert.assertTrue(sphere.contains(new Cartesian3D(support.get(0).getX() + 0.1,
+ Assert.assertTrue(sphere.contains(new Point3D(support.get(0).getX() + 0.1,
support.get(0).getY() + 0.1,
support.get(0).getZ() + 0.1),
0.5));
@@ -62,73 +61,73 @@ public class SphereGeneratorTest {
@Test
public void testSupport2Points() {
- List<Cartesian3D> support = Arrays.asList(new Cartesian3D(1, 0, 0),
- new Cartesian3D(3, 0, 0));
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ List<Point3D> support = Arrays.asList(new Point3D(1, 0, 0),
+ new Point3D(3, 0, 0));
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
Assert.assertEquals(1.0, sphere.getRadius(), 1.0e-10);
int i = 0;
- for (Cartesian3D v : support) {
+ for (Point3D v : support) {
Assert.assertTrue(sphere.contains(v));
Assert.assertEquals(1.0, v.distance(sphere.getCenter()), 1.0e-10);
Assert.assertTrue(v == sphere.getSupport()[i++]);
}
- Assert.assertTrue(sphere.contains(new Cartesian3D(2, 0.9, 0)));
- Assert.assertFalse(sphere.contains(Cartesian3D.ZERO));
- Assert.assertEquals(0.0, new Cartesian3D(2, 0, 0).distance(sphere.getCenter()), 1.0e-10);
+ Assert.assertTrue(sphere.contains(new Point3D(2, 0.9, 0)));
+ Assert.assertFalse(sphere.contains(Point3D.ZERO));
+ Assert.assertEquals(0.0, new Point3D(2, 0, 0).distance(sphere.getCenter()), 1.0e-10);
Assert.assertEquals(2, sphere.getSupportSize());
}
@Test
public void testSupport3Points() {
- List<Cartesian3D> support = Arrays.asList(new Cartesian3D(1, 0, 0),
- new Cartesian3D(3, 0, 0),
- new Cartesian3D(2, 2, 0));
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ List<Point3D> support = Arrays.asList(new Point3D(1, 0, 0),
+ new Point3D(3, 0, 0),
+ new Point3D(2, 2, 0));
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
Assert.assertEquals(5.0 / 4.0, sphere.getRadius(), 1.0e-10);
int i = 0;
- for (Cartesian3D v : support) {
+ for (Point3D v : support) {
Assert.assertTrue(sphere.contains(v));
Assert.assertEquals(5.0 / 4.0, v.distance(sphere.getCenter()), 1.0e-10);
Assert.assertTrue(v == sphere.getSupport()[i++]);
}
- Assert.assertTrue(sphere.contains(new Cartesian3D(2, 0.9, 0)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(0.9, 0, 0)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(3.1, 0, 0)));
- Assert.assertTrue(sphere.contains(new Cartesian3D(2.0, -0.499, 0)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(2.0, -0.501, 0)));
- Assert.assertTrue(sphere.contains(new Cartesian3D(2.0, 3.0 / 4.0, -1.249)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(2.0, 3.0 / 4.0, -1.251)));
- Assert.assertEquals(0.0, new Cartesian3D(2.0, 3.0 / 4.0, 0).distance(sphere.getCenter()), 1.0e-10);
+ Assert.assertTrue(sphere.contains(new Point3D(2, 0.9, 0)));
+ Assert.assertFalse(sphere.contains(new Point3D(0.9, 0, 0)));
+ Assert.assertFalse(sphere.contains(new Point3D(3.1, 0, 0)));
+ Assert.assertTrue(sphere.contains(new Point3D(2.0, -0.499, 0)));
+ Assert.assertFalse(sphere.contains(new Point3D(2.0, -0.501, 0)));
+ Assert.assertTrue(sphere.contains(new Point3D(2.0, 3.0 / 4.0, -1.249)));
+ Assert.assertFalse(sphere.contains(new Point3D(2.0, 3.0 / 4.0, -1.251)));
+ Assert.assertEquals(0.0, new Point3D(2.0, 3.0 / 4.0, 0).distance(sphere.getCenter()), 1.0e-10);
Assert.assertEquals(3, sphere.getSupportSize());
}
@Test
public void testSupport4Points() {
- List<Cartesian3D> support = Arrays.asList(new Cartesian3D(17, 14, 18),
- new Cartesian3D(11, 14, 22),
- new Cartesian3D( 2, 22, 17),
- new Cartesian3D(22, 11, -10));
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ List<Point3D> support = Arrays.asList(new Point3D(17, 14, 18),
+ new Point3D(11, 14, 22),
+ new Point3D( 2, 22, 17),
+ new Point3D(22, 11, -10));
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
Assert.assertEquals(25.0, sphere.getRadius(), 1.0e-10);
int i = 0;
- for (Cartesian3D v : support) {
+ for (Point3D v : support) {
Assert.assertTrue(sphere.contains(v));
Assert.assertEquals(25.0, v.distance(sphere.getCenter()), 1.0e-10);
Assert.assertTrue(v == sphere.getSupport()[i++]);
}
- Assert.assertTrue(sphere.contains (new Cartesian3D(-22.999, 2, 2)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(-23.001, 2, 2)));
- Assert.assertTrue(sphere.contains (new Cartesian3D( 26.999, 2, 2)));
- Assert.assertFalse(sphere.contains(new Cartesian3D( 27.001, 2, 2)));
- Assert.assertTrue(sphere.contains (new Cartesian3D(2, -22.999, 2)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(2, -23.001, 2)));
- Assert.assertTrue(sphere.contains (new Cartesian3D(2, 26.999, 2)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(2, 27.001, 2)));
- Assert.assertTrue(sphere.contains (new Cartesian3D(2, 2, -22.999)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(2, 2, -23.001)));
- Assert.assertTrue(sphere.contains (new Cartesian3D(2, 2, 26.999)));
- Assert.assertFalse(sphere.contains(new Cartesian3D(2, 2, 27.001)));
- Assert.assertEquals(0.0, new Cartesian3D(2.0, 2.0, 2.0).distance(sphere.getCenter()), 1.0e-10);
+ Assert.assertTrue(sphere.contains (new Point3D(-22.999, 2, 2)));
+ Assert.assertFalse(sphere.contains(new Point3D(-23.001, 2, 2)));
+ Assert.assertTrue(sphere.contains (new Point3D( 26.999, 2, 2)));
+ Assert.assertFalse(sphere.contains(new Point3D( 27.001, 2, 2)));
+ Assert.assertTrue(sphere.contains (new Point3D(2, -22.999, 2)));
+ Assert.assertFalse(sphere.contains(new Point3D(2, -23.001, 2)));
+ Assert.assertTrue(sphere.contains (new Point3D(2, 26.999, 2)));
+ Assert.assertFalse(sphere.contains(new Point3D(2, 27.001, 2)));
+ Assert.assertTrue(sphere.contains (new Point3D(2, 2, -22.999)));
+ Assert.assertFalse(sphere.contains(new Point3D(2, 2, -23.001)));
+ Assert.assertTrue(sphere.contains (new Point3D(2, 2, 26.999)));
+ Assert.assertFalse(sphere.contains(new Point3D(2, 2, 27.001)));
+ Assert.assertEquals(0.0, new Point3D(2.0, 2.0, 2.0).distance(sphere.getCenter()), 1.0e-10);
Assert.assertEquals(4, sphere.getSupportSize());
}
@@ -140,12 +139,12 @@ public class SphereGeneratorTest {
for (int i = 0; i < 100; ++i) {
double d = 25 * random.nextDouble();
double refRadius = 10 * random.nextDouble();
- Cartesian3D refCenter = new Cartesian3D(d, new Cartesian3D(sr.nextVector()));
- List<Cartesian3D> support = new ArrayList<>();
+ Point3D refCenter = Point3D.vectorCombination(d, Point3D.of(sr.nextVector()));
+ List<Point3D> support = new ArrayList<>();
for (int j = 0; j < 5; ++j) {
- support.add(new Cartesian3D(1.0, refCenter, refRadius, new Cartesian3D(sr.nextVector())));
+ support.add(Point3D.vectorCombination(1.0, refCenter, refRadius, Point3D.of(sr.nextVector())));
}
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
Assert.assertEquals(0.0, refCenter.distance(sphere.getCenter()), 4e-7 * refRadius);
Assert.assertEquals(refRadius, sphere.getRadius(), 1e-7 * refRadius);
}
@@ -153,20 +152,20 @@ public class SphereGeneratorTest {
@Test
public void testDegeneratedCase() {
- final List<Cartesian3D> support =
- Arrays.asList(new Cartesian3D(Math.scalb(-8039905610797991.0, -50), // -7.140870659936730
+ final List<Point3D> support =
+ Arrays.asList(new Point3D(Math.scalb(-8039905610797991.0, -50), // -7.140870659936730
Math.scalb(-4663475464714142.0, -48), // -16.567993074240455
Math.scalb( 6592658872616184.0, -49)), // 11.710914678204503
- new Cartesian3D(Math.scalb(-8036658568968473.0, -50), // -7.137986707455888
+ new Point3D(Math.scalb(-8036658568968473.0, -50), // -7.137986707455888
Math.scalb(-4664256346424880.0, -48), // -16.570767323375720
Math.scalb( 6591357011730307.0, -49)), // 11.708602108715928)
- new Cartesian3D(Math.scalb(-8037820142977230.0, -50), // -7.139018392423351
+ new Point3D(Math.scalb(-8037820142977230.0, -50), // -7.139018392423351
Math.scalb(-4665280434237813.0, -48), // -16.574405614157020
Math.scalb( 6592435966112099.0, -49)), // 11.710518716711425
- new Cartesian3D(Math.scalb(-8038007803611611.0, -50), // -7.139185068549035
+ new Point3D(Math.scalb(-8038007803611611.0, -50), // -7.139185068549035
Math.scalb(-4664291215918380.0, -48), // -16.570891204702250
Math.scalb( 6595270610894208.0, -49))); // 11.715554057357394
- EnclosingBall<Euclidean3D, Cartesian3D> sphere = new SphereGenerator().ballOnSupport(support);
+ EnclosingBall<Point3D> sphere = new SphereGenerator().ballOnSupport(support);
// the following values have been computed using Emacs calc with exact arithmetic from the
// rational representation corresponding to the scalb calls (i.e. -8039905610797991/2^50, ...)
@@ -177,7 +176,7 @@ public class SphereGeneratorTest {
Assert.assertEquals(-16.571096474251747245361467833760, sphere.getCenter().getY(), 1.0e-20);
Assert.assertEquals( 11.711945804096960876521111630800, sphere.getCenter().getZ(), 1.0e-20);
- for (Cartesian3D v : support) {
+ for (Point3D v : support) {
Assert.assertTrue(sphere.contains(v, 1.0e-14));
}
diff --git a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGeneratorTest.java b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGeneratorTest.java
index 4fbe657..fcafaa4 100644
--- a/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGeneratorTest.java
+++ b/commons-geometry-enclosing/src/test/java/org/apache/commons/geometry/euclidean/twod/enclosing/DiskGeneratorTest.java
@@ -19,23 +19,22 @@ package org.apache.commons.geometry.euclidean.twod.enclosing;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
+
+import org.apache.commons.geometry.enclosing.EnclosingBall;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
import org.apache.commons.rng.UniformRandomProvider;
-import org.apache.commons.rng.simple.RandomSource;
import org.apache.commons.rng.sampling.UnitSphereSampler;
-import org.apache.commons.geometry.enclosing.EnclosingBall;
-import org.apache.commons.geometry.euclidean.twod.enclosing.DiskGenerator;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
+import org.apache.commons.rng.simple.RandomSource;
+import org.junit.Assert;
+import org.junit.Test;
public class DiskGeneratorTest {
@Test
public void testSupport0Point() {
- List<Cartesian2D> support = Arrays.asList(new Cartesian2D[0]);
- EnclosingBall<Euclidean2D, Cartesian2D> disk = new DiskGenerator().ballOnSupport(support);
+ List<Point2D> support = Arrays.asList(new Point2D[0]);
+ EnclosingBall<Point2D> disk = new DiskGenerator().ballOnSupport(support);
Assert.assertTrue(disk.getRadius() < 0);
Assert.assertEquals(0, disk.getSupportSize());
Assert.assertEquals(0, disk.getSupport().length);
@@ -43,15 +42,15 @@ public class DiskGeneratorTest {
@Test
public void testSupport1Point() {
- List<Cartesian2D> support = Arrays.asList(new Cartesian2D(1, 2));
- EnclosingBall<Euclidean2D, Cartesian2D> disk = new DiskGenerator().ballOnSupport(support);
+ List<Point2D> support = Arrays.asList(new Point2D(1, 2));
+ EnclosingBall<Point2D> disk = new DiskGenerator().ballOnSupport(support);
Assert.assertEquals(0.0, disk.getRadius(), 1.0e-10);
Assert.assertTrue(disk.contains(support.get(0)));
Assert.assertTrue(disk.contains(support.get(0), 0.5));
- Assert.assertFalse(disk.contains(new Cartesian2D(support.get(0).getX() + 0.1,
+ Assert.assertFalse(disk.contains(new Point2D(support.get(0).getX() + 0.1,
support.get(0).getY() - 0.1),
0.001));
- Assert.assertTrue(disk.contains(new Cartesian2D(support.get(0).getX() + 0.1,
+ Assert.assertTrue(disk.contains(new Point2D(support.get(0).getX() + 0.1,
support.get(0).getY() - 0.1),
0.5));
Assert.assertEquals(0, support.get(0).distance(disk.getCenter()), 1.0e-10);
@@ -61,41 +60,41 @@ public class DiskGeneratorTest {
@Test
public void testSupport2Points() {
- List<Cartesian2D> support = Arrays.asList(new Cartesian2D(1, 0),
- new Cartesian2D(3, 0));
- EnclosingBall<Euclidean2D, Cartesian2D> disk = new DiskGenerator().ballOnSupport(support);
+ List<Point2D> support = Arrays.asList(new Point2D(1, 0),
+ new Point2D(3, 0));
+ EnclosingBall<Point2D> disk = new DiskGenerator().ballOnSupport(support);
Assert.assertEquals(1.0, disk.getRadius(), 1.0e-10);
int i = 0;
- for (Cartesian2D v : support) {
+ for (Point2D v : support) {
Assert.assertTrue(disk.contains(v));
Assert.assertEquals(1.0, v.distance(disk.getCenter()), 1.0e-10);
Assert.assertTrue(v == disk.getSupport()[i++]);
}
- Assert.assertTrue(disk.contains(new Cartesian2D(2, 0.9)));
- Assert.assertFalse(disk.contains(Cartesian2D.ZERO));
- Assert.assertEquals(0.0, new Cartesian2D(2, 0).distance(disk.getCenter()), 1.0e-10);
+ Assert.assertTrue(disk.contains(new Point2D(2, 0.9)));
+ Assert.assertFalse(disk.contains(Point2D.ZERO));
+ Assert.assertEquals(0.0, new Point2D(2, 0).distance(disk.getCenter()), 1.0e-10);
Assert.assertEquals(2, disk.getSupportSize());
}
@Test
public void testSupport3Points() {
- List<Cartesian2D> support = Arrays.asList(new Cartesian2D(1, 0),
- new Cartesian2D(3, 0),
- new Cartesian2D(2, 2));
- EnclosingBall<Euclidean2D, Cartesian2D> disk = new DiskGenerator().ballOnSupport(support);
+ List<Point2D> support = Arrays.asList(new Point2D(1, 0),
+ new Point2D(3, 0),
+ new Point2D(2, 2));
+ EnclosingBall<Point2D> disk = new DiskGenerator().ballOnSupport(support);
Assert.assertEquals(5.0 / 4.0, disk.getRadius(), 1.0e-10);
int i = 0;
- for (Cartesian2D v : support) {
+ for (Point2D v : support) {
Assert.assertTrue(disk.contains(v));
Assert.assertEquals(5.0 / 4.0, v.distance(disk.getCenter()), 1.0e-10);
Assert.assertTrue(v == disk.getSupport()[i++]);
}
- Assert.assertTrue(disk.contains(new Cartesian2D(2, 0.9)));
- Assert.assertFalse(disk.contains(new Cartesian2D(0.9, 0)));
- Assert.assertFalse(disk.contains(new Cartesian2D(3.1, 0)));
- Assert.assertTrue(disk.contains(new Cartesian2D(2.0, -0.499)));
- Assert.assertFalse(disk.contains(new Cartesian2D(2.0, -0.501)));
- Assert.assertEquals(0.0, new Cartesian2D(2.0, 3.0 / 4.0).distance(disk.getCenter()), 1.0e-10);
+ Assert.assertTrue(disk.contains(new Point2D(2, 0.9)));
+ Assert.assertFalse(disk.contains(new Point2D(0.9, 0)));
+ Assert.assertFalse(disk.contains(new Point2D(3.1, 0)));
+ Assert.assertTrue(disk.contains(new Point2D(2.0, -0.499)));
+ Assert.assertFalse(disk.contains(new Point2D(2.0, -0.501)));
+ Assert.assertEquals(0.0, new Point2D(2.0, 3.0 / 4.0).distance(disk.getCenter()), 1.0e-10);
Assert.assertEquals(3, disk.getSupportSize());
}
@@ -107,12 +106,12 @@ public class DiskGeneratorTest {
for (int i = 0; i < 500; ++i) {
double d = 25 * random.nextDouble();
double refRadius = 10 * random.nextDouble();
- Cartesian2D refCenter = new Cartesian2D(d, new Cartesian2D(sr.nextVector()));
- List<Cartesian2D> support = new ArrayList<>();
+ Point2D refCenter = Point2D.vectorCombination(d, Point2D.of(sr.nextVector()));
+ List<Point2D> support = new ArrayList<>();
for (int j = 0; j < 3; ++j) {
- support.add(new Cartesian2D(1.0, refCenter, refRadius, new Cartesian2D(sr.nextVector())));
+ support.add(Point2D.vectorCombination(1.0, refCenter, refRadius, Point2D.of(sr.nextVector())));
}
- EnclosingBall<Euclidean2D, Cartesian2D> disk = new DiskGenerator().ballOnSupport(support);
+ EnclosingBall<Point2D> disk = new DiskGenerator().ballOnSupport(support);
Assert.assertEquals(0.0, refCenter.distance(disk.getCenter()), 3e-9 * refRadius);
Assert.assertEquals(refRadius, disk.getRadius(), 7e-10 * refRadius);
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanPoint.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanPoint.java
new file mode 100644
index 0000000..033b6bd
--- /dev/null
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanPoint.java
@@ -0,0 +1,43 @@
+/*
+ * 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.geometry.euclidean;
+
+import org.apache.commons.geometry.core.AffinePoint;
+
+/** Represents a point in a Euclidean space of any dimension.
+ *
+ * @param <P> Point implementation type
+ * @param <V> Vector implementation type
+ */
+public interface EuclideanPoint<P extends EuclideanPoint<P, V>, V extends EuclideanVector<P, V>> extends AffinePoint<P, V> {
+
+ /** Returns a vector with the same coordinates as this point.
+ * This is equivalent to the expression {@code v = P - Z} where
+ * {@code P} is this point, {@code Z} is the zero point. and
+ * {@code v} is the returned vector.
+ * @return vector with same coordinate values as this point
+ */
+ V asVector();
+
+ /** Returns the vector representing the displacement from this point
+ * to the given point. This is exactly equivalent to {@code p.subtract(thisPoint)}
+ * but with a method name that is much easier to visualize.
+ * @param p the point the returned vector will be directed toward
+ * @return vector representing the displacement <em>from</em> this point <em>to</em> the given point
+ */
+ V vectorTo(P p);
+}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
similarity index 57%
copy from commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
copy to commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
index 42fd4b7..0622c89 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/EuclideanVector.java
@@ -14,24 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.geometry.euclidean.twod;
+package org.apache.commons.geometry.euclidean;
import org.apache.commons.geometry.core.Vector;
-/** This class represents a 2D vector.
+/** Represents a vector in a Euclidean space of any dimension.
+ *
+ * @param <P> Point implementation type
+ * @param <V> Vector implementation type
*/
-public abstract class Vector2D implements Vector<Euclidean2D> {
-
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see Cartesian2D#Cartesian2D(double, double)
- */
- public abstract double getX();
+public interface EuclideanVector<P extends EuclideanPoint<P, V>, V extends EuclideanVector<P, V>> extends Vector<V> {
- /** Get the ordinate of the vector.
- * @return ordinate of the vector
- * @see Cartesian2D#Cartesian2D(double, double)
+ /** Returns a point with the same coordinates as this vector.
+ * This is equivalent to the expression {@code P = Z + v}, where
+ * {@code v} is this vector, {@code Z} is the zero point, and
+ * {@code P} is the returned point.
+ * @return point with the same coordinates as this vector
*/
- public abstract double getY();
-
+ P asPoint();
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java
index 4517616..7cfbf9d 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java
@@ -16,201 +16,39 @@
*/
package org.apache.commons.geometry.euclidean.oned;
-import java.text.NumberFormat;
+import org.apache.commons.geometry.core.Spatial;
-import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.Vector;
-
-/** This class represents a 1D point or a 1D vector.
- * <p>An instance of Cartesian1D represents the point with the corresponding
- * Cartesian coordinates.</p>
- * <p>An instance of Cartesian1D also represents the vector which begins at
- * the origin and ends at the point corresponding to the coordinates.</p>
- * <p>Instances of this class are guaranteed to be immutable.</p>
+/** This class represents a Cartesian coordinate value in
+ * one-dimensional Euclidean space.
*/
-public class Cartesian1D extends Vector1D implements Point<Euclidean1D> {
-
- /** Origin (coordinates: 0). */
- public static final Cartesian1D ZERO = new Cartesian1D(0.0);
-
- /** Unit (coordinates: 1). */
- public static final Cartesian1D ONE = new Cartesian1D(1.0);
-
- // CHECKSTYLE: stop ConstantName
- /** A vector with all coordinates set to NaN. */
- public static final Cartesian1D NaN = new Cartesian1D(Double.NaN);
- // CHECKSTYLE: resume ConstantName
-
- /** A vector with all coordinates set to positive infinity. */
- public static final Cartesian1D POSITIVE_INFINITY =
- new Cartesian1D(Double.POSITIVE_INFINITY);
-
- /** A vector with all coordinates set to negative infinity. */
- public static final Cartesian1D NEGATIVE_INFINITY =
- new Cartesian1D(Double.NEGATIVE_INFINITY);
+public abstract class Cartesian1D implements Spatial {
/** Serializable UID. */
- private static final long serialVersionUID = 7556674948671647925L;
+ private static final long serialVersionUID = -1178039568877797126L;
- /** Abscissa. */
- private final double x;
+ /** Abscissa (coordinate value). */
+ protected final double x;
- /** Simple constructor.
- * Build a vector from its coordinates
- * @param x abscissa
- * @see #getX()
+ /**
+ * Simple constructor.
+ * @param x abscissa (coordinate value)
*/
- public Cartesian1D(double x) {
+ protected Cartesian1D(double x) {
this.x = x;
}
- /** Multiplicative constructor
- * Build a vector from another one and a scale factor.
- * The vector built will be a * u
- * @param a scale factor
- * @param u base (unscaled) vector
- */
- public Cartesian1D(double a, Cartesian1D u) {
- this.x = a * u.x;
- }
-
- /** Linear constructor
- * Build a vector from two other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- */
- public Cartesian1D(double a1, Cartesian1D u1, double a2, Cartesian1D u2) {
- this.x = a1 * u1.x + a2 * u2.x;
- }
-
- /** Linear constructor
- * Build a vector from three other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- * @param a3 third scale factor
- * @param u3 third base (unscaled) vector
- */
- public Cartesian1D(double a1, Cartesian1D u1, double a2, Cartesian1D u2,
- double a3, Cartesian1D u3) {
- this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x;
- }
-
- /** Linear constructor
- * Build a vector from four other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- * @param a3 third scale factor
- * @param u3 third base (unscaled) vector
- * @param a4 fourth scale factor
- * @param u4 fourth base (unscaled) vector
- */
- public Cartesian1D(double a1, Cartesian1D u1, double a2, Cartesian1D u2,
- double a3, Cartesian1D u3, double a4, Cartesian1D u4) {
- this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x;
- }
-
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see #Cartesian1D(double)
+ /**
+ * Returns the abscissa (coordinate value) of the instance.
+ * @return the abscissa value
*/
- @Override
public double getX() {
return x;
}
/** {@inheritDoc} */
@Override
- public Space getSpace() {
- return Euclidean1D.getInstance();
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D getZero() {
- return ZERO;
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNorm1() {
- return Math.abs(x);
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNorm() {
- return Math.abs(x);
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNormSq() {
- return x * x;
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNormInf() {
- return Math.abs(x);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D add(Vector<Euclidean1D> v) {
- Cartesian1D v1 = (Cartesian1D) v;
- return new Cartesian1D(x + v1.getX());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D add(double factor, Vector<Euclidean1D> v) {
- Cartesian1D v1 = (Cartesian1D) v;
- return new Cartesian1D(x + factor * v1.getX());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D subtract(Vector<Euclidean1D> p) {
- Cartesian1D p3 = (Cartesian1D) p;
- return new Cartesian1D(x - p3.x);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D subtract(double factor, Vector<Euclidean1D> v) {
- Cartesian1D v1 = (Cartesian1D) v;
- return new Cartesian1D(x - factor * v1.getX());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D normalize() throws IllegalStateException {
- double s = getNorm();
- if (s == 0) {
- throw new IllegalStateException("Norm is zero");
- }
- return scalarMultiply(1 / s);
- }
- /** {@inheritDoc} */
- @Override
- public Cartesian1D negate() {
- return new Cartesian1D(-x);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian1D scalarMultiply(double a) {
- return new Cartesian1D(a * x);
+ public int getDimension() {
+ return 1;
}
/** {@inheritDoc} */
@@ -224,159 +62,4 @@ public class Cartesian1D extends Vector1D implements Point<Euclidean1D> {
public boolean isInfinite() {
return !isNaN() && Double.isInfinite(x);
}
-
- /** {@inheritDoc} */
- @Override
- public double distance1(Vector<Euclidean1D> p) {
- Cartesian1D p1 = (Cartesian1D) p;
- final double dx = Math.abs(p1.x - x);
- return dx;
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance(Point<Euclidean1D> p) {
- return distance((Cartesian1D) p);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance(Vector<Euclidean1D> v) {
- return distance((Cartesian1D) v);
- }
-
- /** Compute the distance between the instance and other coordinates.
- * @param c other coordinates
- * @return the distance between the instance and c
- */
- public double distance(Cartesian1D c) {
- final double dx = c.x - x;
- return Math.abs(dx);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distanceInf(Vector<Euclidean1D> p) {
- Cartesian1D p1 = (Cartesian1D) p;
- final double dx = Math.abs(p1.x - x);
- return dx;
- }
-
- /** {@inheritDoc} */
- @Override
- public double distanceSq(Vector<Euclidean1D> p) {
- Cartesian1D p1 = (Cartesian1D) p;
- final double dx = p1.x - x;
- return dx * dx;
- }
-
- /** {@inheritDoc} */
- @Override
- public double dotProduct(final Vector<Euclidean1D> v) {
- final Cartesian1D v1 = (Cartesian1D) v;
- return x * v1.x;
- }
-
- /** Compute the distance between two points according to the L<sub>2</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>p1.subtract(p2).getNorm()</code> except that no intermediate
- * vector is built</p>
- * @param p1 first vector
- * @param p2 second vector
- * @return the distance between p1 and p2 according to the L<sub>2</sub> norm
- */
- public static double distance(Cartesian1D p1, Cartesian1D p2) {
- return p1.distance(p2);
- }
-
- /** Compute the distance between two points according to the L<sub>∞</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>p1.subtract(p2).getNormInf()</code> except that no intermediate
- * vector is built</p>
- * @param p1 first vector
- * @param p2 second vector
- * @return the distance between p1 and p2 according to the L<sub>∞</sub> norm
- */
- public static double distanceInf(Cartesian1D p1, Cartesian1D p2) {
- return p1.distanceInf(p2);
- }
-
- /** Compute the square of the distance between two points.
- * <p>Calling this method is equivalent to calling:
- * <code>p1.subtract(p2).getNormSq()</code> except that no intermediate
- * vector is built</p>
- * @param p1 first vector
- * @param p2 second vector
- * @return the square of the distance between p1 and p2
- */
- public static double distanceSq(Cartesian1D p1, Cartesian1D p2) {
- return p1.distanceSq(p2);
- }
-
- /**
- * Test for the equality of two 1D vectors.
- * <p>
- * If all coordinates of two 1D vectors are exactly the same, and none are
- * <code>Double.NaN</code>, the two 1D vectors are considered to be equal.
- * </p>
- * <p>
- * <code>NaN</code> coordinates are considered to affect globally the vector
- * and be equals to each other - i.e, if either (or all) coordinates of the
- * 1D vector are equal to <code>Double.NaN</code>, the 1D vector is equal to
- * {@link #NaN}.
- * </p>
- *
- * @param other Object to test for equality to this
- * @return true if two 1D vector objects are equal, false if
- * object is null, not an instance of Cartesian1D, or
- * not equal to this Cartesian1D instance
- *
- */
- @Override
- public boolean equals(Object other) {
-
- if (this == other) {
- return true;
- }
-
- if (other instanceof Cartesian1D) {
- final Cartesian1D rhs = (Cartesian1D)other;
- if (rhs.isNaN()) {
- return this.isNaN();
- }
-
- return x == rhs.x;
- }
- return false;
- }
-
- /**
- * Get a hashCode for the 1D vector.
- * <p>
- * All NaN values have the same hash code.</p>
- *
- * @return a hash code value for this object
- */
- @Override
- public int hashCode() {
- if (isNaN()) {
- return 7785;
- }
- return 997 * Double.hashCode(x);
- }
-
- /** Get a string representation of this vector.
- * @return a string representation of this vector
- */
- @Override
- public String toString() {
- return toString(NumberFormat.getInstance());
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString(final NumberFormat format) {
- return "{" + format.format(x) + "}";
- }
-
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Euclidean1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Euclidean1D.java
deleted file mode 100644
index 394e317..0000000
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Euclidean1D.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.geometry.euclidean.oned;
-
-import java.io.Serializable;
-
-import org.apache.commons.geometry.core.Space;
-
-/**
- * This class implements a one-dimensional space.
- */
-public class Euclidean1D implements Serializable, Space {
-
- /** Serializable version identifier. */
- private static final long serialVersionUID = -1178039568877797126L;
-
- /** Private constructor for the singleton.
- */
- private Euclidean1D() {
- }
-
- /** Get the unique instance.
- * @return the unique instance
- */
- public static Euclidean1D getInstance() {
- return LazyHolder.INSTANCE;
- }
-
- /** {@inheritDoc} */
- @Override
- public int getDimension() {
- return 1;
- }
-
- /** {@inheritDoc}
- * <p>
- * As the 1-dimension Euclidean space does not have proper sub-spaces,
- * this method always throws a {@link UnsupportedOperationException}
- * </p>
- * @return nothing
- * @throws UnsupportedOperationException in all cases
- */
- @Override
- public Space getSubSpace() throws UnsupportedOperationException {
- throw new UnsupportedOperationException("One-dimensional space does not have a subspace");
- }
-
- // CHECKSTYLE: stop HideUtilityClassConstructor
- /** Holder for the instance.
- * <p>We use here the Initialization On Demand Holder Idiom.</p>
- */
- private static class LazyHolder {
- /** Cached field instance. */
- private static final Euclidean1D INSTANCE = new Euclidean1D();
- }
- // CHECKSTYLE: resume HideUtilityClassConstructor
-
- /** Handle deserialization of the singleton.
- * @return the singleton instance
- */
- private Object readResolve() {
- // return the singleton instance
- return LazyHolder.INSTANCE;
- }
-}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/IntervalsSet.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/IntervalsSet.java
index 3bdcd17..05e7798 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/IntervalsSet.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/IntervalsSet.java
@@ -22,7 +22,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
-import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.partitioning.AbstractRegion;
import org.apache.commons.geometry.core.partitioning.BSPTree;
import org.apache.commons.geometry.core.partitioning.BoundaryProjection;
@@ -30,7 +29,7 @@ import org.apache.commons.geometry.core.partitioning.SubHyperplane;
/** This class represents a 1D region: a set of intervals.
*/
-public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> implements Iterable<double[]> {
+public class IntervalsSet extends AbstractRegion<Point1D, Point1D> implements Iterable<double[]> {
/** Build an intervals set representing the whole real line.
* @param tolerance tolerance below which points are considered identical.
@@ -60,7 +59,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param tree inside/outside BSP tree representing the intervals set
* @param tolerance tolerance below which points are considered identical.
*/
- public IntervalsSet(final BSPTree<Euclidean1D> tree, final double tolerance) {
+ public IntervalsSet(final BSPTree<Point1D> tree, final double tolerance) {
super(tree, tolerance);
}
@@ -84,7 +83,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param boundary collection of boundary elements
* @param tolerance tolerance below which points are considered identical.
*/
- public IntervalsSet(final Collection<SubHyperplane<Euclidean1D>> boundary,
+ public IntervalsSet(final Collection<SubHyperplane<Point1D>> boundary,
final double tolerance) {
super(boundary, tolerance);
}
@@ -97,7 +96,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param tolerance tolerance below which points are considered identical.
* @return the built tree
*/
- private static BSPTree<Euclidean1D> buildTree(final double lower, final double upper,
+ private static BSPTree<Point1D> buildTree(final double lower, final double upper,
final double tolerance) {
if (Double.isInfinite(lower) && (lower < 0)) {
if (Double.isInfinite(upper) && (upper > 0)) {
@@ -105,31 +104,31 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
return new BSPTree<>(Boolean.TRUE);
}
// the tree must be open on the negative infinity side
- final SubHyperplane<Euclidean1D> upperCut =
- new OrientedPoint(new Cartesian1D(upper), true, tolerance).wholeHyperplane();
+ final SubHyperplane<Point1D> upperCut =
+ new OrientedPoint(new Point1D(upper), true, tolerance).wholeHyperplane();
return new BSPTree<>(upperCut,
- new BSPTree<Euclidean1D>(Boolean.FALSE),
- new BSPTree<Euclidean1D>(Boolean.TRUE),
+ new BSPTree<Point1D>(Boolean.FALSE),
+ new BSPTree<Point1D>(Boolean.TRUE),
null);
}
- final SubHyperplane<Euclidean1D> lowerCut =
- new OrientedPoint(new Cartesian1D(lower), false, tolerance).wholeHyperplane();
+ final SubHyperplane<Point1D> lowerCut =
+ new OrientedPoint(new Point1D(lower), false, tolerance).wholeHyperplane();
if (Double.isInfinite(upper) && (upper > 0)) {
// the tree must be open on the positive infinity side
return new BSPTree<>(lowerCut,
- new BSPTree<Euclidean1D>(Boolean.FALSE),
- new BSPTree<Euclidean1D>(Boolean.TRUE),
+ new BSPTree<Point1D>(Boolean.FALSE),
+ new BSPTree<Point1D>(Boolean.TRUE),
null);
}
// the tree must be bounded on the two sides
- final SubHyperplane<Euclidean1D> upperCut =
- new OrientedPoint(new Cartesian1D(upper), true, tolerance).wholeHyperplane();
+ final SubHyperplane<Point1D> upperCut =
+ new OrientedPoint(new Point1D(upper), true, tolerance).wholeHyperplane();
return new BSPTree<>(lowerCut,
- new BSPTree<Euclidean1D>(Boolean.FALSE),
+ new BSPTree<Point1D>(Boolean.FALSE),
new BSPTree<>(upperCut,
- new BSPTree<Euclidean1D>(Boolean.FALSE),
- new BSPTree<Euclidean1D>(Boolean.TRUE),
+ new BSPTree<Point1D>(Boolean.FALSE),
+ new BSPTree<Point1D>(Boolean.TRUE),
null),
null);
@@ -137,7 +136,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
/** {@inheritDoc} */
@Override
- public IntervalsSet buildNew(final BSPTree<Euclidean1D> tree) {
+ public IntervalsSet buildNew(final BSPTree<Point1D> tree) {
return new IntervalsSet(tree, getTolerance());
}
@@ -145,7 +144,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
@Override
protected void computeGeometricalProperties() {
if (getTree(false).getCut() == null) {
- setBarycenter((Point<Euclidean1D>) Cartesian1D.NaN);
+ setBarycenter(Point1D.NaN);
setSize(((Boolean) getTree(false).getAttribute()) ? Double.POSITIVE_INFINITY : 0);
} else {
double size = 0.0;
@@ -156,11 +155,11 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
}
setSize(size);
if (Double.isInfinite(size)) {
- setBarycenter((Point<Euclidean1D>) Cartesian1D.NaN);
+ setBarycenter(Point1D.NaN);
} else if (size > 0) {
- setBarycenter((Point<Euclidean1D>) new Cartesian1D(sum / size));
+ setBarycenter(new Point1D(sum / size));
} else {
- setBarycenter((Point<Euclidean1D>) ((OrientedPoint) getTree(false).getCut().getHyperplane()).getLocation());
+ setBarycenter(((OrientedPoint) getTree(false).getCut().getHyperplane()).getLocation());
}
}
}
@@ -172,7 +171,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* instance is empty)
*/
public double getInf() {
- BSPTree<Euclidean1D> node = getTree(false);
+ BSPTree<Point1D> node = getTree(false);
double inf = Double.POSITIVE_INFINITY;
while (node.getCut() != null) {
final OrientedPoint op = (OrientedPoint) node.getCut().getHyperplane();
@@ -189,7 +188,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* instance is empty)
*/
public double getSup() {
- BSPTree<Euclidean1D> node = getTree(false);
+ BSPTree<Point1D> node = getTree(false);
double sup = Double.NEGATIVE_INFINITY;
while (node.getCut() != null) {
final OrientedPoint op = (OrientedPoint) node.getCut().getHyperplane();
@@ -202,10 +201,10 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
/** {@inheritDoc}
*/
@Override
- public BoundaryProjection<Euclidean1D> projectToBoundary(final Point<Euclidean1D> point) {
+ public BoundaryProjection<Point1D> projectToBoundary(final Point1D point) {
// get position of test point
- final double x = ((Cartesian1D) point).getX();
+ final double x = point.getX();
double previous = Double.NEGATIVE_INFINITY;
for (final double[] a : this) {
@@ -242,8 +241,8 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param x abscissa of the point
* @return a new point for finite abscissa, null otherwise
*/
- private Cartesian1D finiteOrNullPoint(final double x) {
- return Double.isInfinite(x) ? null : new Cartesian1D(x);
+ private Point1D finiteOrNullPoint(final double x) {
+ return Double.isInfinite(x) ? null : new Point1D(x);
}
/** Build an ordered list of intervals representing the instance.
@@ -271,15 +270,15 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param root tree root
* @return first leaf node
*/
- private BSPTree<Euclidean1D> getFirstLeaf(final BSPTree<Euclidean1D> root) {
+ private BSPTree<Point1D> getFirstLeaf(final BSPTree<Point1D> root) {
if (root.getCut() == null) {
return root;
}
// find the smallest internal node
- BSPTree<Euclidean1D> smallest = null;
- for (BSPTree<Euclidean1D> n = root; n != null; n = previousInternalNode(n)) {
+ BSPTree<Point1D> smallest = null;
+ for (BSPTree<Point1D> n = root; n != null; n = previousInternalNode(n)) {
smallest = n;
}
@@ -291,10 +290,10 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @return smallest internal node,
* or null if there are no internal nodes (i.e. the set is either empty or covers the real line)
*/
- private BSPTree<Euclidean1D> getFirstIntervalBoundary() {
+ private BSPTree<Point1D> getFirstIntervalBoundary() {
// start search at the tree root
- BSPTree<Euclidean1D> node = getTree(false);
+ BSPTree<Point1D> node = getTree(false);
if (node.getCut() == null) {
return null;
}
@@ -315,7 +314,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node to check
* @return true if the node corresponds to the start abscissa of an interval
*/
- private boolean isIntervalStart(final BSPTree<Euclidean1D> node) {
+ private boolean isIntervalStart(final BSPTree<Point1D> node) {
if ((Boolean) leafBefore(node).getAttribute()) {
// it has an inside cell before it, it may end an interval but not start it
@@ -337,7 +336,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node to check
* @return true if the node corresponds to the end abscissa of an interval
*/
- private boolean isIntervalEnd(final BSPTree<Euclidean1D> node) {
+ private boolean isIntervalEnd(final BSPTree<Point1D> node) {
if (!(Boolean) leafBefore(node).getAttribute()) {
// it has an outside cell before it, it may start an interval but not end it
@@ -360,7 +359,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @return next internal node in ascending order, or null
* if this is the last internal node
*/
- private BSPTree<Euclidean1D> nextInternalNode(BSPTree<Euclidean1D> node) {
+ private BSPTree<Point1D> nextInternalNode(BSPTree<Point1D> node) {
if (childAfter(node).getCut() != null) {
// the next node is in the sub-tree
@@ -380,7 +379,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @return previous internal node in ascending order, or null
* if this is the first internal node
*/
- private BSPTree<Euclidean1D> previousInternalNode(BSPTree<Euclidean1D> node) {
+ private BSPTree<Point1D> previousInternalNode(BSPTree<Point1D> node) {
if (childBefore(node).getCut() != null) {
// the next node is in the sub-tree
@@ -399,7 +398,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node at which the sub-tree starts
* @return leaf node just before the internal node
*/
- private BSPTree<Euclidean1D> leafBefore(BSPTree<Euclidean1D> node) {
+ private BSPTree<Point1D> leafBefore(BSPTree<Point1D> node) {
node = childBefore(node);
while (node.getCut() != null) {
@@ -414,7 +413,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node at which the sub-tree starts
* @return leaf node just after the internal node
*/
- private BSPTree<Euclidean1D> leafAfter(BSPTree<Euclidean1D> node) {
+ private BSPTree<Point1D> leafAfter(BSPTree<Point1D> node) {
node = childAfter(node);
while (node.getCut() != null) {
@@ -429,8 +428,8 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node child node considered
* @return true is the node has a parent end is before it in ascending order
*/
- private boolean isBeforeParent(final BSPTree<Euclidean1D> node) {
- final BSPTree<Euclidean1D> parent = node.getParent();
+ private boolean isBeforeParent(final BSPTree<Point1D> node) {
+ final BSPTree<Point1D> parent = node.getParent();
if (parent == null) {
return false;
} else {
@@ -442,8 +441,8 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node child node considered
* @return true is the node has a parent end is after it in ascending order
*/
- private boolean isAfterParent(final BSPTree<Euclidean1D> node) {
- final BSPTree<Euclidean1D> parent = node.getParent();
+ private boolean isAfterParent(final BSPTree<Point1D> node) {
+ final BSPTree<Point1D> parent = node.getParent();
if (parent == null) {
return false;
} else {
@@ -455,7 +454,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node at which the sub-tree starts
* @return child node just before the internal node
*/
- private BSPTree<Euclidean1D> childBefore(BSPTree<Euclidean1D> node) {
+ private BSPTree<Point1D> childBefore(BSPTree<Point1D> node) {
if (isDirect(node)) {
// smaller abscissas are on minus side, larger abscissas are on plus side
return node.getMinus();
@@ -469,7 +468,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node at which the sub-tree starts
* @return child node just after the internal node
*/
- private BSPTree<Euclidean1D> childAfter(BSPTree<Euclidean1D> node) {
+ private BSPTree<Point1D> childAfter(BSPTree<Point1D> node) {
if (isDirect(node)) {
// smaller abscissas are on minus side, larger abscissas are on plus side
return node.getPlus();
@@ -483,7 +482,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node to check
* @return true if the oriented point is direct
*/
- private boolean isDirect(final BSPTree<Euclidean1D> node) {
+ private boolean isDirect(final BSPTree<Point1D> node) {
return ((OrientedPoint) node.getCut().getHyperplane()).isDirect();
}
@@ -491,7 +490,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
* @param node internal node to check
* @return abscissa
*/
- private double getAngle(final BSPTree<Euclidean1D> node) {
+ private double getAngle(final BSPTree<Point1D> node) {
return ((OrientedPoint) node.getCut().getHyperplane()).getLocation().getX();
}
@@ -512,7 +511,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
private class SubIntervalsIterator implements Iterator<double[]> {
/** Current node. */
- private BSPTree<Euclidean1D> current;
+ private BSPTree<Point1D> current;
/** Sub-interval no yet returned. */
private double[] pending;
@@ -549,7 +548,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
private void selectPending() {
// look for the start of the interval
- BSPTree<Euclidean1D> start = current;
+ BSPTree<Point1D> start = current;
while (start != null && !isIntervalStart(start)) {
start = nextInternalNode(start);
}
@@ -562,7 +561,7 @@ public class IntervalsSet extends AbstractRegion<Euclidean1D, Euclidean1D> imple
}
// look for the end of the interval
- BSPTree<Euclidean1D> end = start;
+ BSPTree<Point1D> end = start;
while (end != null && !isIntervalEnd(end)) {
end = nextInternalNode(end);
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/OrientedPoint.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/OrientedPoint.java
index b1d0d89..e03edbb 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/OrientedPoint.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/OrientedPoint.java
@@ -16,8 +16,6 @@
*/
package org.apache.commons.geometry.euclidean.oned;
-import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Vector;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
/** This class represents a 1D oriented hyperplane.
@@ -25,10 +23,10 @@ import org.apache.commons.geometry.core.partitioning.Hyperplane;
* boolean.</p>
* <p>Instances of this class are guaranteed to be immutable.</p>
*/
-public class OrientedPoint implements Hyperplane<Euclidean1D> {
+public class OrientedPoint implements Hyperplane<Point1D> {
- /** Vector location. */
- private final Cartesian1D location;
+ /** Point location. */
+ private final Point1D location;
/** Orientation. */
private boolean direct;
@@ -42,7 +40,7 @@ public class OrientedPoint implements Hyperplane<Euclidean1D> {
* abscissas greater than {@code location}
* @param tolerance tolerance below which points are considered to belong to the hyperplane
*/
- public OrientedPoint(final Cartesian1D location, final boolean direct, final double tolerance) {
+ public OrientedPoint(final Point1D location, final boolean direct, final double tolerance) {
this.location = location;
this.direct = direct;
this.tolerance = tolerance;
@@ -58,18 +56,10 @@ public class OrientedPoint implements Hyperplane<Euclidean1D> {
return this;
}
- /** Get the offset (oriented distance) of a vector.
- * @param vector vector to check
- * @return offset of the vector
- */
- public double getOffset(Vector<Euclidean1D> vector) {
- return getOffset((Point<Euclidean1D>) vector);
- }
-
/** {@inheritDoc} */
@Override
- public double getOffset(final Point<Euclidean1D> point) {
- final double delta = ((Cartesian1D) point).getX() - location.getX();
+ public double getOffset(final Point1D point) {
+ final double delta = point.getX() - location.getX();
return direct ? delta : -delta;
}
@@ -100,13 +90,13 @@ public class OrientedPoint implements Hyperplane<Euclidean1D> {
/** {@inheritDoc} */
@Override
- public boolean sameOrientationAs(final Hyperplane<Euclidean1D> other) {
+ public boolean sameOrientationAs(final Hyperplane<Point1D> other) {
return !(direct ^ ((OrientedPoint) other).direct);
}
/** {@inheritDoc} */
@Override
- public Point<Euclidean1D> project(Point<Euclidean1D> point) {
+ public Point1D project(Point1D point) {
return location;
}
@@ -119,7 +109,7 @@ public class OrientedPoint implements Hyperplane<Euclidean1D> {
/** Get the hyperplane location on the real line.
* @return the hyperplane location
*/
- public Cartesian1D getLocation() {
+ public Point1D getLocation() {
return location;
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java
new file mode 100644
index 0000000..8983598
--- /dev/null
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java
@@ -0,0 +1,267 @@
+/*
+ * 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.geometry.euclidean.oned;
+
+import org.apache.commons.geometry.euclidean.EuclideanPoint;
+import org.apache.commons.numbers.arrays.LinearCombination;
+
+/** This class representing a point in one-dimensional Euclidean space.
+ * Instances of this class are guaranteed to be immutable.
+ */
+public final class Point1D extends Cartesian1D implements EuclideanPoint<Point1D, Vector1D> {
+
+ /** Origin (coordinates: 0). */
+ public static final Point1D ZERO = new Point1D(0.0);
+
+ /** Unit (coordinates: 1). */
+ public static final Point1D ONE = new Point1D(1.0);
+
+ // CHECKSTYLE: stop ConstantName
+ /** A vector with all coordinates set to NaN. */
+ public static final Point1D NaN = new Point1D(Double.NaN);
+ // CHECKSTYLE: resume ConstantName
+
+ /** A point with all coordinates set to positive infinity. */
+ public static final Point1D POSITIVE_INFINITY =
+ new Point1D(Double.POSITIVE_INFINITY);
+
+ /** A point with all coordinates set to negative infinity. */
+ public static final Point1D NEGATIVE_INFINITY =
+ new Point1D(Double.NEGATIVE_INFINITY);
+
+ /** Serializable UID. */
+ private static final long serialVersionUID = 7556674948671647925L;
+
+ /** Simple constructor.
+ * @param x abscissa (coordinate value)
+ * @see #getX()
+ */
+ public Point1D(double x) {
+ super(x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D asVector() {
+ return Vector1D.of(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distance(Point1D p) {
+ return Math.abs(p.x - x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D subtract(Point1D p) {
+ return Vector1D.of(x - p.x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D vectorTo(Point1D p) {
+ return p.subtract(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Point1D add(Vector1D v) {
+ return new Point1D(x + v.x);
+ }
+
+ /**
+ * Get a hashCode for this point.
+ * <p>All NaN values have the same hash code.</p>
+ *
+ * @return a hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ if (isNaN()) {
+ return 7785;
+ }
+ return 997 * Double.hashCode(x);
+ }
+
+ /**
+ * Test for the equality of two points.
+ * <p>
+ * If all coordinates of two points are exactly the same, and none are
+ * <code>Double.NaN</code>, the two points are considered to be equal.
+ * </p>
+ * <p>
+ * <code>NaN</code> coordinates are considered to globally affect the point
+ * and be equal to each other - i.e, if either (or all) coordinates of the
+ * point are equal to <code>Double.NaN</code>, the point is equal to
+ * {@link #NaN}.
+ * </p>
+ *
+ * @param other Object to test for equality to this
+ * @return true if the two point objects are equal, false if
+ * object is null, not an instance of Point1D, or
+ * not equal to this Point1D instance
+ *
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other instanceof Point1D) {
+ final Point1D rhs = (Point1D) other;
+ if (rhs.isNaN()) {
+ return this.isNaN();
+ }
+
+ return x == rhs.x;
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "(" + x + ")";
+ }
+
+ /** Returns a point with the given coordinate value.
+ * @param x point coordinate
+ * @return point instance
+ */
+ public static Point1D of(double x) {
+ return new Point1D(x);
+ }
+
+ /** Returns a point instance with the given coordinate value.
+ * @param value point coordinate
+ * @return point instance
+ */
+ public static Point1D of(Cartesian1D value) {
+ return new Point1D(value.x);
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a scale factor for first coordinate
+ * @param c first coordinate
+ * @return point with coordinates calculated by {@code a * c}
+ * @see {@link Vector1D#linearCombination(double, Vector1D)}
+ */
+ public static Point1D vectorCombination(double a, Cartesian1D c) {
+ return new Point1D(a * c.x);
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2)}
+ * @see {@link Vector1D#linearCombination(double, Cartesian1D, double, Cartesian1D)}
+ */
+ public static Point1D vectorCombination(double a1, Cartesian1D c1, double a2, Cartesian1D c2) {
+ return new Point1D(
+ LinearCombination.value(a1, c1.x, a2, c2.x));
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3)}
+ * @see {@link Vector1D#linearCombination(double, Cartesian1D, double, Cartesian1D, double, Cartesian1D)}
+ */
+ public static Point1D vectorCombination(double a1, Cartesian1D c1, double a2, Cartesian1D c2,
+ double a3, Cartesian1D c3) {
+ return new Point1D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x));
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @param a4 scale factor for fourth coordinate
+ * @param c4 fourth coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3) + (a4 * c4)}
+ * @see {@link Vector1D#linearCombination(double, Cartesian1D, double, Cartesian1D, double, Cartesian1D, double, Cartesian1D)}
+ */
+ public static Point1D vectorCombination(double a1, Cartesian1D c1, double a2, Cartesian1D c2,
+ double a3, Cartesian1D c3, double a4, Cartesian1D c4) {
+ return new Point1D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x, a4, c4.x));
+ }
+}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/SubOrientedPoint.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/SubOrientedPoint.java
index 8e05e5a..de6881b 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/SubOrientedPoint.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/SubOrientedPoint.java
@@ -25,14 +25,14 @@ import org.apache.commons.geometry.core.partitioning.Region;
* boolean.</p>
* <p>Instances of this class are guaranteed to be immutable.</p>
*/
-public class SubOrientedPoint extends AbstractSubHyperplane<Euclidean1D, Euclidean1D> {
+public class SubOrientedPoint extends AbstractSubHyperplane<Point1D, Point1D> {
/** Simple constructor.
* @param hyperplane underlying hyperplane
* @param remainingRegion remaining region of the hyperplane
*/
- public SubOrientedPoint(final Hyperplane<Euclidean1D> hyperplane,
- final Region<Euclidean1D> remainingRegion) {
+ public SubOrientedPoint(final Hyperplane<Point1D> hyperplane,
+ final Region<Point1D> remainingRegion) {
super(hyperplane, remainingRegion);
}
@@ -50,14 +50,14 @@ public class SubOrientedPoint extends AbstractSubHyperplane<Euclidean1D, Euclide
/** {@inheritDoc} */
@Override
- protected AbstractSubHyperplane<Euclidean1D, Euclidean1D> buildNew(final Hyperplane<Euclidean1D> hyperplane,
- final Region<Euclidean1D> remainingRegion) {
+ protected AbstractSubHyperplane<Point1D, Point1D> buildNew(final Hyperplane<Point1D> hyperplane,
+ final Region<Point1D> remainingRegion) {
return new SubOrientedPoint(hyperplane, remainingRegion);
}
/** {@inheritDoc} */
@Override
- public SplitSubHyperplane<Euclidean1D> split(final Hyperplane<Euclidean1D> hyperplane) {
+ public SplitSubHyperplane<Point1D> split(final Hyperplane<Point1D> hyperplane) {
final OrientedPoint thisHyperplane = (OrientedPoint) getHyperplane();
final double global = hyperplane.getOffset(thisHyperplane.getLocation());
@@ -65,11 +65,11 @@ public class SubOrientedPoint extends AbstractSubHyperplane<Euclidean1D, Euclide
final double tolerance = thisHyperplane.getTolerance();
if (global < -tolerance) {
- return new SplitSubHyperplane<Euclidean1D>(null, this);
+ return new SplitSubHyperplane<Point1D>(null, this);
} else if (global > tolerance) {
- return new SplitSubHyperplane<Euclidean1D>(this, null);
+ return new SplitSubHyperplane<Point1D>(this, null);
} else {
- return new SplitSubHyperplane<Euclidean1D>(null, null);
+ return new SplitSubHyperplane<Point1D>(null, null);
}
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
index e9fdaf1..f2adbad 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
@@ -16,16 +16,307 @@
*/
package org.apache.commons.geometry.euclidean.oned;
-import org.apache.commons.geometry.core.Vector;
+import org.apache.commons.geometry.euclidean.EuclideanVector;
+import org.apache.commons.numbers.arrays.LinearCombination;
-/** This class represents a 1D vector.
+/** This class represents a vector in one-dimensional Euclidean space.
+ * Instances of this class are guaranteed to be immutable.
*/
-public abstract class Vector1D implements Vector<Euclidean1D> {
+public final class Vector1D extends Cartesian1D implements EuclideanVector<Point1D, Vector1D> {
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see Cartesian1D#Cartesian1D(double)
+ /** Zero vector (coordinates: 0). */
+ public static final Vector1D ZERO = new Vector1D(0.0);
+
+ /** Unit vector (coordinates: 1). */
+ public static final Vector1D ONE = new Vector1D(1.0);
+
+ // CHECKSTYLE: stop ConstantName
+ /** A vector with all coordinates set to NaN. */
+ public static final Vector1D NaN = new Vector1D(Double.NaN);
+ // CHECKSTYLE: resume ConstantName
+
+ /** A vector with all coordinates set to positive infinity. */
+ public static final Vector1D POSITIVE_INFINITY =
+ new Vector1D(Double.POSITIVE_INFINITY);
+
+ /** A vector with all coordinates set to negative infinity. */
+ public static final Vector1D NEGATIVE_INFINITY =
+ new Vector1D(Double.NEGATIVE_INFINITY);
+
+ /** Serializable UID. */
+ private static final long serialVersionUID = 1582116020164328846L;
+
+ /** Simple constructor.
+ * @param x abscissa (coordinate value)
*/
- public abstract double getX();
+ public Vector1D(double x) {
+ super(x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Point1D asPoint() {
+ return Point1D.of(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D getZero() {
+ return ZERO;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNorm1() {
+ return getNorm();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNorm() {
+ return Math.abs(x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNormSq() {
+ return x * x;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNormInf() {
+ return getNorm();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D add(Vector1D v) {
+ return new Vector1D(x + v.x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D add(double factor, Vector1D v) {
+ return new Vector1D(x + (factor * v.x));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D subtract(Vector1D v) {
+ return new Vector1D(x - v.x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D subtract(double factor, Vector1D v) {
+ return new Vector1D(x - (factor * v.x));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D negate() {
+ return new Vector1D(-x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D normalize() throws IllegalStateException {
+ double s = getNorm();
+ if (s == 0) {
+ throw new IllegalStateException("Norm is zero");
+ }
+ return scalarMultiply(1.0 / s);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector1D scalarMultiply(double a) {
+ return new Vector1D(a * x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distance1(Vector1D v) {
+ return distance(v);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distance(Vector1D v) {
+ return Math.abs(v.x - x);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distanceInf(Vector1D v) {
+ return distance(v);
+ }
+ /** {@inheritDoc} */
+ @Override
+ public double distanceSq(Vector1D v) {
+ final double dx = v.x - x;
+ return dx * dx;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double dotProduct(Vector1D v) {
+ return x * v.x;
+ }
+
+ /**
+ * Get a hashCode for the vector.
+ * <p>All NaN values have the same hash code.</p>
+ *
+ * @return a hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ if (isNaN()) {
+ return 857;
+ }
+ return 403 * Double.hashCode(x);
+ }
+
+ /**
+ * Test for the equality of two vectors.
+ * <p>
+ * If all coordinates of two vectors are exactly the same, and none are
+ * <code>Double.NaN</code>, the two vectors are considered to be equal.
+ * </p>
+ * <p>
+ * <code>NaN</code> coordinates are considered to globally affect the vector
+ * and be equal to each other - i.e, if either (or all) coordinates of the
+ * vector are equal to <code>Double.NaN</code>, the vector is equal to
+ * {@link #NaN}.
+ * </p>
+ *
+ * @param other Object to test for equality to this
+ * @return true if two vector objects are equal, false if
+ * object is null, not an instance of Vector1D, or
+ * not equal to this Vector1D instance
+ *
+ */
+ @Override
+ public boolean equals(Object other) {
+
+ if (this == other) {
+ return true;
+ }
+
+ if (other instanceof Vector1D) {
+ final Vector1D rhs = (Vector1D) other;
+ if (rhs.isNaN()) {
+ return this.isNaN();
+ }
+
+ return x == rhs.x;
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "{" + x + "}";
+ }
+
+ /** Returns a vector with the given coordinate value.
+ * @param x vector coordinate
+ * @return vector instance
+ */
+ public static Vector1D of(double x) {
+ return new Vector1D(x);
+ }
+
+ /** Returns a vector instance with the given coordinate value.
+ * @param value vector coordinate
+ * @return vector instance
+ */
+ public static Vector1D of(Cartesian1D value) {
+ return new Vector1D(value.x);
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a scale factor for first coordinate
+ * @param c first coordinate
+ * @return vector with coordinates calculated by {@code a * c}
+ */
+ public static Vector1D linearCombination(double a, Cartesian1D c) {
+ return new Vector1D(a * c.x);
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @return vector with coordinates calculated by {@code (a1 * c1) + (a2 * c2)}
+ */
+ public static Vector1D linearCombination(double a1, Cartesian1D c1, double a2, Cartesian1D c2) {
+ return new Vector1D(
+ LinearCombination.value(a1, c1.x, a2, c2.x));
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @return vector with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3)}
+ */
+ public static Vector1D linearCombination(double a1, Cartesian1D c1, double a2, Cartesian1D c2,
+ double a3, Cartesian1D c3) {
+ return new Vector1D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x));
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @param a4 scale factor for fourth coordinate
+ * @param c4 fourth coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3) + (a4 * c4)}
+ */
+ public static Vector1D linearCombination(double a1, Cartesian1D c1, double a2, Cartesian1D c2,
+ double a3, Cartesian1D c3, double a4, Cartesian1D c4) {
+ return new Vector1D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x, a4, c4.x));
+ }
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/package-info.java
similarity index 68%
copy from commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
copy to commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/package-info.java
index e9fdaf1..2ed2a4c 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/package-info.java
@@ -14,18 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.geometry.euclidean.oned;
-
-import org.apache.commons.geometry.core.Vector;
-
-/** This class represents a 1D vector.
+/**
+ *
+ * <p>
+ * This package provides basic interfaces for Euclidean components.
+ * </p>
*/
-public abstract class Vector1D implements Vector<Euclidean1D> {
-
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see Cartesian1D#Cartesian1D(double)
- */
- public abstract double getX();
-
-}
+package org.apache.commons.geometry.euclidean;
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java
index 79b975f..b57c108 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java
@@ -17,210 +17,59 @@
package org.apache.commons.geometry.euclidean.threed;
-import java.io.Serializable;
-import java.text.NumberFormat;
+import org.apache.commons.geometry.core.Spatial;
-import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.Vector;
-import org.apache.commons.numbers.arrays.LinearCombination;
-
-/**
- * This class represents points or vectors in a three-dimensional space.
- * <p>An instance of Cartesian3D represents the point with the corresponding
- * coordinates.</p>
- * <p>An instance of Cartesian3D also represents the vector which begins at
- * the origin and ends at the point corresponding to the coordinates.</p>
- * <p>Instance of this class are guaranteed to be immutable.</p>
+/** This class represents a Cartesian coordinate value in
+ * three-dimensional Euclidean space.
*/
-public class Cartesian3D extends Vector3D implements Serializable, Point<Euclidean3D> {
-
- /** Null vector (coordinates: 0, 0, 0). */
- public static final Cartesian3D ZERO = new Cartesian3D(0, 0, 0);
-
- /** First canonical vector (coordinates: 1, 0, 0). */
- public static final Cartesian3D PLUS_I = new Cartesian3D(1, 0, 0);
-
- /** Opposite of the first canonical vector (coordinates: -1, 0, 0). */
- public static final Cartesian3D MINUS_I = new Cartesian3D(-1, 0, 0);
-
- /** Second canonical vector (coordinates: 0, 1, 0). */
- public static final Cartesian3D PLUS_J = new Cartesian3D(0, 1, 0);
-
- /** Opposite of the second canonical vector (coordinates: 0, -1, 0). */
- public static final Cartesian3D MINUS_J = new Cartesian3D(0, -1, 0);
-
- /** Third canonical vector (coordinates: 0, 0, 1). */
- public static final Cartesian3D PLUS_K = new Cartesian3D(0, 0, 1);
-
- /** Opposite of the third canonical vector (coordinates: 0, 0, -1). */
- public static final Cartesian3D MINUS_K = new Cartesian3D(0, 0, -1);
-
- // CHECKSTYLE: stop ConstantName
- /** A vector with all coordinates set to NaN. */
- public static final Cartesian3D NaN = new Cartesian3D(Double.NaN, Double.NaN, Double.NaN);
- // CHECKSTYLE: resume ConstantName
-
- /** A vector with all coordinates set to positive infinity. */
- public static final Cartesian3D POSITIVE_INFINITY =
- new Cartesian3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
-
- /** A vector with all coordinates set to negative infinity. */
- public static final Cartesian3D NEGATIVE_INFINITY =
- new Cartesian3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
+public abstract class Cartesian3D implements Spatial {
- /** Serializable version identifier. */
- private static final long serialVersionUID = 1313493323784566947L;
+ /** Serializable UID. */
+ private static final long serialVersionUID = 6249091865814886817L;
- /** Error message when norms are zero. */
- private static final String ZERO_NORM_MSG = "Norm is zero";
+ /** Abscissa (first coordinate value) */
+ protected final double x;
- /** Abscissa. */
- private final double x;
+ /** Ordinate (second coordinate value) */
+ protected final double y;
- /** Ordinate. */
- private final double y;
-
- /** Height. */
- private final double z;
+ /** Height (third coordinate value)*/
+ protected final double z;
/** Simple constructor.
- * Build a vector from its coordinates
- * @param x abscissa
- * @param y ordinate
- * @param z height
- * @see #getX()
- * @see #getY()
- * @see #getZ()
+ * @param x abscissa (first coordinate value)
+ * @param y ordinate (second coordinate value)
+ * @param z height (third coordinate value)
*/
- public Cartesian3D(double x, double y, double z) {
+ protected Cartesian3D(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
- /** Simple constructor.
- * Build a vector from its coordinates
- * @param v coordinates array
- * @exception DimensionMismatchException if array does not have 3 elements
- * @see #toArray()
- */
- public Cartesian3D(double[] v) throws IllegalArgumentException {
- if (v.length != 3) {
- throw new IllegalArgumentException("Dimension mismatch: " + v.length + " != 3");
- }
- this.x = v[0];
- this.y = v[1];
- this.z = v[2];
- }
-
- /** Simple constructor.
- * Build a vector from its azimuthal coordinates
- * @param alpha azimuth (α) around Z
- * (0 is +X, π/2 is +Y, π is -X and 3π/2 is -Y)
- * @param delta elevation (δ) above (XY) plane, from -π/2 to +π/2
- * @see #getAlpha()
- * @see #getDelta()
+ /** Returns the abscissa (first coordinate) value of the instance.
+ * @return the abscisaa
*/
- public Cartesian3D(double alpha, double delta) {
- double cosDelta = Math.cos(delta);
- this.x = Math.cos(alpha) * cosDelta;
- this.y = Math.sin(alpha) * cosDelta;
- this.z = Math.sin(delta);
- }
-
- /** Multiplicative constructor
- * Build a vector from another one and a scale factor.
- * The vector built will be a * u
- * @param a scale factor
- * @param u base (unscaled) vector
- */
- public Cartesian3D(double a, Cartesian3D u) {
- this.x = a * u.x;
- this.y = a * u.y;
- this.z = a * u.z;
- }
-
- /** Linear constructor
- * Build a vector from two other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- */
- public Cartesian3D(double a1, Cartesian3D u1, double a2, Cartesian3D u2) {
- this.x = LinearCombination.value(a1, u1.x, a2, u2.x);
- this.y = LinearCombination.value(a1, u1.y, a2, u2.y);
- this.z = LinearCombination.value(a1, u1.z, a2, u2.z);
- }
-
- /** Linear constructor
- * Build a vector from three other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- * @param a3 third scale factor
- * @param u3 third base (unscaled) vector
- */
- public Cartesian3D(double a1, Cartesian3D u1, double a2, Cartesian3D u2,
- double a3, Cartesian3D u3) {
- this.x = LinearCombination.value(a1, u1.x, a2, u2.x, a3, u3.x);
- this.y = LinearCombination.value(a1, u1.y, a2, u2.y, a3, u3.y);
- this.z = LinearCombination.value(a1, u1.z, a2, u2.z, a3, u3.z);
- }
-
- /** Linear constructor
- * Build a vector from four other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- * @param a3 third scale factor
- * @param u3 third base (unscaled) vector
- * @param a4 fourth scale factor
- * @param u4 fourth base (unscaled) vector
- */
- public Cartesian3D(double a1, Cartesian3D u1, double a2, Cartesian3D u2,
- double a3, Cartesian3D u3, double a4, Cartesian3D u4) {
- this.x = LinearCombination.value(a1, u1.x, a2, u2.x, a3, u3.x, a4, u4.x);
- this.y = LinearCombination.value(a1, u1.y, a2, u2.y, a3, u3.y, a4, u4.y);
- this.z = LinearCombination.value(a1, u1.z, a2, u2.z, a3, u3.z, a4, u4.z);
- }
-
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see #Cartesian3D(double, double, double)
- */
- @Override
public double getX() {
return x;
}
- /** Get the ordinate of the vector.
- * @return ordinate of the vector
- * @see #Cartesian3D(double, double, double)
+ /** Returns the ordinate (second coordinate) value of the instance.
+ * @return the ordinate
*/
- @Override
public double getY() {
return y;
}
- /** Get the height of the vector.
- * @return height of the vector
- * @see #Cartesian3D(double, double, double)
+ /** Returns the height (third coordinate) value of the instance.
+ * @return the height
*/
- @Override
public double getZ() {
return z;
}
- /** Get the vector coordinates as a dimension 3 array.
- * @return vector coordinates
- * @see #Cartesian3D(double[])
+ /** Get the coordinates for this instance as a dimension 3 array.
+ * @return the coordinates for this instance
*/
public double[] toArray() {
return new double[] { x, y, z };
@@ -228,172 +77,8 @@ public class Cartesian3D extends Vector3D implements Serializable, Point<Euclide
/** {@inheritDoc} */
@Override
- public Space getSpace() {
- return Euclidean3D.getInstance();
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D getZero() {
- return ZERO;
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNorm1() {
- return Math.abs(x) + Math.abs(y) + Math.abs(z);
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNorm() {
- // there are no cancellation problems here, so we use the straightforward formula
- return Math.sqrt (x * x + y * y + z * z);
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNormSq() {
- // there are no cancellation problems here, so we use the straightforward formula
- return x * x + y * y + z * z;
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNormInf() {
- return Math.max(Math.max(Math.abs(x), Math.abs(y)), Math.abs(z));
- }
-
- /** Get the azimuth of the vector.
- * @return azimuth (α) of the vector, between -π and +π
- * @see #Cartesian3D(double, double)
- */
- public double getAlpha() {
- return Math.atan2(y, x);
- }
-
- /** Get the elevation of the vector.
- * @return elevation (δ) of the vector, between -π/2 and +π/2
- * @see #Cartesian3D(double, double)
- */
- public double getDelta() {
- return Math.asin(z / getNorm());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D add(final Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- return new Cartesian3D(x + v3.x, y + v3.y, z + v3.z);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D add(double factor, final Vector<Euclidean3D> v) {
- return new Cartesian3D(1, this, factor, (Cartesian3D) v);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D subtract(final Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- return new Cartesian3D(x - v3.x, y - v3.y, z - v3.z);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D subtract(final double factor, final Vector<Euclidean3D> v) {
- return new Cartesian3D(1, this, -factor, (Cartesian3D) v);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D normalize() throws IllegalStateException {
- double s = getNorm();
- if (s == 0) {
- throw new IllegalStateException(ZERO_NORM_MSG);
- }
- return scalarMultiply(1 / s);
- }
-
- /** Get a vector orthogonal to the instance.
- * <p>There are an infinite number of normalized vectors orthogonal
- * to the instance. This method picks up one of them almost
- * arbitrarily. It is useful when one needs to compute a reference
- * frame with one of the axes in a predefined direction. The
- * following example shows how to build a frame having the k axis
- * aligned with the known vector u :
- * <pre><code>
- * Cartesian3D k = u.normalize();
- * Cartesian3D i = k.orthogonal();
- * Cartesian3D j = Cartesian3D.crossProduct(k, i);
- * </code></pre>
- * @return a new normalized vector orthogonal to the instance
- * @exception IllegalStateException if the norm of the instance is zero
- */
- public Cartesian3D orthogonal() throws IllegalStateException {
-
- double threshold = 0.6 * getNorm();
- if (threshold == 0) {
- throw new IllegalStateException(ZERO_NORM_MSG);
- }
-
- if (Math.abs(x) <= threshold) {
- double inverse = 1 / Math.sqrt(y * y + z * z);
- return new Cartesian3D(0, inverse * z, -inverse * y);
- } else if (Math.abs(y) <= threshold) {
- double inverse = 1 / Math.sqrt(x * x + z * z);
- return new Cartesian3D(-inverse * z, 0, inverse * x);
- }
- double inverse = 1 / Math.sqrt(x * x + y * y);
- return new Cartesian3D(inverse * y, -inverse * x, 0);
-
- }
-
- /** Compute the angular separation between two vectors.
- * <p>This method computes the angular separation between two
- * vectors using the dot product for well separated vectors and the
- * cross product for almost aligned vectors. This allows to have a
- * good accuracy in all cases, even for vectors very close to each
- * other.</p>
- * @param v1 first vector
- * @param v2 second vector
- * @return angular separation between v1 and v2
- * @exception IllegalArgumentException if either vector has a zero norm
- */
- public static double angle(Cartesian3D v1, Cartesian3D v2) throws IllegalArgumentException {
-
- double normProduct = v1.getNorm() * v2.getNorm();
- if (normProduct == 0) {
- throw new IllegalArgumentException(ZERO_NORM_MSG);
- }
-
- double dot = v1.dotProduct(v2);
- double threshold = normProduct * 0.9999;
- if ((dot < -threshold) || (dot > threshold)) {
- // the vectors are almost aligned, compute using the sine
- Cartesian3D v3 = crossProduct(v1, v2);
- if (dot >= 0) {
- return Math.asin(v3.getNorm() / normProduct);
- }
- return Math.PI - Math.asin(v3.getNorm() / normProduct);
- }
-
- // the vectors are sufficiently separated to use the cosine
- return Math.acos(dot / normProduct);
-
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D negate() {
- return new Cartesian3D(-x, -y, -z);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian3D scalarMultiply(double a) {
- return new Cartesian3D(a * x, a * y, a * z);
+ public int getDimension() {
+ return 3;
}
/** {@inheritDoc} */
@@ -408,214 +93,16 @@ public class Cartesian3D extends Vector3D implements Serializable, Point<Euclide
return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y) || Double.isInfinite(z));
}
- /**
- * Test for the equality of two 3D vectors.
- * <p>
- * If all coordinates of two 3D vectors are exactly the same, and none are
- * <code>Double.NaN</code>, the two 3D vectors are considered to be equal.
- * </p>
- * <p>
- * <code>NaN</code> coordinates are considered to affect globally the vector
- * and be equals to each other - i.e, if either (or all) coordinates of the
- * 3D vector are equal to <code>Double.NaN</code>, the 3D vector is equal to
- * {@link #NaN}.
- * </p>
- *
- * @param other Object to test for equality to this
- * @return true if two 3D vector objects are equal, false if
- * object is null, not an instance of Cartesian3D, or
- * not equal to this Cartesian3D instance
- *
- */
- @Override
- public boolean equals(Object other) {
-
- if (this == other) {
- return true;
- }
-
- if (other instanceof Cartesian3D) {
- final Cartesian3D rhs = (Cartesian3D)other;
- if (rhs.isNaN()) {
- return this.isNaN();
- }
-
- return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
- }
- return false;
- }
-
- /**
- * Get a hashCode for the 3D vector.
- * <p>
- * All NaN values have the same hash code.</p>
- *
- * @return a hash code value for this object
- */
- @Override
- public int hashCode() {
- if (isNaN()) {
- return 642;
- }
- return 643 * (164 * Double.hashCode(x) + 3 * Double.hashCode(y) + Double.hashCode(z));
- }
-
- /** {@inheritDoc}
- * <p>
- * The implementation uses specific multiplication and addition
- * algorithms to preserve accuracy and reduce cancellation effects.
- * It should be very accurate even for nearly orthogonal vectors.
- * </p>
- * @see LinearCombination#value(double, double, double, double, double, double)
- */
- @Override
- public double dotProduct(final Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- return LinearCombination.value(x, v3.x, y, v3.y, z, v3.z);
- }
-
- /** Compute the cross-product of the instance with another vector.
- * @param v other vector
- * @return the cross product this ^ v as a new Cartesian3D
- */
- public Cartesian3D crossProduct(final Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- return new Cartesian3D(LinearCombination.value(y, v3.z, -z, v3.y),
- LinearCombination.value(z, v3.x, -x, v3.z),
- LinearCombination.value(x, v3.y, -y, v3.x));
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance1(Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- final double dx = Math.abs(v3.x - x);
- final double dy = Math.abs(v3.y - y);
- final double dz = Math.abs(v3.z - z);
- return dx + dy + dz;
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance(Point<Euclidean3D> p) {
- return distance((Cartesian3D) p);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance(Vector<Euclidean3D> v) {
- return distance((Cartesian3D) v);
- }
-
- /** Compute the distance between the instance and other coordinates.
- * @param c other coordinates
- * @return the distance between the instance and c
- */
- public double distance(Cartesian3D c) {
- final double dx = c.x - x;
- final double dy = c.y - y;
- final double dz = c.z - z;
- return Math.sqrt(dx * dx + dy * dy + dz * dz);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distanceInf(Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- final double dx = Math.abs(v3.x - x);
- final double dy = Math.abs(v3.y - y);
- final double dz = Math.abs(v3.z - z);
- return Math.max(Math.max(dx, dy), dz);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distanceSq(Vector<Euclidean3D> v) {
- final Cartesian3D v3 = (Cartesian3D) v;
- final double dx = v3.x - x;
- final double dy = v3.y - y;
- final double dz = v3.z - z;
- return dx * dx + dy * dy + dz * dz;
- }
-
- /** Compute the dot-product of two vectors.
- * @param v1 first vector
- * @param v2 second vector
- * @return the dot product v1.v2
- */
- public static double dotProduct(Cartesian3D v1, Cartesian3D v2) {
- return v1.dotProduct(v2);
- }
-
- /** Compute the cross-product of two vectors.
- * @param v1 first vector
- * @param v2 second vector
- * @return the cross product v1 ^ v2 as a new Vector
+ /** Returns the Euclidean distance from this set of coordinates to the given coordinates.
+ * @param other coordinates to compute the distance to.
+ * @return Euclidean distance value
*/
- public static Cartesian3D crossProduct(final Cartesian3D v1, final Cartesian3D v2) {
- return v1.crossProduct(v2);
- }
-
- /** Compute the distance between two vectors according to the L<sub>1</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>v1.subtract(v2).getNorm1()</code> except that no intermediate
- * vector is built</p>
- * @param v1 first vector
- * @param v2 second vector
- * @return the distance between v1 and v2 according to the L<sub>1</sub> norm
- */
- public static double distance1(Cartesian3D v1, Cartesian3D v2) {
- return v1.distance1(v2);
- }
-
- /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>v1.subtract(v2).getNorm()</code> except that no intermediate
- * vector is built</p>
- * @param v1 first vector
- * @param v2 second vector
- * @return the distance between v1 and v2 according to the L<sub>2</sub> norm
- */
- public static double distance(Cartesian3D v1, Cartesian3D v2) {
- return v1.distance(v2);
- }
-
- /** Compute the distance between two vectors according to the L<sub>∞</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>v1.subtract(v2).getNormInf()</code> except that no intermediate
- * vector is built</p>
- * @param v1 first vector
- * @param v2 second vector
- * @return the distance between v1 and v2 according to the L<sub>∞</sub> norm
- */
- public static double distanceInf(Cartesian3D v1, Cartesian3D v2) {
- return v1.distanceInf(v2);
- }
-
- /** Compute the square of the distance between two vectors.
- * <p>Calling this method is equivalent to calling:
- * <code>v1.subtract(v2).getNormSq()</code> except that no intermediate
- * vector is built</p>
- * @param v1 first vector
- * @param v2 second vector
- * @return the square of the distance between v1 and v2
- */
- public static double distanceSq(Cartesian3D v1, Cartesian3D v2) {
- return v1.distanceSq(v2);
- }
-
- /** Get a string representation of this vector.
- * @return a string representation of this vector
- */
- @Override
- public String toString() {
- return toString(NumberFormat.getInstance());
- }
+ protected double euclideanDistance(Cartesian3D other) {
+ // there are no cancellation problems here, so we use the straightforward formula
+ final double dx = x - other.x;
+ final double dy = y - other.y;
+ final double dz = z - other.z;
- /** {@inheritDoc} */
- @Override
- public String toString(final NumberFormat format) {
- return "{" + format.format(x) + "; " + format.format(y) + "; " + format.format(z) + "}";
+ return Math.sqrt((dx * dx) + (dy * dy) + (dz * dz));
}
-
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Euclidean3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Euclidean3D.java
deleted file mode 100644
index 4988476..0000000
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Euclidean3D.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.geometry.euclidean.threed;
-
-import java.io.Serializable;
-
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
-
-/**
- * This class implements a three-dimensional space.
- */
-public class Euclidean3D implements Serializable, Space {
-
- /** Serializable version identifier. */
- private static final long serialVersionUID = 6249091865814886817L;
-
- /** Private constructor for the singleton.
- */
- private Euclidean3D() {
- }
-
- /** Get the unique instance.
- * @return the unique instance
- */
- public static Euclidean3D getInstance() {
- return LazyHolder.INSTANCE;
- }
-
- /** {@inheritDoc} */
- @Override
- public int getDimension() {
- return 3;
- }
-
- /** {@inheritDoc} */
- @Override
- public Euclidean2D getSubSpace() {
- return Euclidean2D.getInstance();
- }
-
- // CHECKSTYLE: stop HideUtilityClassConstructor
- /** Holder for the instance.
- * <p>We use here the Initialization On Demand Holder Idiom.</p>
- */
- private static class LazyHolder {
- /** Cached field instance. */
- private static final Euclidean3D INSTANCE = new Euclidean3D();
- }
- // CHECKSTYLE: resume HideUtilityClassConstructor
-
- /** Handle deserialization of the singleton.
- * @return the singleton instance
- */
- private Object readResolve() {
- // return the singleton instance
- return LazyHolder.INSTANCE;
- }
-
-}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Line.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Line.java
index 2024032..68512a8 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Line.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Line.java
@@ -16,12 +16,9 @@
*/
package org.apache.commons.geometry.euclidean.threed;
-import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Vector;
import org.apache.commons.geometry.core.partitioning.Embedding;
-import org.apache.commons.geometry.euclidean.oned.Cartesian1D;
-import org.apache.commons.geometry.euclidean.oned.Euclidean1D;
import org.apache.commons.geometry.euclidean.oned.IntervalsSet;
+import org.apache.commons.geometry.euclidean.oned.Point1D;
import org.apache.commons.numbers.core.Precision;
/** The class represent lines in a three dimensional space.
@@ -33,13 +30,13 @@ import org.apache.commons.numbers.core.Precision;
* which is closest to the origin. Abscissa increases in the line
* direction.</p>0
*/
-public class Line implements Embedding<Euclidean3D, Euclidean1D> {
+public class Line implements Embedding<Point3D, Point1D> {
/** Line direction. */
- private Cartesian3D direction;
+ private Vector3D direction;
/** Line point closest to the origin. */
- private Cartesian3D zero;
+ private Point3D zero;
/** Tolerance below which points are considered identical. */
private final double tolerance;
@@ -50,7 +47,7 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if the points are equal
*/
- public Line(final Cartesian3D p1, final Cartesian3D p2, final double tolerance)
+ public Line(final Point3D p1, final Point3D p2, final double tolerance)
throws IllegalArgumentException {
reset(p1, p2);
this.tolerance = tolerance;
@@ -72,14 +69,14 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param p2 second point belonging to the line (this can be any point, different from p1)
* @exception IllegalArgumentException if the points are equal
*/
- public void reset(final Cartesian3D p1, final Cartesian3D p2) throws IllegalStateException {
- final Cartesian3D delta = p2.subtract(p1);
+ public void reset(final Point3D p1, final Point3D p2) throws IllegalArgumentException {
+ final Vector3D delta = p2.subtract(p1);
final double norm2 = delta.getNormSq();
if (norm2 == 0.0) {
throw new IllegalArgumentException("Points are equal");
}
- this.direction = new Cartesian3D(1.0 / Math.sqrt(norm2), delta);
- zero = new Cartesian3D(1.0, p1, -p1.dotProduct(delta) / norm2, delta);
+ this.direction = Vector3D.linearCombination(1.0 / Math.sqrt(norm2), delta);
+ this.zero = Point3D.vectorCombination(1.0, p1, -p1.asVector().dotProduct(delta) / norm2, delta);
}
/** Get the tolerance below which points are considered identical.
@@ -101,14 +98,14 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
/** Get the normalized direction vector.
* @return normalized direction vector
*/
- public Cartesian3D getDirection() {
+ public Vector3D getDirection() {
return direction;
}
/** Get the line point closest to the origin.
* @return line point closest to the origin
*/
- public Cartesian3D getOrigin() {
+ public Point3D getOrigin() {
return zero;
}
@@ -119,7 +116,7 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param point point to check
* @return abscissa of the point
*/
- public double getAbscissa(final Cartesian3D point) {
+ public double getAbscissa(final Point3D point) {
return point.subtract(zero).dotProduct(direction);
}
@@ -127,42 +124,8 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param abscissa desired abscissa for the point
* @return one point belonging to the line, at specified abscissa
*/
- public Cartesian3D pointAt(final double abscissa) {
- return new Cartesian3D(1.0, zero, abscissa, direction);
- }
-
- /** Transform a space point into a sub-space point.
- * @param vector n-dimension point of the space
- * @return (n-1)-dimension point of the sub-space corresponding to
- * the specified space point
- */
- public Cartesian1D toSubSpace(Vector<Euclidean3D> vector) {
- return toSubSpace((Point<Euclidean3D>) vector);
- }
-
- /** Transform a sub-space point into a space point.
- * @param vector (n-1)-dimension point of the sub-space
- * @return n-dimension point of the space corresponding to the
- * specified sub-space point
- */
- public Cartesian3D toSpace(Vector<Euclidean1D> vector) {
- return toSpace((Point<Euclidean1D>) vector);
- }
-
- /** {@inheritDoc}
- * @see #getAbscissa(Cartesian3D)
- */
- @Override
- public Cartesian1D toSubSpace(final Point<Euclidean3D> point) {
- return toSubSpace((Cartesian3D) point);
- }
-
- /** {@inheritDoc}
- * @see #pointAt(double)
- */
- @Override
- public Cartesian3D toSpace(final Point<Euclidean1D> point) {
- return toSpace((Cartesian1D) point);
+ public Point3D pointAt(final double abscissa) {
+ return Point3D.vectorCombination(1.0, zero, abscissa, direction);
}
/** Transform a space point into a sub-space point.
@@ -170,8 +133,9 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @return (n-1)-dimension point of the sub-space corresponding to
* the specified space point
*/
- public Cartesian1D toSubSpace(final Cartesian3D point) {
- return new Cartesian1D(getAbscissa(point));
+ @Override
+ public Point1D toSubSpace(final Point3D point) {
+ return new Point1D(getAbscissa(point));
}
/** Transform a sub-space point into a space point.
@@ -179,7 +143,8 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @return n-dimension point of the space corresponding to the
* specified sub-space point
*/
- public Cartesian3D toSpace(final Cartesian1D point) {
+ @Override
+ public Point3D toSpace(final Point1D point) {
return pointAt(point.getX());
}
@@ -191,7 +156,7 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @return true if the lines are similar
*/
public boolean isSimilarTo(final Line line) {
- final double angle = Cartesian3D.angle(direction, line.direction);
+ final double angle = direction.angle(line.direction);
return ((angle < tolerance) || (angle > (Math.PI - tolerance))) && contains(line.zero);
}
@@ -199,7 +164,7 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param p point to check
* @return true if p belongs to the line
*/
- public boolean contains(final Cartesian3D p) {
+ public boolean contains(final Point3D p) {
return distance(p) < tolerance;
}
@@ -207,9 +172,9 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param p to check
* @return distance between the instance and the point
*/
- public double distance(final Cartesian3D p) {
- final Cartesian3D d = p.subtract(zero);
- final Cartesian3D n = new Cartesian3D(1.0, d, -d.dotProduct(direction), direction);
+ public double distance(final Point3D p) {
+ final Vector3D d = p.subtract(zero);
+ final Vector3D n = Vector3D.linearCombination(1.0, d, -d.dotProduct(direction), direction);
return n.getNorm();
}
@@ -219,7 +184,7 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
*/
public double distance(final Line line) {
- final Cartesian3D normal = Cartesian3D.crossProduct(direction, line.direction);
+ final Vector3D normal = direction.crossProduct(line.direction);
final double n = normal.getNorm();
if (n < Precision.SAFE_MIN) {
// lines are parallel
@@ -237,7 +202,7 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @param line line to check against the instance
* @return point of the instance closest to another line
*/
- public Cartesian3D closestPoint(final Line line) {
+ public Point3D closestPoint(final Line line) {
final double cos = direction.dotProduct(line.direction);
final double n = 1 - cos * cos;
@@ -246,11 +211,11 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
return zero;
}
- final Cartesian3D delta0 = line.zero.subtract(zero);
+ final Vector3D delta0 = line.zero.subtract(zero);
final double a = delta0.dotProduct(direction);
final double b = delta0.dotProduct(line.direction);
- return new Cartesian3D(1, zero, (a - b * cos) / n, direction);
+ return Point3D.vectorCombination(1, zero, (a - b * cos) / n, direction);
}
@@ -259,8 +224,8 @@ public class Line implements Embedding<Euclidean3D, Euclidean1D> {
* @return intersection point of the instance and the other line
* or null if there are no intersection points
*/
- public Cartesian3D intersection(final Line line) {
- final Cartesian3D closest = closestPoint(line);
+ public Point3D intersection(final Line line) {
+ final Point3D closest = closestPoint(line);
return line.contains(closest) ? closest : null;
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/OutlineExtractor.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/OutlineExtractor.java
index 3f25191..830d8bf 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/OutlineExtractor.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/OutlineExtractor.java
@@ -18,16 +18,14 @@ package org.apache.commons.geometry.euclidean.threed;
import java.util.ArrayList;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
-import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
-import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.partitioning.AbstractSubHyperplane;
import org.apache.commons.geometry.core.partitioning.BSPTree;
import org.apache.commons.geometry.core.partitioning.BSPTreeVisitor;
import org.apache.commons.geometry.core.partitioning.BoundaryAttribute;
import org.apache.commons.geometry.core.partitioning.RegionFactory;
import org.apache.commons.geometry.core.partitioning.SubHyperplane;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
+import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
/** Extractor for {@link PolygonsSet polyhedrons sets} outlines.
* <p>This class extracts the 2D outlines from {{@link PolygonsSet
@@ -36,29 +34,29 @@ import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
public class OutlineExtractor {
/** Abscissa axis of the projection plane. */
- private final Cartesian3D u;
+ private final Vector3D u;
/** Ordinate axis of the projection plane. */
- private final Cartesian3D v;
+ private final Vector3D v;
/** Normal of the projection plane (viewing direction). */
- private final Cartesian3D w;
+ private final Vector3D w;
/** Build an extractor for a specific projection plane.
* @param u abscissa axis of the projection point
* @param v ordinate axis of the projection point
*/
- public OutlineExtractor(final Cartesian3D u, final Cartesian3D v) {
+ public OutlineExtractor(final Vector3D u, final Vector3D v) {
this.u = u;
this.v = v;
- w = Cartesian3D.crossProduct(u, v);
+ this.w = u.crossProduct(v);
}
/** Extract the outline of a polyhedrons set.
* @param polyhedronsSet polyhedrons set whose outline must be extracted
* @return an outline, as an array of loops.
*/
- public Cartesian2D[][] getOutline(final PolyhedronsSet polyhedronsSet) {
+ public Point2D[][] getOutline(final PolyhedronsSet polyhedronsSet) {
// project all boundary facets into one polygons set
final BoundaryProjector projector = new BoundaryProjector(polyhedronsSet.getTolerance());
@@ -66,9 +64,9 @@ public class OutlineExtractor {
final PolygonsSet projected = projector.getProjected();
// Remove the spurious intermediate vertices from the outline
- final Cartesian2D[][] outline = projected.getVertices();
+ final Point2D[][] outline = projected.getVertices();
for (int i = 0; i < outline.length; ++i) {
- final Cartesian2D[] rawLoop = outline[i];
+ final Point2D[] rawLoop = outline[i];
int end = rawLoop.length;
int j = 0;
while (j < end) {
@@ -85,7 +83,7 @@ public class OutlineExtractor {
}
if (end != rawLoop.length) {
// resize the array
- outline[i] = new Cartesian2D[end];
+ outline[i] = new Point2D[end];
System.arraycopy(rawLoop, 0, outline[i], 0, end);
}
}
@@ -102,10 +100,10 @@ public class OutlineExtractor {
* @param i index of the point to check (must be between 0 and n-1)
* @return true if the point is exactly between its neighbors
*/
- private boolean pointIsBetween(final Cartesian2D[] loop, final int n, final int i) {
- final Cartesian2D previous = loop[(i + n - 1) % n];
- final Cartesian2D current = loop[i];
- final Cartesian2D next = loop[(i + 1) % n];
+ private boolean pointIsBetween(final Point2D[] loop, final int n, final int i) {
+ final Point2D previous = loop[(i + n - 1) % n];
+ final Point2D current = loop[i];
+ final Point2D next = loop[(i + 1) % n];
final double dx1 = current.getX() - previous.getX();
final double dy1 = current.getY() - previous.getY();
final double dx2 = next.getX() - current.getX();
@@ -117,7 +115,7 @@ public class OutlineExtractor {
}
/** Visitor projecting the boundary facets on a plane. */
- private class BoundaryProjector implements BSPTreeVisitor<Euclidean3D> {
+ private class BoundaryProjector implements BSPTreeVisitor<Point3D> {
/** Projection of the polyhedrons set on the plane. */
private PolygonsSet projected;
@@ -129,22 +127,22 @@ public class OutlineExtractor {
* @param tolerance tolerance below which points are considered identical
*/
BoundaryProjector(final double tolerance) {
- this.projected = new PolygonsSet(new BSPTree<Euclidean2D>(Boolean.FALSE), tolerance);
+ this.projected = new PolygonsSet(new BSPTree<Point2D>(Boolean.FALSE), tolerance);
this.tolerance = tolerance;
}
/** {@inheritDoc} */
@Override
- public Order visitOrder(final BSPTree<Euclidean3D> node) {
+ public Order visitOrder(final BSPTree<Point3D> node) {
return Order.MINUS_SUB_PLUS;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(final BSPTree<Euclidean3D> node) {
+ public void visitInternalNode(final BSPTree<Point3D> node) {
@SuppressWarnings("unchecked")
- final BoundaryAttribute<Euclidean3D> attribute =
- (BoundaryAttribute<Euclidean3D>) node.getAttribute();
+ final BoundaryAttribute<Point3D> attribute =
+ (BoundaryAttribute<Point3D>) node.getAttribute();
if (attribute.getPlusOutside() != null) {
addContribution(attribute.getPlusOutside(), false);
}
@@ -155,33 +153,33 @@ public class OutlineExtractor {
/** {@inheritDoc} */
@Override
- public void visitLeafNode(final BSPTree<Euclidean3D> node) {
+ public void visitLeafNode(final BSPTree<Point3D> node) {
}
/** Add he contribution of a boundary facet.
* @param facet boundary facet
* @param reversed if true, the facet has the inside on its plus side
*/
- private void addContribution(final SubHyperplane<Euclidean3D> facet, final boolean reversed) {
+ private void addContribution(final SubHyperplane<Point3D> facet, final boolean reversed) {
// extract the vertices of the facet
@SuppressWarnings("unchecked")
- final AbstractSubHyperplane<Euclidean3D, Euclidean2D> absFacet =
- (AbstractSubHyperplane<Euclidean3D, Euclidean2D>) facet;
+ final AbstractSubHyperplane<Point3D, Point2D> absFacet =
+ (AbstractSubHyperplane<Point3D, Point2D>) facet;
final Plane plane = (Plane) facet.getHyperplane();
final double scal = plane.getNormal().dotProduct(w);
if (Math.abs(scal) > 1.0e-3) {
- Cartesian2D[][] vertices =
+ Point2D[][] vertices =
((PolygonsSet) absFacet.getRemainingRegion()).getVertices();
if ((scal < 0) ^ reversed) {
// the facet is seen from the inside,
// we need to invert its boundary orientation
- final Cartesian2D[][] newVertices = new Cartesian2D[vertices.length][];
+ final Point2D[][] newVertices = new Point2D[vertices.length][];
for (int i = 0; i < vertices.length; ++i) {
- final Cartesian2D[] loop = vertices[i];
- final Cartesian2D[] newLoop = new Cartesian2D[loop.length];
+ final Point2D[] loop = vertices[i];
+ final Point2D[] newLoop = new Point2D[loop.length];
if (loop[0] == null) {
newLoop[0] = null;
for (int j = 1; j < loop.length; ++j) {
@@ -201,22 +199,22 @@ public class OutlineExtractor {
}
// compute the projection of the facet in the outline plane
- final ArrayList<SubHyperplane<Euclidean2D>> edges = new ArrayList<>();
- for (Cartesian2D[] loop : vertices) {
+ final ArrayList<SubHyperplane<Point2D>> edges = new ArrayList<>();
+ for (Point2D[] loop : vertices) {
final boolean closed = loop[0] != null;
int previous = closed ? (loop.length - 1) : 1;
- Cartesian3D previous3D = plane.toSpace(loop[previous]);
+ Vector3D previous3D = plane.toSpace(loop[previous]).asVector();
int current = (previous + 1) % loop.length;
- Cartesian2D pPoint = new Cartesian2D(previous3D.dotProduct(u),
+ Point2D pPoint = new Point2D(previous3D.dotProduct(u),
previous3D.dotProduct(v));
while (current < loop.length) {
- final Cartesian3D current3D = plane.toSpace((Point<Euclidean2D>) loop[current]);
- final Cartesian2D cPoint = new Cartesian2D(current3D.dotProduct(u),
+ final Vector3D current3D = plane.toSpace(loop[current]).asVector();
+ final Point2D cPoint = new Point2D(current3D.dotProduct(u),
current3D.dotProduct(v));
final org.apache.commons.geometry.euclidean.twod.Line line =
new org.apache.commons.geometry.euclidean.twod.Line(pPoint, cPoint, tolerance);
- SubHyperplane<Euclidean2D> edge = line.wholeHyperplane();
+ SubHyperplane<Point2D> edge = line.wholeHyperplane();
if (closed || (previous != 1)) {
// the previous point is a real vertex
@@ -247,7 +245,7 @@ public class OutlineExtractor {
final PolygonsSet projectedFacet = new PolygonsSet(edges, tolerance);
// add the contribution of the facet to the global outline
- projected = (PolygonsSet) new RegionFactory<Euclidean2D>().union(projected, projectedFacet);
+ projected = (PolygonsSet) new RegionFactory<Point2D>().union(projected, projectedFacet);
}
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java
index 8a54620..5ac48dc 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Plane.java
@@ -16,33 +16,30 @@
*/
package org.apache.commons.geometry.euclidean.threed;
-import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Vector;
import org.apache.commons.geometry.core.partitioning.Embedding;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
-import org.apache.commons.geometry.euclidean.oned.Cartesian1D;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
+import org.apache.commons.geometry.euclidean.oned.Point1D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
/** The class represent planes in a three dimensional space.
*/
-public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Euclidean2D> {
+public class Plane implements Hyperplane<Point3D>, Embedding<Point3D, Point2D> {
/** Offset of the origin with respect to the plane. */
private double originOffset;
/** Origin of the plane frame. */
- private Cartesian3D origin;
+ private Point3D origin;
/** First vector of the plane frame (in plane). */
- private Cartesian3D u;
+ private Vector3D u;
/** Second vector of the plane frame (in plane). */
- private Cartesian3D v;
+ private Vector3D v;
/** Third vector of the plane frame (plane normal). */
- private Cartesian3D w;
+ private Vector3D w;
/** Tolerance below which points are considered identical. */
private final double tolerance;
@@ -52,7 +49,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if the normal norm is too small
*/
- public Plane(final Cartesian3D normal, final double tolerance)
+ public Plane(final Vector3D normal, final double tolerance)
throws IllegalArgumentException {
setNormal(normal);
this.tolerance = tolerance;
@@ -66,11 +63,11 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if the normal norm is too small
*/
- public Plane(final Cartesian3D p, final Cartesian3D normal, final double tolerance)
+ public Plane(final Point3D p, final Vector3D normal, final double tolerance)
throws IllegalArgumentException {
setNormal(normal);
this.tolerance = tolerance;
- originOffset = -p.dotProduct(w);
+ this.originOffset = -p.asVector().dotProduct(w);
setFrame();
}
@@ -83,7 +80,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if the points do not constitute a plane
*/
- public Plane(final Cartesian3D p1, final Cartesian3D p2, final Cartesian3D p3, final double tolerance)
+ public Plane(final Point3D p1, final Point3D p2, final Point3D p3, final double tolerance)
throws IllegalArgumentException {
this(p1, p2.subtract(p1).crossProduct(p3.subtract(p1)), tolerance);
}
@@ -119,9 +116,9 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param normal normal direction to the plane
* @exception IllegalArgumentException if the normal norm is too small
*/
- public void reset(final Cartesian3D p, final Cartesian3D normal) throws IllegalArgumentException {
+ public void reset(final Point3D p, final Vector3D normal) throws IllegalArgumentException {
setNormal(normal);
- originOffset = -p.dotProduct(w);
+ originOffset = -p.asVector().dotProduct(w);
setFrame();
}
@@ -143,20 +140,20 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param normal normal direction to the plane (will be copied)
* @exception IllegalArgumentException if the normal norm is too close to zero
*/
- private void setNormal(final Cartesian3D normal) throws IllegalArgumentException {
+ private void setNormal(final Vector3D normal) throws IllegalArgumentException {
final double norm = normal.getNorm();
if (norm < 1.0e-10) {
throw new IllegalArgumentException("Norm is zero");
}
- w = new Cartesian3D(1.0 / norm, normal);
+ w = Vector3D.linearCombination(1.0 / norm, normal);
}
/** Reset the plane frame.
*/
private void setFrame() {
- origin = new Cartesian3D(-originOffset, w);
+ origin = Vector3D.linearCombination(-originOffset, w).asPoint();
u = w.orthogonal();
- v = Cartesian3D.crossProduct(w, u);
+ v = w.crossProduct(u);
}
/** Get the origin point of the plane frame.
@@ -165,7 +162,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @return the origin point of the plane frame (point closest to the
* 3D-space origin)
*/
- public Cartesian3D getOrigin() {
+ public Point3D getOrigin() {
return origin;
}
@@ -177,7 +174,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @see #getU
* @see #getV
*/
- public Cartesian3D getNormal() {
+ public Vector3D getNormal() {
return w;
}
@@ -189,7 +186,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @see #getV
* @see #getNormal
*/
- public Cartesian3D getU() {
+ public Vector3D getU() {
return u;
}
@@ -201,13 +198,13 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @see #getU
* @see #getNormal
*/
- public Cartesian3D getV() {
+ public Vector3D getV() {
return v;
}
/** {@inheritDoc} */
@Override
- public Point<Euclidean3D> project(Point<Euclidean3D> point) {
+ public Point3D project(Point3D point) {
return toSpace(toSubSpace(point));
}
@@ -229,67 +226,32 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* reversed.</p>
*/
public void revertSelf() {
- final Cartesian3D tmp = u;
+ final Vector3D tmp = u;
u = v;
v = tmp;
w = w.negate();
originOffset = -originOffset;
}
- /** Transform a space vector into a sub-space vector.
- * @param vector n-dimension vector of the space
- * @return (n-1)-dimension vector of the sub-space corresponding to
- * the specified space vector
- */
- public Cartesian2D toSubSpace(Vector<Euclidean3D> vector) {
- return toSubSpace((Cartesian3D) vector);
- }
-
- /** Transform a sub-space point into a space point.
- * @param vector (n-1)-dimension point of the sub-space
- * @return n-dimension point of the space corresponding to the
- * specified sub-space point
- */
- public Cartesian3D toSpace(Vector<Euclidean2D> vector) {
- return toSpace((Cartesian2D) vector);
- }
-
/** Transform a 3D space point into an in-plane point.
- * @param point point of the space (must be a {@link Cartesian3D} instance)
+ * @param point point of the space (must be a {@link Point3D} instance)
* @return in-plane point
* @see #toSpace
*/
@Override
- public Cartesian2D toSubSpace(final Point<Euclidean3D> point) {
- return toSubSpace((Cartesian3D) point);
+ public Point2D toSubSpace(final Point3D point) {
+ Vector3D vec = point.asVector();
+ return new Point2D(vec.dotProduct(u), vec.dotProduct(v));
}
/** Transform an in-plane point into a 3D space point.
- * @param point in-plane point (must be a {@link Cartesian2D} instance)
+ * @param point in-plane point (must be a {@link Point2D} instance)
* @return 3D space point
* @see #toSubSpace
*/
@Override
- public Cartesian3D toSpace(final Point<Euclidean2D> point) {
- return toSpace((Cartesian2D) point);
- }
-
- /** Transform a 3D space point into an in-plane point.
- * @param point point of the space
- * @return in-plane point
- * @see #toSpace
- */
- public Cartesian2D toSubSpace(final Cartesian3D point) {
- return new Cartesian2D(point.dotProduct(u), point.dotProduct(v));
- }
-
- /** Transform an in-plane point into a 3D space point.
- * @param point in-plane point
- * @return 3D space point
- * @see #toSubSpace
- */
- public Cartesian3D toSpace(final Cartesian2D point) {
- return new Cartesian3D(point.getX(), u, point.getY(), v, -originOffset, w);
+ public Point3D toSpace(final Point2D point) {
+ return Point3D.vectorCombination(point.getX(), u, point.getY(), v, -originOffset, w);
}
/** Get one point from the 3D-space.
@@ -299,8 +261,8 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @return one point in the 3D-space, with given coordinates and offset
* relative to the plane
*/
- public Cartesian3D getPointAt(final Cartesian2D inPlane, final double offset) {
- return new Cartesian3D(inPlane.getX(), u, inPlane.getY(), v, offset - originOffset, w);
+ public Point3D getPointAt(final Point2D inPlane, final double offset) {
+ return Point3D.vectorCombination(inPlane.getX(), u, inPlane.getY(), v, offset - originOffset, w);
}
/** Check if the instance is similar to another plane.
@@ -311,7 +273,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @return true if the planes are similar
*/
public boolean isSimilarTo(final Plane plane) {
- final double angle = Cartesian3D.angle(w, plane.w);
+ final double angle = w.angle(plane.w);
return ((angle < 1.0e-10) && (Math.abs(originOffset - plane.originOffset) < tolerance)) ||
((angle > (Math.PI - 1.0e-10)) && (Math.abs(originOffset + plane.originOffset) < tolerance));
}
@@ -322,9 +284,9 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param rotation vectorial rotation operator
* @return a new plane
*/
- public Plane rotate(final Cartesian3D center, final Rotation rotation) {
+ public Plane rotate(final Point3D center, final Rotation rotation) {
- final Cartesian3D delta = origin.subtract(center);
+ final Vector3D delta = origin.subtract(center);
final Plane plane = new Plane(center.add(rotation.applyTo(delta)),
rotation.applyTo(w), tolerance);
@@ -341,7 +303,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param translation translation to apply
* @return a new plane
*/
- public Plane translate(final Cartesian3D translation) {
+ public Plane translate(final Vector3D translation) {
final Plane plane = new Plane(origin.add(translation), w, tolerance);
@@ -358,15 +320,15 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @return intersection point between between the line and the
* instance (null if the line is parallel to the instance)
*/
- public Cartesian3D intersection(final Line line) {
- final Cartesian3D direction = line.getDirection();
+ public Point3D intersection(final Line line) {
+ final Vector3D direction = line.getDirection();
final double dot = w.dotProduct(direction);
if (Math.abs(dot) < 1.0e-10) {
return null;
}
- final Cartesian3D point = line.toSpace(Cartesian1D.ZERO);
- final double k = -(originOffset + w.dotProduct(point)) / dot;
- return new Cartesian3D(1.0, point, k, direction);
+ final Point3D point = line.toSpace(Point1D.ZERO);
+ final double k = -(originOffset + w.dotProduct(point.asVector())) / dot;
+ return Point3D.vectorCombination(1.0, point, k, direction);
}
/** Build the line shared by the instance and another plane.
@@ -375,11 +337,11 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* other plane (really a {@link Line Line} instance)
*/
public Line intersection(final Plane other) {
- final Cartesian3D direction = Cartesian3D.crossProduct(w, other.w);
+ final Vector3D direction = w.crossProduct(other.w);
if (direction.getNorm() < tolerance) {
return null;
}
- final Cartesian3D point = intersection(this, other, new Plane(direction, tolerance));
+ final Point3D point = intersection(this, other, new Plane(direction, tolerance));
return new Line(point, point.add(direction), tolerance);
}
@@ -389,7 +351,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param plane3 third plane2
* @return intersection point of three planes, null if some planes are parallel
*/
- public static Cartesian3D intersection(final Plane plane1, final Plane plane2, final Plane plane3) {
+ public static Point3D intersection(final Plane plane1, final Plane plane2, final Plane plane3) {
// coefficients of the three planes linear equations
final double a1 = plane1.w.getX();
@@ -418,7 +380,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
}
final double r = 1.0 / determinant;
- return new Cartesian3D(
+ return new Point3D(
(-a23 * d1 - (c1 * b3 - c3 * b1) * d2 - (c2 * b1 - c1 * b2) * d3) * r,
(-b23 * d1 - (c3 * a1 - c1 * a3) * d2 - (c1 * a2 - c2 * a1) * d3) * r,
(-c23 * d1 - (b1 * a3 - b3 * a1) * d2 - (b2 * a1 - b1 * a2) * d3) * r);
@@ -446,7 +408,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @param p point to check
* @return true if p belongs to the plane
*/
- public boolean contains(final Cartesian3D p) {
+ public boolean contains(final Point3D p) {
return Math.abs(getOffset(p)) < tolerance;
}
@@ -464,14 +426,6 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
return originOffset + (sameOrientationAs(plane) ? -plane.originOffset : plane.originOffset);
}
- /** Get the offset (oriented distance) of a vector.
- * @param vector vector to check
- * @return offset of the vector
- */
-// public double getOffset(Vector<Euclidean3D> vector) {
-// return getOffset((Point<Euclidean3D>) vector);
-// }
-
/** Get the offset (oriented distance) of a point.
* <p>The offset is 0 if the point is on the underlying hyperplane,
* it is positive if the point is on one particular side of the
@@ -481,8 +435,8 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* @return offset of the point
*/
@Override
- public double getOffset(final Point<Euclidean3D> point) {
- return ((Cartesian3D) point).dotProduct(w) + originOffset;
+ public double getOffset(final Point3D point) {
+ return point.asVector().dotProduct(w) + originOffset;
}
/** Check if the instance has the same orientation as another hyperplane.
@@ -491,7 +445,7 @@ public class Plane implements Hyperplane<Euclidean3D>, Embedding<Euclidean3D, Eu
* the same orientation
*/
@Override
- public boolean sameOrientationAs(final Hyperplane<Euclidean3D> other) {
+ public boolean sameOrientationAs(final Hyperplane<Point3D> other) {
return (((Plane) other).w).dotProduct(w) > 0.0;
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java
new file mode 100644
index 0000000..a91f03e
--- /dev/null
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java
@@ -0,0 +1,291 @@
+/*
+ * 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.geometry.euclidean.threed;
+
+import org.apache.commons.geometry.euclidean.EuclideanPoint;
+import org.apache.commons.numbers.arrays.LinearCombination;
+
+/** This class represents a point in three-dimensional Euclidean space.
+ * Instances of this class are guaranteed to be immutable.
+ */
+public final class Point3D extends Cartesian3D implements EuclideanPoint<Point3D, Vector3D> {
+
+ /** Zero point (coordinates: 0, 0, 0). */
+ public static final Point3D ZERO = new Point3D(0, 0, 0);
+
+ // CHECKSTYLE: stop ConstantName
+ /** A point with all coordinates set to NaN. */
+ public static final Point3D NaN = new Point3D(Double.NaN, Double.NaN, Double.NaN);
+ // CHECKSTYLE: resume ConstantName
+
+ /** A point with all coordinates set to positive infinity. */
+ public static final Point3D POSITIVE_INFINITY =
+ new Point3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
+
+ /** A point with all coordinates set to negative infinity. */
+ public static final Point3D NEGATIVE_INFINITY =
+ new Point3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
+
+ /** Serializable version identifier. */
+ private static final long serialVersionUID = 1313493323784566947L;
+
+ /** Simple constructor.
+ * Build a point from its coordinates
+ * @param x abscissa
+ * @param y ordinate
+ * @param z height
+ */
+ public Point3D(double x, double y, double z) {
+ super(x, y, z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D asVector() {
+ return Vector3D.of(x, y, z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distance(Point3D p) {
+ return euclideanDistance(p);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D subtract(Point3D p) {
+ return new Vector3D(
+ x - p.x,
+ y - p.y,
+ z - p.z
+ );
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D vectorTo(Point3D p) {
+ return p.subtract(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Point3D add(Vector3D v) {
+ return new Point3D(
+ x + v.x,
+ y + v.y,
+ z + v.z
+ );
+ }
+
+ /**
+ * Get a hashCode for the point.
+ * <p>All NaN values have the same hash code.</p>
+ *
+ * @return a hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ if (isNaN()) {
+ return 642;
+ }
+ return 643 * (164 * Double.hashCode(x) + 3 * Double.hashCode(y) + Double.hashCode(z));
+ }
+
+ /** Test for the equality of two points.
+ * <p>
+ * If all coordinates of two points are exactly the same, and none are
+ * <code>Double.NaN</code>, the two points are considered to be equal.
+ * </p>
+ * <p>
+ * <code>NaN</code> coordinates are considered to globally affect the point
+ * and be equal to each other - i.e, if either (or all) coordinates of the
+ * point are equal to <code>Double.NaN</code>, the point is equal to
+ * {@link #NaN}.
+ * </p>
+ *
+ * @param other Object to test for equality to this
+ * @return true if two Point3D objects are equal, false if
+ * object is null, not an instance of Point3D, or
+ * not equal to this Point3D instance
+ *
+ */
+ @Override
+ public boolean equals(Object other) {
+
+ if (this == other) {
+ return true;
+ }
+
+ if (other instanceof Point3D) {
+ final Point3D rhs = (Point3D) other;
+ if (rhs.isNaN()) {
+ return this.isNaN();
+ }
+
+ return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "(" + x + "; " + y + "; " + z + ")";
+ }
+
+ /** Returns a point with the given coordinate values
+ * @param x abscissa (first coordinate value)
+ * @param y ordinate (second coordinate value)
+ * @param z height (third coordinate value)
+ * @return point instance
+ */
+ public static Point3D of(double x, double y, double z) {
+ return new Point3D(x, y, z);
+ }
+
+ /** Returns a point with the given coordinates.
+ * @param value coordinate values
+ * @return point instance
+ */
+ public static Point3D of(Cartesian3D value) {
+ return new Point3D(value.x, value.y, value.z);
+ }
+
+ /** Creates a point from the coordinates in the given 3-element array.
+ * @param p coordinates array
+ * @return new point
+ * @exception IllegalArgumentException if the array does not have 3 elements
+ */
+ public static Point3D of(double[] p) {
+ if (p.length != 3) {
+ throw new IllegalArgumentException("Dimension mismatch: " + p.length + " != 3");
+ }
+ return new Point3D(p[0], p[1], p[2]);
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a scale factor for first coordinate
+ * @param c first coordinate
+ * @return point with coordinates calculated by {@code a * c}
+ */
+ public static Point3D vectorCombination(double a, Cartesian3D c) {
+ return new Point3D(a * c.x, a * c.y, a * c.z);
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2)}
+ */
+ public static Point3D vectorCombination(double a1, Cartesian3D c1, double a2, Cartesian3D c2) {
+ return new Point3D(
+ LinearCombination.value(a1, c1.x, a2, c2.x),
+ LinearCombination.value(a1, c1.y, a2, c2.y),
+ LinearCombination.value(a1, c1.z, a2, c2.z));
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3)}
+ */
+ public static Point3D vectorCombination(double a1, Cartesian3D c1, double a2, Cartesian3D c2,
+ double a3, Cartesian3D c3) {
+ return new Point3D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x),
+ LinearCombination.value(a1, c1.y, a2, c2.y, a3, c3.y),
+ LinearCombination.value(a1, c1.z, a2, c2.z, a3, c3.z));
+ }
+
+ /** Returns a point with coordinates calculated by multiplying each input coordinate
+ * with its corresponding factor and adding the results.
+ *
+ * <p>This is equivalent
+ * to converting all input coordinates to vectors, scaling and adding the
+ * vectors (a linear combination), and adding the result to the zero point.
+ * This method, however, does not create any intermediate objects.
+ * </p>
+ * <p>
+ * The name of this method was chosen to emphasize the fact that the operation
+ * should be viewed as occurring in vector space, since addition and scalar
+ * multiplication are not defined directly for points.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @param a4 scale factor for fourth coordinate
+ * @param c4 fourth coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3) + (a4 * c4)}
+ */
+ public static Point3D vectorCombination(double a1, Cartesian3D c1, double a2, Cartesian3D c2,
+ double a3, Cartesian3D c3, double a4, Cartesian3D c4) {
+ return new Point3D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x, a4, c4.x),
+ LinearCombination.value(a1, c1.y, a2, c2.y, a3, c3.y, a4, c4.y),
+ LinearCombination.value(a1, c1.z, a2, c2.z, a3, c3.z, a4, c4.z));
+ }
+}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/PolyhedronsSet.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/PolyhedronsSet.java
index 6cb2771..d70efba 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/PolyhedronsSet.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/PolyhedronsSet.java
@@ -31,15 +31,14 @@ import org.apache.commons.geometry.core.partitioning.Region;
import org.apache.commons.geometry.core.partitioning.RegionFactory;
import org.apache.commons.geometry.core.partitioning.SubHyperplane;
import org.apache.commons.geometry.core.partitioning.Transform;
-import org.apache.commons.geometry.euclidean.oned.Euclidean1D;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
+import org.apache.commons.geometry.euclidean.oned.Point1D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
import org.apache.commons.geometry.euclidean.twod.SubLine;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
/** This class represents a 3D region: a set of polyhedrons.
*/
-public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
+public class PolyhedronsSet extends AbstractRegion<Point3D, Point2D> {
/** Build a polyhedrons set representing the whole real line.
* @param tolerance tolerance below which points are considered identical
@@ -68,7 +67,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @param tree inside/outside BSP tree representing the region
* @param tolerance tolerance below which points are considered identical
*/
- public PolyhedronsSet(final BSPTree<Euclidean3D> tree, final double tolerance) {
+ public PolyhedronsSet(final BSPTree<Point3D> tree, final double tolerance) {
super(tree, tolerance);
}
@@ -92,7 +91,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* collection of {@link SubHyperplane SubHyperplane} objects
* @param tolerance tolerance below which points are considered identical
*/
- public PolyhedronsSet(final Collection<SubHyperplane<Euclidean3D>> boundary,
+ public PolyhedronsSet(final Collection<SubHyperplane<Point3D>> boundary,
final double tolerance) {
super(boundary, tolerance);
}
@@ -114,7 +113,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if some basic sanity checks fail
*/
- public PolyhedronsSet(final List<Cartesian3D> vertices, final List<int[]> facets,
+ public PolyhedronsSet(final List<Point3D> vertices, final List<int[]> facets,
final double tolerance) {
super(buildBoundary(vertices, facets, tolerance), tolerance);
}
@@ -145,7 +144,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @param tolerance tolerance below which points are considered identical
* @return boundary tree
*/
- private static BSPTree<Euclidean3D> buildBoundary(final double xMin, final double xMax,
+ private static BSPTree<Point3D> buildBoundary(final double xMin, final double xMax,
final double yMin, final double yMax,
final double zMin, final double zMax,
final double tolerance) {
@@ -153,14 +152,14 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
// too thin box, build an empty polygons set
return new BSPTree<>(Boolean.FALSE);
}
- final Plane pxMin = new Plane(new Cartesian3D(xMin, 0, 0), Cartesian3D.MINUS_I, tolerance);
- final Plane pxMax = new Plane(new Cartesian3D(xMax, 0, 0), Cartesian3D.PLUS_I, tolerance);
- final Plane pyMin = new Plane(new Cartesian3D(0, yMin, 0), Cartesian3D.MINUS_J, tolerance);
- final Plane pyMax = new Plane(new Cartesian3D(0, yMax, 0), Cartesian3D.PLUS_J, tolerance);
- final Plane pzMin = new Plane(new Cartesian3D(0, 0, zMin), Cartesian3D.MINUS_K, tolerance);
- final Plane pzMax = new Plane(new Cartesian3D(0, 0, zMax), Cartesian3D.PLUS_K, tolerance);
- final Region<Euclidean3D> boundary =
- new RegionFactory<Euclidean3D>().buildConvex(pxMin, pxMax, pyMin, pyMax, pzMin, pzMax);
+ final Plane pxMin = new Plane(new Point3D(xMin, 0, 0), Vector3D.MINUS_X, tolerance);
+ final Plane pxMax = new Plane(new Point3D(xMax, 0, 0), Vector3D.PLUS_X, tolerance);
+ final Plane pyMin = new Plane(new Point3D(0, yMin, 0), Vector3D.MINUS_Y, tolerance);
+ final Plane pyMax = new Plane(new Point3D(0, yMax, 0), Vector3D.PLUS_Y, tolerance);
+ final Plane pzMin = new Plane(new Point3D(0, 0, zMin), Vector3D.MINUS_Z, tolerance);
+ final Plane pzMax = new Plane(new Point3D(0, 0, zMax), Vector3D.PLUS_Z, tolerance);
+ final Region<Point3D> boundary =
+ new RegionFactory<Point3D>().buildConvex(pxMin, pxMax, pyMin, pyMax, pzMin, pzMax);
return boundary.getTree(false);
}
@@ -171,15 +170,15 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @return boundary as a list of sub-hyperplanes
* @exception IllegalArgumentException if some basic sanity checks fail
*/
- private static List<SubHyperplane<Euclidean3D>> buildBoundary(final List<Cartesian3D> vertices,
+ private static List<SubHyperplane<Point3D>> buildBoundary(final List<Point3D> vertices,
final List<int[]> facets,
final double tolerance) {
// check vertices distances
for (int i = 0; i < vertices.size() - 1; ++i) {
- final Cartesian3D vi = vertices.get(i);
+ final Point3D vi = vertices.get(i);
for (int j = i + 1; j < vertices.size(); ++j) {
- if (Cartesian3D.distance(vi, vertices.get(j)) <= tolerance) {
+ if (vi.distance(vertices.get(j)) <= tolerance) {
throw new IllegalArgumentException("Vertices are too close near point " + vi);
}
}
@@ -203,15 +202,15 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
found = found || (v == vA);
}
if (!found) {
- final Cartesian3D start = vertices.get(vA);
- final Cartesian3D end = vertices.get(vB);
+ final Point3D start = vertices.get(vA);
+ final Point3D end = vertices.get(vB);
throw new IllegalArgumentException("Edge joining points " + start + " and " + end + " is connected to one facet only");
}
}
}
}
- final List<SubHyperplane<Euclidean3D>> boundary = new ArrayList<>();
+ final List<SubHyperplane<Point3D>> boundary = new ArrayList<>();
for (final int[] facet : facets) {
@@ -220,9 +219,9 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
tolerance);
// check all points are in the plane
- final Cartesian2D[] two2Points = new Cartesian2D[facet.length];
+ final Point2D[] two2Points = new Point2D[facet.length];
for (int i = 0 ; i < facet.length; ++i) {
- final Cartesian3D v = vertices.get(facet[i]);
+ final Point3D v = vertices.get(facet[i]);
if (!plane.contains(v)) {
throw new IllegalArgumentException("Point " + v + " is out of plane");
}
@@ -244,7 +243,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @return references array such that r[v][k] = f for some k if facet f contains vertex v
* @exception IllegalArgumentException if some facets have fewer than 3 vertices
*/
- private static int[][] findReferences(final List<Cartesian3D> vertices, final List<int[]> facets) {
+ private static int[][] findReferences(final List<Point3D> vertices, final List<int[]> facets) {
// find the maximum number of facets a vertex belongs to
final int[] nbFacets = new int[vertices.size()];
@@ -288,7 +287,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* once in the successors list (which means one facet orientation is wrong)
*/
- private static int[][] successors(final List<Cartesian3D> vertices, final List<int[]> facets,
+ private static int[][] successors(final List<Point3D> vertices, final List<int[]> facets,
final int[][] references) {
// create an array large enough
@@ -311,8 +310,8 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
successors[v][k] = facet[(i + 1) % facet.length];
for (int l = 0; l < k; ++l) {
if (successors[v][l] == successors[v][k]) {
- final Cartesian3D start = vertices.get(v);
- final Cartesian3D end = vertices.get(successors[v][k]);
+ final Point3D start = vertices.get(v);
+ final Point3D end = vertices.get(successors[v][k]);
throw new IllegalArgumentException("Facet orientation mismatch around edge joining points " + start + " and " + end);
}
}
@@ -326,7 +325,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
/** {@inheritDoc} */
@Override
- public PolyhedronsSet buildNew(final BSPTree<Euclidean3D> tree) {
+ public PolyhedronsSet buildNew(final BSPTree<Point3D> tree) {
return new PolyhedronsSet(tree, getTolerance());
}
@@ -336,11 +335,11 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
// check simple cases first
if (isEmpty()) {
setSize(0.0);
- setBarycenter((Point<Euclidean3D>) Cartesian3D.NaN);
+ setBarycenter(Point3D.NaN);
}
else if (isFull()) {
setSize(Double.POSITIVE_INFINITY);
- setBarycenter((Point<Euclidean3D>) Cartesian3D.NaN);
+ setBarycenter(Point3D.NaN);
}
else {
// not empty or full; compute the contribution of all boundary facets
@@ -348,16 +347,16 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
getTree(true).visit(contributionVisitor);
final double size = contributionVisitor.getSize();
- final Cartesian3D barycenter = contributionVisitor.getBarycenter();
+ final Point3D barycenter = contributionVisitor.getBarycenter();
if (size < 0) {
// the polyhedrons set is a finite outside surrounded by an infinite inside
setSize(Double.POSITIVE_INFINITY);
- setBarycenter((Point<Euclidean3D>) Cartesian3D.NaN);
+ setBarycenter(Point3D.NaN);
} else {
// the polyhedrons set is finite
setSize(size);
- setBarycenter((Point<Euclidean3D>) barycenter);
+ setBarycenter(barycenter);
}
}
}
@@ -376,13 +375,13 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* line from the apex to the base. The polyhedron barycenter then becomes
* the volume-weighted average of these pyramid centers.
*/
- private static class FacetsContributionVisitor implements BSPTreeVisitor<Euclidean3D> {
+ private static class FacetsContributionVisitor implements BSPTreeVisitor<Point3D> {
/** Accumulator for facet volume contributions. */
private double volumeSum;
/** Accumulator for barycenter contributions. */
- private Cartesian3D barycenterSum = Cartesian3D.ZERO;
+ private Point3D barycenterSum = Point3D.ZERO;
/** Returns the total computed size (ie, volume) of the polyhedron.
* This value will be negative if the polyhedron is "inside-out", meaning
@@ -399,25 +398,25 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* region is infinite.
* @return the barycenter.
*/
- public Cartesian3D getBarycenter() {
+ public Point3D getBarycenter() {
// Since the volume we used when adding together the facet contributions
// was 3x the actual pyramid size, we'll multiply by 1/4 here instead
// of 3/4 to adjust for the actual barycenter position in each pyramid.
- return new Cartesian3D(1.0 / (4 * getSize()), barycenterSum);
+ return Point3D.vectorCombination(1.0 / (4 * getSize()), barycenterSum);
}
/** {@inheritDoc} */
@Override
- public Order visitOrder(final BSPTree<Euclidean3D> node) {
+ public Order visitOrder(final BSPTree<Point3D> node) {
return Order.MINUS_SUB_PLUS;
}
/** {@inheritDoc} */
@Override
- public void visitInternalNode(final BSPTree<Euclidean3D> node) {
+ public void visitInternalNode(final BSPTree<Point3D> node) {
@SuppressWarnings("unchecked")
- final BoundaryAttribute<Euclidean3D> attribute =
- (BoundaryAttribute<Euclidean3D>) node.getAttribute();
+ final BoundaryAttribute<Point3D> attribute =
+ (BoundaryAttribute<Point3D>) node.getAttribute();
if (attribute.getPlusOutside() != null) {
addContribution(attribute.getPlusOutside(), false);
}
@@ -428,34 +427,34 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
/** {@inheritDoc} */
@Override
- public void visitLeafNode(final BSPTree<Euclidean3D> node) {
+ public void visitLeafNode(final BSPTree<Point3D> node) {
}
/** Add the contribution of a boundary facet.
* @param facet boundary facet
* @param reversed if true, the facet has the inside on its plus side
*/
- private void addContribution(final SubHyperplane<Euclidean3D> facet, final boolean reversed) {
+ private void addContribution(final SubHyperplane<Point3D> facet, final boolean reversed) {
- final Region<Euclidean2D> polygon = ((SubPlane) facet).getRemainingRegion();
+ final Region<Point2D> polygon = ((SubPlane) facet).getRemainingRegion();
final double area = polygon.getSize();
if (Double.isInfinite(area)) {
volumeSum = Double.POSITIVE_INFINITY;
- barycenterSum = Cartesian3D.NaN;
+ barycenterSum = Point3D.NaN;
} else {
final Plane plane = (Plane) facet.getHyperplane();
- final Cartesian3D facetBarycenter = plane.toSpace(polygon.getBarycenter());
+ final Point3D facetBarycenter = plane.toSpace(polygon.getBarycenter());
// the volume here is actually 3x the actual pyramid volume; we'll apply
// the final scaling all at once at the end
- double scaledVolume = area * facetBarycenter.dotProduct(plane.getNormal());
+ double scaledVolume = area * facetBarycenter.asVector().dotProduct(plane.getNormal());
if (reversed) {
scaledVolume = -scaledVolume;
}
volumeSum += scaledVolume;
- barycenterSum = new Cartesian3D(1.0, barycenterSum, scaledVolume, facetBarycenter);
+ barycenterSum = Point3D.vectorCombination(1.0, barycenterSum, scaledVolume, facetBarycenter);
}
}
}
@@ -467,7 +466,7 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* given point, or null if the line does not intersect any
* sub-hyperplane
*/
- public SubHyperplane<Euclidean3D> firstIntersection(final Cartesian3D point, final Line line) {
+ public SubHyperplane<Point3D> firstIntersection(final Point3D point, final Line line) {
return recurseFirstIntersection(getTree(true), point, line);
}
@@ -479,23 +478,23 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* given point, or null if the line does not intersect any
* sub-hyperplane
*/
- private SubHyperplane<Euclidean3D> recurseFirstIntersection(final BSPTree<Euclidean3D> node,
- final Cartesian3D point,
+ private SubHyperplane<Point3D> recurseFirstIntersection(final BSPTree<Point3D> node,
+ final Point3D point,
final Line line) {
- final SubHyperplane<Euclidean3D> cut = node.getCut();
+ final SubHyperplane<Point3D> cut = node.getCut();
if (cut == null) {
return null;
}
- final BSPTree<Euclidean3D> minus = node.getMinus();
- final BSPTree<Euclidean3D> plus = node.getPlus();
+ final BSPTree<Point3D> minus = node.getMinus();
+ final BSPTree<Point3D> plus = node.getPlus();
final Plane plane = (Plane) cut.getHyperplane();
// establish search order
final double offset = plane.getOffset(point);
final boolean in = Math.abs(offset) < getTolerance();
- final BSPTree<Euclidean3D> near;
- final BSPTree<Euclidean3D> far;
+ final BSPTree<Point3D> near;
+ final BSPTree<Point3D> far;
if (offset < 0) {
near = minus;
far = plus;
@@ -506,23 +505,23 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
if (in) {
// search in the cut hyperplane
- final SubHyperplane<Euclidean3D> facet = boundaryFacet(point, node);
+ final SubHyperplane<Point3D> facet = boundaryFacet(point, node);
if (facet != null) {
return facet;
}
}
// search in the near branch
- final SubHyperplane<Euclidean3D> crossed = recurseFirstIntersection(near, point, line);
+ final SubHyperplane<Point3D> crossed = recurseFirstIntersection(near, point, line);
if (crossed != null) {
return crossed;
}
if (!in) {
// search in the cut hyperplane
- final Cartesian3D hit3D = plane.intersection(line);
+ final Point3D hit3D = plane.intersection(line);
if (hit3D != null && line.getAbscissa(hit3D) > line.getAbscissa(point)) {
- final SubHyperplane<Euclidean3D> facet = boundaryFacet(hit3D, node);
+ final SubHyperplane<Point3D> facet = boundaryFacet(hit3D, node);
if (facet != null) {
return facet;
}
@@ -540,12 +539,12 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @return the boundary facet this points belongs to (or null if it
* does not belong to any boundary facet)
*/
- private SubHyperplane<Euclidean3D> boundaryFacet(final Cartesian3D point,
- final BSPTree<Euclidean3D> node) {
- final Cartesian2D point2D = ((Plane) node.getCut().getHyperplane()).toSubSpace(point);
+ private SubHyperplane<Point3D> boundaryFacet(final Point3D point,
+ final BSPTree<Point3D> node) {
+ final Point2D point2D = ((Plane) node.getCut().getHyperplane()).toSubSpace(point);
@SuppressWarnings("unchecked")
- final BoundaryAttribute<Euclidean3D> attribute =
- (BoundaryAttribute<Euclidean3D>) node.getAttribute();
+ final BoundaryAttribute<Point3D> attribute =
+ (BoundaryAttribute<Point3D>) node.getAttribute();
if ((attribute.getPlusOutside() != null) &&
(((SubPlane) attribute.getPlusOutside()).getRemainingRegion().checkPoint(point2D) == Location.INSIDE)) {
return attribute.getPlusOutside();
@@ -563,15 +562,15 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @param rotation vectorial rotation operator
* @return a new instance representing the rotated region
*/
- public PolyhedronsSet rotate(final Cartesian3D center, final Rotation rotation) {
+ public PolyhedronsSet rotate(final Point3D center, final Rotation rotation) {
return (PolyhedronsSet) applyTransform(new RotationTransform(center, rotation));
}
/** 3D rotation as a Transform. */
- private static class RotationTransform implements Transform<Euclidean3D, Euclidean2D> {
+ private static class RotationTransform implements Transform<Point3D, Point2D> {
/** Center point of the rotation. */
- private final Cartesian3D center;
+ private final Point3D center;
/** Vectorial rotation. */
private final Rotation rotation;
@@ -580,46 +579,46 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
private Plane cachedOriginal;
/** Cached 2D transform valid inside the cached original hyperplane. */
- private Transform<Euclidean2D, Euclidean1D> cachedTransform;
+ private Transform<Point2D, Point1D> cachedTransform;
/** Build a rotation transform.
* @param center center point of the rotation
* @param rotation vectorial rotation
*/
- RotationTransform(final Cartesian3D center, final Rotation rotation) {
+ RotationTransform(final Point3D center, final Rotation rotation) {
this.center = center;
this.rotation = rotation;
}
/** {@inheritDoc} */
@Override
- public Cartesian3D apply(final Point<Euclidean3D> point) {
- final Cartesian3D delta = ((Cartesian3D) point).subtract(center);
- return new Cartesian3D(1.0, center, 1.0, rotation.applyTo(delta));
+ public Point3D apply(final Point3D point) {
+ final Vector3D delta = point.subtract(center);
+ return Point3D.vectorCombination(1.0, center, 1.0, rotation.applyTo(delta));
}
/** {@inheritDoc} */
@Override
- public Plane apply(final Hyperplane<Euclidean3D> hyperplane) {
+ public Plane apply(final Hyperplane<Point3D> hyperplane) {
return ((Plane) hyperplane).rotate(center, rotation);
}
/** {@inheritDoc} */
@Override
- public SubHyperplane<Euclidean2D> apply(final SubHyperplane<Euclidean2D> sub,
- final Hyperplane<Euclidean3D> original,
- final Hyperplane<Euclidean3D> transformed) {
+ public SubHyperplane<Point2D> apply(final SubHyperplane<Point2D> sub,
+ final Hyperplane<Point3D> original,
+ final Hyperplane<Point3D> transformed) {
if (original != cachedOriginal) {
// we have changed hyperplane, reset the in-hyperplane transform
final Plane oPlane = (Plane) original;
final Plane tPlane = (Plane) transformed;
- final Cartesian3D p00 = oPlane.getOrigin();
- final Cartesian3D p10 = oPlane.toSpace(new Cartesian2D(1.0, 0.0));
- final Cartesian3D p01 = oPlane.toSpace(new Cartesian2D(0.0, 1.0));
- final Cartesian2D tP00 = tPlane.toSubSpace(apply(p00));
- final Cartesian2D tP10 = tPlane.toSubSpace(apply(p10));
- final Cartesian2D tP01 = tPlane.toSubSpace(apply(p01));
+ final Point3D p00 = oPlane.getOrigin();
+ final Point3D p10 = oPlane.toSpace(new Point2D(1.0, 0.0));
+ final Point3D p01 = oPlane.toSpace(new Point2D(0.0, 1.0));
+ final Point2D tP00 = tPlane.toSubSpace(apply(p00));
+ final Point2D tP10 = tPlane.toSubSpace(apply(p10));
+ final Point2D tP01 = tPlane.toSubSpace(apply(p01));
cachedOriginal = (Plane) original;
cachedTransform =
@@ -641,52 +640,52 @@ public class PolyhedronsSet extends AbstractRegion<Euclidean3D, Euclidean2D> {
* @param translation translation to apply
* @return a new instance representing the translated region
*/
- public PolyhedronsSet translate(final Cartesian3D translation) {
+ public PolyhedronsSet translate(final Vector3D translation) {
return (PolyhedronsSet) applyTransform(new TranslationTransform(translation));
}
/** 3D translation as a transform. */
- private static class TranslationTransform implements Transform<Euclidean3D, Euclidean2D> {
+ private static class TranslationTransform implements Transform<Point3D, Point2D> {
/** Translation vector. */
- private final Cartesian3D translation;
+ private final Vector3D translation;
/** Cached original hyperplane. */
private Plane cachedOriginal;
/** Cached 2D transform valid inside the cached original hyperplane. */
- private Transform<Euclidean2D, Euclidean1D> cachedTransform;
+ private Transform<Point2D, Point1D> cachedTransform;
/** Build a translation transform.
* @param translation translation vector
*/
- TranslationTransform(final Cartesian3D translation) {
+ TranslationTransform(final Vector3D translation) {
this.translation = translation;
}
/** {@inheritDoc} */
@Override
- public Cartesian3D apply(final Point<Euclidean3D> point) {
- return new Cartesian3D(1.0, (Cartesian3D) point, 1.0, translation);
+ public Point3D apply(final Point3D point) {
+ return Point3D.vectorCombination(1.0, point, 1.0, translation);
}
/** {@inheritDoc} */
@Override
- public Plane apply(final Hyperplane<Euclidean3D> hyperplane) {
+ public Plane apply(final Hyperplane<Point3D> hyperplane) {
return ((Plane) hyperplane).translate(translation);
}
/** {@inheritDoc} */
@Override
- public SubHyperplane<Euclidean2D> apply(final SubHyperplane<Euclidean2D> sub,
- final Hyperplane<Euclidean3D> original,
- final Hyperplane<Euclidean3D> transformed) {
+ public SubHyperplane<Point2D> apply(final SubHyperplane<Point2D> sub,
+ final Hyperplane<Point3D> original,
+ final Hyperplane<Point3D> transformed) {
if (original != cachedOriginal) {
// we have changed hyperplane, reset the in-hyperplane transform
final Plane oPlane = (Plane) original;
final Plane tPlane = (Plane) transformed;
- final Cartesian2D shift = tPlane.toSubSpace(apply(oPlane.getOrigin()));
+ final Point2D shift = tPlane.toSubSpace(apply(oPlane.getOrigin()));
cachedOriginal = (Plane) original;
cachedTransform =
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java
index eac61f1..7261fd1 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Rotation.java
@@ -44,8 +44,8 @@ import org.apache.commons.numbers.arrays.LinearCombination;
* <p>Focus is oriented on what a rotation <em>do</em> rather than on its
* underlying representation. Once it has been built, and regardless of its
* internal representation, a rotation is an <em>operator</em> which basically
- * transforms three dimensional {@link Cartesian3D vectors} into other three
- * dimensional {@link Cartesian3D vectors}. Depending on the application, the
+ * transforms three dimensional {@link Vector3D vectors} into other three
+ * dimensional {@link Vector3D vectors}. Depending on the application, the
* meaning of these vectors may vary and the semantics of the rotation also.</p>
* <p>For example in an spacecraft attitude simulation tool, users will often
* consider the vectors are fixed (say the Earth direction for example) and the
@@ -68,8 +68,8 @@ import org.apache.commons.numbers.arrays.LinearCombination;
* class does not push the user towards one specific definition and hence does not
* provide methods like <code>projectVectorIntoDestinationFrame</code> or
* <code>computeTransformedDirection</code>. It provides simpler and more generic
- * methods: {@link #applyTo(Cartesian3D) applyTo(Cartesian3D)} and {@link
- * #applyInverseTo(Cartesian3D) applyInverseTo(Cartesian3D)}.</p>
+ * methods: {@link #applyTo(Vector3D) applyTo(Cartesian3D)} and {@link
+ * #applyInverseTo(Vector3D) applyInverseTo(Cartesian3D)}.</p>
*
* <p>Since a rotation is basically a vectorial operator, several rotations can be
* composed together and the composite operation <code>r = r<sub>1</sub> o
@@ -84,7 +84,7 @@ import org.apache.commons.numbers.arrays.LinearCombination;
*
* <p>Rotations are guaranteed to be immutable objects.</p>
*
- * @see Cartesian3D
+ * @see Vector3D
* @see RotationOrder
*/
@@ -154,16 +154,16 @@ public class Rotation implements Serializable {
/** Build a rotation from an axis and an angle.
* <p>
* Calling this constructor is equivalent to call
- * {@link #Rotation(Cartesian3D, double, RotationConvention)
+ * {@link #Rotation(Vector3D, double, RotationConvention)
* new Rotation(axis, angle, RotationConvention.VECTOR_OPERATOR)}
* </p>
* @param axis axis around which to rotate
* @param angle rotation angle.
* @exception IllegalArgumentException if the axis norm is zero
- * @deprecated as of 3.6, replaced with {@link #Rotation(Cartesian3D, double, RotationConvention)}
+ * @deprecated as of 3.6, replaced with {@link #Rotation(Vector3D, double, RotationConvention)}
*/
@Deprecated
- public Rotation(Cartesian3D axis, double angle) throws IllegalArgumentException {
+ public Rotation(Vector3D axis, double angle) throws IllegalArgumentException {
this(axis, angle, RotationConvention.VECTOR_OPERATOR);
}
@@ -173,7 +173,7 @@ public class Rotation implements Serializable {
* @param convention convention to use for the semantics of the angle
* @exception IllegalArgumentException if the axis norm is zero
*/
- public Rotation(final Cartesian3D axis, final double angle, final RotationConvention convention)
+ public Rotation(final Vector3D axis, final double angle, final RotationConvention convention)
throws IllegalArgumentException {
double norm = axis.getNorm();
@@ -267,19 +267,19 @@ public class Rotation implements Serializable {
* @exception IllegalArgumentException if the norm of one of the vectors is zero,
* or if one of the pair is degenerated (i.e. the vectors of the pair are collinear)
*/
- public Rotation(Cartesian3D u1, Cartesian3D u2, Cartesian3D v1, Cartesian3D v2)
+ public Rotation(Vector3D u1, Vector3D u2, Vector3D v1, Vector3D v2)
throws IllegalArgumentException {
try {
// build orthonormalized base from u1, u2
// this fails when vectors are null or collinear, which is forbidden to define a rotation
- final Cartesian3D u3 = u1.crossProduct(u2).normalize();
+ final Vector3D u3 = u1.crossProduct(u2).normalize();
u2 = u3.crossProduct(u1).normalize();
u1 = u1.normalize();
// build an orthonormalized base from v1, v2
// this fails when vectors are null or collinear, which is forbidden to define a rotation
- final Cartesian3D v3 = v1.crossProduct(v2).normalize();
+ final Vector3D v3 = v1.crossProduct(v2).normalize();
v2 = v3.crossProduct(v1).normalize();
v1 = v1.normalize();
@@ -327,7 +327,7 @@ public class Rotation implements Serializable {
* @param v desired image of u by the rotation
* @exception IllegalArgumentException if the norm of one of the vectors is zero
*/
- public Rotation(Cartesian3D u, Cartesian3D v) throws IllegalArgumentException {
+ public Rotation(Vector3D u, Vector3D v) throws IllegalArgumentException {
double normProduct = u.getNorm() * v.getNorm();
if (normProduct == 0) {
@@ -339,7 +339,7 @@ public class Rotation implements Serializable {
if (dot < ((2.0e-15 - 1.0) * normProduct)) {
// special case u = -v: we select a PI angle rotation around
// an arbitrary vector orthogonal to u
- Cartesian3D w = u.orthogonal();
+ Vector3D w = u.orthogonal();
q0 = 0.0;
q1 = -w.getX();
q2 = -w.getY();
@@ -349,7 +349,7 @@ public class Rotation implements Serializable {
// the shortest possible rotation: axis orthogonal to this plane
q0 = Math.sqrt(0.5 * (1.0 + dot / normProduct));
double coeff = 1.0 / (2.0 * q0 * normProduct);
- Cartesian3D q = v.crossProduct(u);
+ Vector3D q = v.crossProduct(u);
q1 = coeff * q.getX();
q2 = coeff * q.getY();
q3 = coeff * q.getZ();
@@ -517,11 +517,11 @@ public class Rotation implements Serializable {
* {@link #getAxis(RotationConvention) getAxis(RotationConvention.VECTOR_OPERATOR)}
* </p>
* @return normalized axis of the rotation
- * @see #Rotation(Cartesian3D, double, RotationConvention)
+ * @see #Rotation(Vector3D, double, RotationConvention)
* @deprecated as of 3.6, replaced with {@link #getAxis(RotationConvention)}
*/
@Deprecated
- public Cartesian3D getAxis() {
+ public Vector3D getAxis() {
return getAxis(RotationConvention.VECTOR_OPERATOR);
}
@@ -533,26 +533,26 @@ public class Rotation implements Serializable {
* </p>
* @param convention convention to use for the semantics of the angle
* @return normalized axis of the rotation
- * @see #Rotation(Cartesian3D, double, RotationConvention)
+ * @see #Rotation(Vector3D, double, RotationConvention)
*/
- public Cartesian3D getAxis(final RotationConvention convention) {
+ public Vector3D getAxis(final RotationConvention convention) {
final double squaredSine = q1 * q1 + q2 * q2 + q3 * q3;
if (squaredSine == 0) {
- return convention == RotationConvention.VECTOR_OPERATOR ? Cartesian3D.PLUS_I : Cartesian3D.MINUS_I;
+ return convention == RotationConvention.VECTOR_OPERATOR ? Vector3D.PLUS_X : Vector3D.MINUS_X;
} else {
final double sgn = convention == RotationConvention.VECTOR_OPERATOR ? +1 : -1;
if (q0 < 0) {
final double inverse = sgn / Math.sqrt(squaredSine);
- return new Cartesian3D(q1 * inverse, q2 * inverse, q3 * inverse);
+ return new Vector3D(q1 * inverse, q2 * inverse, q3 * inverse);
}
final double inverse = -sgn / Math.sqrt(squaredSine);
- return new Cartesian3D(q1 * inverse, q2 * inverse, q3 * inverse);
+ return new Vector3D(q1 * inverse, q2 * inverse, q3 * inverse);
}
}
/** Get the angle of the rotation.
* @return angle of the rotation (between 0 and π)
- * @see #Rotation(Cartesian3D, double)
+ * @see #Rotation(Vector3D, double)
*/
public double getAngle() {
if ((q0 < -0.1) || (q0 > 0.1)) {
@@ -630,8 +630,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (psi) cos (theta), -sin (psi) cos (theta), sin (theta)
// and we can choose to have theta in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -648,8 +648,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (theta) cos (psi), -sin (psi), sin (theta) cos (psi)
// and we can choose to have psi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -666,8 +666,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// sin (psi) cos (phi), cos (psi) cos (phi), -sin (phi)
// and we can choose to have phi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -684,8 +684,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// sin (psi), cos (phi) cos (psi), -sin (phi) cos (psi)
// and we can choose to have psi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -702,8 +702,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// -sin (theta) cos (phi), sin (phi), cos (theta) cos (phi)
// and we can choose to have phi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -720,8 +720,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// -sin (theta), sin (phi) cos (theta), cos (phi) cos (theta)
// and we can choose to have theta in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -738,8 +738,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (theta), sin (theta) sin (phi2), sin (theta) cos (phi2)
// and we can choose to have theta in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -756,8 +756,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (psi), -sin (psi) cos (phi2), sin (psi) sin (phi2)
// and we can choose to have psi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -774,8 +774,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// sin (phi) sin (theta2), cos (phi), -sin (phi) cos (theta2)
// and we can choose to have phi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -792,8 +792,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// sin (psi) cos (theta2), cos (psi), sin (psi) sin (theta2)
// and we can choose to have psi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -810,8 +810,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// sin (phi) sin (psi2), sin (phi) cos (psi2), cos (phi)
// and we can choose to have phi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -828,8 +828,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// -sin (theta) cos (psi2), sin (theta) sin (psi2), cos (theta)
// and we can choose to have theta in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -848,8 +848,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// sin (theta), -sin (phi) cos (theta), cos (phi) cos (theta)
// and we can choose to have theta in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -866,8 +866,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// -sin (psi), cos (phi) cos (psi), sin (phi) cos (psi)
// and we can choose to have psi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -884,8 +884,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// sin (theta) cos (phi), -sin (phi), cos (theta) cos (phi)
// and we can choose to have phi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -902,8 +902,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (theta) cos (psi), sin (psi), -sin (theta) cos (psi)
// and we can choose to have psi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -920,8 +920,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// -sin (psi) cos (phi), cos (psi) cos (phi), sin (phi)
// and we can choose to have phi in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -938,8 +938,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (psi) cos (theta), sin (psi) cos (theta), -sin (theta)
// and we can choose to have theta in the interval [-PI/2 ; +PI/2]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(CARDAN_SINGULARITY_MSG);
}
@@ -956,8 +956,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (theta), sin (theta) sin (phi1), -sin (theta) cos (phi1)
// and we can choose to have theta in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -974,8 +974,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusI) coordinates are :
// cos (psi), sin (psi) cos (phi1), sin (psi) sin (phi1)
// and we can choose to have psi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_I);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_I);
+ Vector3D v1 = applyTo(Vector3D.PLUS_X);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_X);
if ((v2.getX() < -0.9999999999) || (v2.getX() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -992,8 +992,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// sin (theta1) sin (phi), cos (phi), cos (theta1) sin (phi)
// and we can choose to have phi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -1010,8 +1010,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusJ) coordinates are :
// -cos (theta1) sin (psi), cos (psi), sin (theta1) sin (psi)
// and we can choose to have psi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_J);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_J);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Y);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Y);
if ((v2.getY() < -0.9999999999) || (v2.getY() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -1028,8 +1028,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// sin (psi1) sin (phi), -cos (psi1) sin (phi), cos (phi)
// and we can choose to have phi in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -1046,8 +1046,8 @@ public class Rotation implements Serializable {
// (-r) (Cartesian3D.plusK) coordinates are :
// cos (psi1) sin (theta), sin (psi1) sin (theta), cos (theta)
// and we can choose to have theta in the interval [0 ; PI]
- Cartesian3D v1 = applyTo(Cartesian3D.PLUS_K);
- Cartesian3D v2 = applyInverseTo(Cartesian3D.PLUS_K);
+ Vector3D v1 = applyTo(Vector3D.PLUS_Z);
+ Vector3D v2 = applyInverseTo(Vector3D.PLUS_Z);
if ((v2.getZ() < -0.9999999999) || (v2.getZ() > 0.9999999999)) {
throw new IllegalStateException(EULER_SINGULARITY_MSG);
}
@@ -1105,7 +1105,7 @@ public class Rotation implements Serializable {
* @param u vector to apply the rotation to
* @return a new vector which is the image of u by the rotation
*/
- public Cartesian3D applyTo(Cartesian3D u) {
+ public Vector3D applyTo(Vector3D u) {
double x = u.getX();
double y = u.getY();
@@ -1113,7 +1113,7 @@ public class Rotation implements Serializable {
double s = q1 * x + q2 * y + q3 * z;
- return new Cartesian3D(2 * (q0 * (x * q0 - (q2 * z - q3 * y)) + s * q1) - x,
+ return new Vector3D(2 * (q0 * (x * q0 - (q2 * z - q3 * y)) + s * q1) - x,
2 * (q0 * (y * q0 - (q3 * x - q1 * z)) + s * q2) - y,
2 * (q0 * (z * q0 - (q1 * y - q2 * x)) + s * q3) - z);
@@ -1142,7 +1142,7 @@ public class Rotation implements Serializable {
* @param u vector to apply the inverse of the rotation to
* @return a new vector which such that u is its image by the rotation
*/
- public Cartesian3D applyInverseTo(Cartesian3D u) {
+ public Vector3D applyInverseTo(Vector3D u) {
double x = u.getX();
double y = u.getY();
@@ -1151,7 +1151,7 @@ public class Rotation implements Serializable {
double s = q1 * x + q2 * y + q3 * z;
double m0 = -q0;
- return new Cartesian3D(2 * (m0 * (x * m0 - (q2 * z - q3 * y)) + s * q1) - x,
+ return new Vector3D(2 * (m0 * (x * m0 - (q2 * z - q3 * y)) + s * q1) - x,
2 * (m0 * (y * m0 - (q3 * x - q1 * z)) + s * q2) - y,
2 * (m0 * (z * m0 - (q1 * y - q2 * x)) + s * q3) - z);
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/RotationOrder.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/RotationOrder.java
index 7e0a042..0d0e440 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/RotationOrder.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/RotationOrder.java
@@ -33,96 +33,96 @@ public final class RotationOrder {
* around Z
*/
public static final RotationOrder XYZ =
- new RotationOrder("XYZ", Cartesian3D.PLUS_I, Cartesian3D.PLUS_J, Cartesian3D.PLUS_K);
+ new RotationOrder("XYZ", Vector3D.PLUS_X, Vector3D.PLUS_Y, Vector3D.PLUS_Z);
/** Set of Cardan angles.
* this ordered set of rotations is around X, then around Z, then
* around Y
*/
public static final RotationOrder XZY =
- new RotationOrder("XZY", Cartesian3D.PLUS_I, Cartesian3D.PLUS_K, Cartesian3D.PLUS_J);
+ new RotationOrder("XZY", Vector3D.PLUS_X, Vector3D.PLUS_Z, Vector3D.PLUS_Y);
/** Set of Cardan angles.
* this ordered set of rotations is around Y, then around X, then
* around Z
*/
public static final RotationOrder YXZ =
- new RotationOrder("YXZ", Cartesian3D.PLUS_J, Cartesian3D.PLUS_I, Cartesian3D.PLUS_K);
+ new RotationOrder("YXZ", Vector3D.PLUS_Y, Vector3D.PLUS_X, Vector3D.PLUS_Z);
/** Set of Cardan angles.
* this ordered set of rotations is around Y, then around Z, then
* around X
*/
public static final RotationOrder YZX =
- new RotationOrder("YZX", Cartesian3D.PLUS_J, Cartesian3D.PLUS_K, Cartesian3D.PLUS_I);
+ new RotationOrder("YZX", Vector3D.PLUS_Y, Vector3D.PLUS_Z, Vector3D.PLUS_X);
/** Set of Cardan angles.
* this ordered set of rotations is around Z, then around X, then
* around Y
*/
public static final RotationOrder ZXY =
- new RotationOrder("ZXY", Cartesian3D.PLUS_K, Cartesian3D.PLUS_I, Cartesian3D.PLUS_J);
+ new RotationOrder("ZXY", Vector3D.PLUS_Z, Vector3D.PLUS_X, Vector3D.PLUS_Y);
/** Set of Cardan angles.
* this ordered set of rotations is around Z, then around Y, then
* around X
*/
public static final RotationOrder ZYX =
- new RotationOrder("ZYX", Cartesian3D.PLUS_K, Cartesian3D.PLUS_J, Cartesian3D.PLUS_I);
+ new RotationOrder("ZYX", Vector3D.PLUS_Z, Vector3D.PLUS_Y, Vector3D.PLUS_X);
/** Set of Euler angles.
* this ordered set of rotations is around X, then around Y, then
* around X
*/
public static final RotationOrder XYX =
- new RotationOrder("XYX", Cartesian3D.PLUS_I, Cartesian3D.PLUS_J, Cartesian3D.PLUS_I);
+ new RotationOrder("XYX", Vector3D.PLUS_X, Vector3D.PLUS_Y, Vector3D.PLUS_X);
/** Set of Euler angles.
* this ordered set of rotations is around X, then around Z, then
* around X
*/
public static final RotationOrder XZX =
- new RotationOrder("XZX", Cartesian3D.PLUS_I, Cartesian3D.PLUS_K, Cartesian3D.PLUS_I);
+ new RotationOrder("XZX", Vector3D.PLUS_X, Vector3D.PLUS_Z, Vector3D.PLUS_X);
/** Set of Euler angles.
* this ordered set of rotations is around Y, then around X, then
* around Y
*/
public static final RotationOrder YXY =
- new RotationOrder("YXY", Cartesian3D.PLUS_J, Cartesian3D.PLUS_I, Cartesian3D.PLUS_J);
+ new RotationOrder("YXY", Vector3D.PLUS_Y, Vector3D.PLUS_X, Vector3D.PLUS_Y);
/** Set of Euler angles.
* this ordered set of rotations is around Y, then around Z, then
* around Y
*/
public static final RotationOrder YZY =
- new RotationOrder("YZY", Cartesian3D.PLUS_J, Cartesian3D.PLUS_K, Cartesian3D.PLUS_J);
+ new RotationOrder("YZY", Vector3D.PLUS_Y, Vector3D.PLUS_Z, Vector3D.PLUS_Y);
/** Set of Euler angles.
* this ordered set of rotations is around Z, then around X, then
* around Z
*/
public static final RotationOrder ZXZ =
- new RotationOrder("ZXZ", Cartesian3D.PLUS_K, Cartesian3D.PLUS_I, Cartesian3D.PLUS_K);
+ new RotationOrder("ZXZ", Vector3D.PLUS_Z, Vector3D.PLUS_X, Vector3D.PLUS_Z);
/** Set of Euler angles.
* this ordered set of rotations is around Z, then around Y, then
* around Z
*/
public static final RotationOrder ZYZ =
- new RotationOrder("ZYZ", Cartesian3D.PLUS_K, Cartesian3D.PLUS_J, Cartesian3D.PLUS_K);
+ new RotationOrder("ZYZ", Vector3D.PLUS_Z, Vector3D.PLUS_Y, Vector3D.PLUS_Z);
/** Name of the rotations order. */
private final String name;
/** Axis of the first rotation. */
- private final Cartesian3D a1;
+ private final Vector3D a1;
/** Axis of the second rotation. */
- private final Cartesian3D a2;
+ private final Vector3D a2;
/** Axis of the third rotation. */
- private final Cartesian3D a3;
+ private final Vector3D a3;
/** Private constructor.
* This is a utility class that cannot be instantiated by the user,
@@ -133,7 +133,7 @@ public final class RotationOrder {
* @param a3 axis of the third rotation
*/
private RotationOrder(final String name,
- final Cartesian3D a1, final Cartesian3D a2, final Cartesian3D a3) {
+ final Vector3D a1, final Vector3D a2, final Vector3D a3) {
this.name = name;
this.a1 = a1;
this.a2 = a2;
@@ -151,21 +151,21 @@ public final class RotationOrder {
/** Get the axis of the first rotation.
* @return axis of the first rotation
*/
- public Cartesian3D getA1() {
+ public Vector3D getA1() {
return a1;
}
/** Get the axis of the second rotation.
* @return axis of the second rotation
*/
- public Cartesian3D getA2() {
+ public Vector3D getA2() {
return a2;
}
/** Get the axis of the second rotation.
* @return axis of the second rotation
*/
- public Cartesian3D getA3() {
+ public Vector3D getA3() {
return a3;
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Segment.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Segment.java
index e9681a1..93825d5 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Segment.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Segment.java
@@ -22,10 +22,10 @@ package org.apache.commons.geometry.euclidean.threed;
public class Segment {
/** Start point of the segment. */
- private final Cartesian3D start;
+ private final Point3D start;
/** End point of the segments. */
- private final Cartesian3D end;
+ private final Point3D end;
/** Line containing the segment. */
private final Line line;
@@ -35,7 +35,7 @@ public class Segment {
* @param end end point of the segment
* @param line line containing the segment
*/
- public Segment(final Cartesian3D start, final Cartesian3D end, final Line line) {
+ public Segment(final Point3D start, final Point3D end, final Line line) {
this.start = start;
this.end = end;
this.line = line;
@@ -44,14 +44,14 @@ public class Segment {
/** Get the start point of the segment.
* @return start point of the segment
*/
- public Cartesian3D getStart() {
+ public Point3D getStart() {
return start;
}
/** Get the end point of the segment.
* @return end point of the segment
*/
- public Cartesian3D getEnd() {
+ public Point3D getEnd() {
return end;
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubLine.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubLine.java
index 2be477f..fdf511b 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubLine.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubLine.java
@@ -19,11 +19,10 @@ package org.apache.commons.geometry.euclidean.threed;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.partitioning.Region.Location;
-import org.apache.commons.geometry.euclidean.oned.Cartesian1D;
import org.apache.commons.geometry.euclidean.oned.Interval;
import org.apache.commons.geometry.euclidean.oned.IntervalsSet;
+import org.apache.commons.geometry.euclidean.oned.Point1D;
/** This class represents a subset of a {@link Line}.
*/
@@ -50,7 +49,7 @@ public class SubLine {
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if the points are equal
*/
- public SubLine(final Cartesian3D start, final Cartesian3D end, final double tolerance)
+ public SubLine(final Point3D start, final Point3D end, final double tolerance)
throws IllegalArgumentException {
this(new Line(start, end, tolerance), buildIntervalSet(start, end, tolerance));
}
@@ -84,8 +83,8 @@ public class SubLine {
final List<Segment> segments = new ArrayList<>(list.size());
for (final Interval interval : list) {
- final Cartesian3D start = line.toSpace(new Cartesian1D(interval.getInf()));
- final Cartesian3D end = line.toSpace(new Cartesian1D(interval.getSup()));
+ final Point3D start = line.toSpace(new Point1D(interval.getInf()));
+ final Point3D end = line.toSpace(new Point1D(interval.getSup()));
segments.add(new Segment(start, end, line));
}
@@ -107,19 +106,19 @@ public class SubLine {
* occurring on endpoints lead to null being returned
* @return the intersection point if there is one, null if the sub-lines don't intersect
*/
- public Cartesian3D intersection(final SubLine subLine, final boolean includeEndPoints) {
+ public Point3D intersection(final SubLine subLine, final boolean includeEndPoints) {
// compute the intersection on infinite line
- Cartesian3D v1D = line.intersection(subLine.line);
+ Point3D v1D = line.intersection(subLine.line);
if (v1D == null) {
return null;
}
// check location of point with respect to first sub-line
- Location loc1 = remainingRegion.checkPoint(line.toSubSpace((Point<Euclidean3D>) v1D));
+ Location loc1 = remainingRegion.checkPoint(line.toSubSpace(v1D));
// check location of point with respect to second sub-line
- Location loc2 = subLine.remainingRegion.checkPoint(subLine.line.toSubSpace((Point<Euclidean3D>) v1D));
+ Location loc2 = subLine.remainingRegion.checkPoint(subLine.line.toSubSpace(v1D));
if (includeEndPoints) {
return ((loc1 != Location.OUTSIDE) && (loc2 != Location.OUTSIDE)) ? v1D : null;
@@ -136,11 +135,11 @@ public class SubLine {
* @param tolerance tolerance below which points are considered identical
* @exception IllegalArgumentException if the points are equal
*/
- private static IntervalsSet buildIntervalSet(final Cartesian3D start, final Cartesian3D end, final double tolerance)
+ private static IntervalsSet buildIntervalSet(final Point3D start, final Point3D end, final double tolerance)
throws IllegalArgumentException {
final Line line = new Line(start, end, tolerance);
- return new IntervalsSet(line.toSubSpace((Point<Euclidean3D>) start).getX(),
- line.toSubSpace((Point<Euclidean3D>) end).getX(),
+ return new IntervalsSet(line.toSubSpace(start).getX(),
+ line.toSubSpace(end).getX(),
tolerance);
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubPlane.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubPlane.java
index 7b38e64..c2848b2 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubPlane.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/SubPlane.java
@@ -21,28 +21,27 @@ import org.apache.commons.geometry.core.partitioning.BSPTree;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.Region;
import org.apache.commons.geometry.core.partitioning.SubHyperplane;
-import org.apache.commons.geometry.euclidean.oned.Cartesian1D;
-import org.apache.commons.geometry.euclidean.twod.Euclidean2D;
+import org.apache.commons.geometry.euclidean.oned.Point1D;
+import org.apache.commons.geometry.euclidean.twod.Point2D;
import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
-import org.apache.commons.geometry.euclidean.twod.Cartesian2D;
/** This class represents a sub-hyperplane for {@link Plane}.
*/
-public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> {
+public class SubPlane extends AbstractSubHyperplane<Point3D, Point2D> {
/** Simple constructor.
* @param hyperplane underlying hyperplane
* @param remainingRegion remaining region of the hyperplane
*/
- public SubPlane(final Hyperplane<Euclidean3D> hyperplane,
- final Region<Euclidean2D> remainingRegion) {
+ public SubPlane(final Hyperplane<Point3D> hyperplane,
+ final Region<Point2D> remainingRegion) {
super(hyperplane, remainingRegion);
}
/** {@inheritDoc} */
@Override
- protected AbstractSubHyperplane<Euclidean3D, Euclidean2D> buildNew(final Hyperplane<Euclidean3D> hyperplane,
- final Region<Euclidean2D> remainingRegion) {
+ protected AbstractSubHyperplane<Point3D, Point2D> buildNew(final Hyperplane<Point3D> hyperplane,
+ final Region<Point2D> remainingRegion) {
return new SubPlane(hyperplane, remainingRegion);
}
@@ -53,7 +52,7 @@ public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> {
* instance on the minus side of the instance
*/
@Override
- public SplitSubHyperplane<Euclidean3D> split(Hyperplane<Euclidean3D> hyperplane) {
+ public SplitSubHyperplane<Point3D> split(Hyperplane<Point3D> hyperplane) {
final Plane otherPlane = (Plane) hyperplane;
final Plane thisPlane = (Plane) getHyperplane();
@@ -73,28 +72,28 @@ public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> {
}
// the hyperplanes do intersect
- Cartesian2D p = thisPlane.toSubSpace(inter.toSpace(Cartesian1D.ZERO));
- Cartesian2D q = thisPlane.toSubSpace(inter.toSpace(Cartesian1D.ONE));
- Cartesian3D crossP = Cartesian3D.crossProduct(inter.getDirection(), thisPlane.getNormal());
+ Point2D p = thisPlane.toSubSpace(inter.toSpace(Point1D.ZERO));
+ Point2D q = thisPlane.toSubSpace(inter.toSpace(Point1D.ONE));
+ Vector3D crossP = inter.getDirection().crossProduct(thisPlane.getNormal());
if (crossP.dotProduct(otherPlane.getNormal()) < 0) {
- final Cartesian2D tmp = p;
+ final Point2D tmp = p;
p = q;
q = tmp;
}
- final SubHyperplane<Euclidean2D> l2DMinus =
+ final SubHyperplane<Point2D> l2DMinus =
new org.apache.commons.geometry.euclidean.twod.Line(p, q, tolerance).wholeHyperplane();
- final SubHyperplane<Euclidean2D> l2DPlus =
+ final SubHyperplane<Point2D> l2DPlus =
new org.apache.commons.geometry.euclidean.twod.Line(q, p, tolerance).wholeHyperplane();
- final BSPTree<Euclidean2D> splitTree = getRemainingRegion().getTree(false).split(l2DMinus);
- final BSPTree<Euclidean2D> plusTree = getRemainingRegion().isEmpty(splitTree.getPlus()) ?
- new BSPTree<Euclidean2D>(Boolean.FALSE) :
- new BSPTree<>(l2DPlus, new BSPTree<Euclidean2D>(Boolean.FALSE),
+ final BSPTree<Point2D> splitTree = getRemainingRegion().getTree(false).split(l2DMinus);
+ final BSPTree<Point2D> plusTree = getRemainingRegion().isEmpty(splitTree.getPlus()) ?
+ new BSPTree<Point2D>(Boolean.FALSE) :
+ new BSPTree<>(l2DPlus, new BSPTree<Point2D>(Boolean.FALSE),
splitTree.getPlus(), null);
- final BSPTree<Euclidean2D> minusTree = getRemainingRegion().isEmpty(splitTree.getMinus()) ?
- new BSPTree<Euclidean2D>(Boolean.FALSE) :
- new BSPTree<>(l2DMinus, new BSPTree<Euclidean2D>(Boolean.FALSE),
+ final BSPTree<Point2D> minusTree = getRemainingRegion().isEmpty(splitTree.getMinus()) ?
+ new BSPTree<Point2D>(Boolean.FALSE) :
+ new BSPTree<>(l2DMinus, new BSPTree<Point2D>(Boolean.FALSE),
splitTree.getMinus(), null);
return new SplitSubHyperplane<>(new SubPlane(thisPlane.copySelf(), new PolygonsSet(plusTree, tolerance)),
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
index 03efa55..9e9d39d 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
@@ -14,32 +14,524 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.commons.geometry.euclidean.threed;
-import org.apache.commons.geometry.core.Vector;
+import org.apache.commons.geometry.euclidean.EuclideanVector;
+import org.apache.commons.numbers.arrays.LinearCombination;
-/**
- * This class implements vectors in a three-dimensional space.
+/** This class represents a vector in three-dimensional Euclidean space.
+ * Instances of this class are guaranteed to be immutable.
*/
-public abstract class Vector3D implements Vector<Euclidean3D> {
+public class Vector3D extends Cartesian3D implements EuclideanVector<Point3D, Vector3D> {
+
+ /** Zero (null) vector (coordinates: 0, 0, 0). */
+ public static final Vector3D ZERO = new Vector3D(0, 0, 0);
+
+ /** First canonical vector (coordinates: 1, 0, 0). */
+ public static final Vector3D PLUS_X = new Vector3D(1, 0, 0);
+
+ /** Opposite of the first canonical vector (coordinates: -1, 0, 0). */
+ public static final Vector3D MINUS_X = new Vector3D(-1, 0, 0);
+
+ /** Second canonical vector (coordinates: 0, 1, 0). */
+ public static final Vector3D PLUS_Y = new Vector3D(0, 1, 0);
+
+ /** Opposite of the second canonical vector (coordinates: 0, -1, 0). */
+ public static final Vector3D MINUS_Y = new Vector3D(0, -1, 0);
+
+ /** Third canonical vector (coordinates: 0, 0, 1). */
+ public static final Vector3D PLUS_Z = new Vector3D(0, 0, 1);
+
+ /** Opposite of the third canonical vector (coordinates: 0, 0, -1). */
+ public static final Vector3D MINUS_Z = new Vector3D(0, 0, -1);
+
+ // CHECKSTYLE: stop ConstantName
+ /** A vector with all coordinates set to NaN. */
+ public static final Vector3D NaN = new Vector3D(Double.NaN, Double.NaN, Double.NaN);
+ // CHECKSTYLE: resume ConstantName
+
+ /** A vector with all coordinates set to positive infinity. */
+ public static final Vector3D POSITIVE_INFINITY =
+ new Vector3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see Cartesian3D#Cartesian3D(double, double, double)
+ /** A vector with all coordinates set to negative infinity. */
+ public static final Vector3D NEGATIVE_INFINITY =
+ new Vector3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
+
+ /** Serializable UID */
+ private static final long serialVersionUID = 3695385854431542858L;
+
+ /** Error message when norms are zero. */
+ private static final String ZERO_NORM_MSG = "Norm is zero";
+
+ /** Simple constructor.
+ * Build a vector from its coordinates
+ * @param x abscissa
+ * @param y ordinate
+ * @param z height
*/
- public abstract double getX();
+ public Vector3D(double x, double y, double z) {
+ super(x, y, z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D getZero() {
+ return ZERO;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Point3D asPoint() {
+ return Point3D.of(x, y, z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNorm1() {
+ return Math.abs(x) + Math.abs(y) + Math.abs(z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNorm() {
+ // there are no cancellation problems here, so we use the straightforward formula
+ return Math.sqrt ((x * x) + (y * y) + (z * z));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNormSq() {
+ // there are no cancellation problems here, so we use the straightforward formula
+ return (x * x) + (y * y) + (z * z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double getNormInf() {
+ return Math.max(Math.max(Math.abs(x), Math.abs(y)), Math.abs(z));
+ }
- /** Get the ordinate of the vector.
- * @return ordinate of the vector
- * @see Cartesian3D#Cartesian3D(double, double, double)
+ /** Get the azimuth of the vector.
+ * @return azimuth (α) of the vector, between -π and +π
*/
- public abstract double getY();
+ public double getAlpha() {
+ return Math.atan2(y, x);
+ }
- /** Get the height of the vector.
- * @return height of the vector
- * @see Cartesian3D#Cartesian3D(double, double, double)
+ /** Get the elevation of the vector.
+ * @return elevation (δ) of the vector, between -π/2 and +π/2
*/
- public abstract double getZ();
+ public double getDelta() {
+ return Math.asin(z / getNorm());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D add(Vector3D v) {
+ return new Vector3D(
+ x + v.x,
+ y + v.y,
+ z + v.z
+ );
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D add(double factor, Vector3D v) {
+ return new Vector3D(
+ x + (factor * v.x),
+ y + (factor * v.y),
+ z + (factor * v.z)
+ );
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D subtract(Vector3D v) {
+ return new Vector3D(
+ x - v.x,
+ y - v.y,
+ z - v.z
+ );
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D subtract(double factor, Vector3D v) {
+ return new Vector3D(
+ x - (factor * v.x),
+ y - (factor * v.y),
+ z - (factor * v.z)
+ );
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D negate() {
+ return new Vector3D(-x, -y, -z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D normalize() throws IllegalStateException {
+ double s = getNorm();
+ if (s == 0) {
+ throw new IllegalStateException(ZERO_NORM_MSG);
+ }
+ return scalarMultiply(1 / s);
+ }
+
+ /** Get a vector orthogonal to the instance.
+ * <p>There are an infinite number of normalized vectors orthogonal
+ * to the instance. This method picks up one of them almost
+ * arbitrarily. It is useful when one needs to compute a reference
+ * frame with one of the axes in a predefined direction. The
+ * following example shows how to build a frame having the k axis
+ * aligned with the known vector u :
+ * <pre><code>
+ * Vector3D k = u.normalize();
+ * Vector3D i = k.orthogonal();
+ * Vector3D j = Vector3D.crossProduct(k, i);
+ * </code></pre>
+ * @return a new normalized vector orthogonal to the instance
+ * @exception IllegalStateException if the norm of the instance is zero
+ */
+ public Vector3D orthogonal() throws IllegalStateException {
+ double threshold = 0.6 * getNorm();
+ if (threshold == 0) {
+ throw new IllegalStateException(ZERO_NORM_MSG);
+ }
+
+ if (Math.abs(x) <= threshold) {
+ double inverse = 1 / Math.sqrt(y * y + z * z);
+ return new Vector3D(0, inverse * z, -inverse * y);
+ } else if (Math.abs(y) <= threshold) {
+ double inverse = 1 / Math.sqrt(x * x + z * z);
+ return new Vector3D(-inverse * z, 0, inverse * x);
+ }
+ double inverse = 1 / Math.sqrt(x * x + y * y);
+ return new Vector3D(inverse * y, -inverse * x, 0);
+ }
+
+ /** Compute the angular separation between two vectors.
+ * <p>This method computes the angular separation between two
+ * vectors using the dot product for well separated vectors and the
+ * cross product for almost aligned vectors. This allows to have a
+ * good accuracy in all cases, even for vectors very close to each
+ * other.</p>
+ * @param v other vector
+ * @return angular separation between this instance and v
+ * @exception IllegalStateException if either vector has a zero norm
+ */
+ public double angle(Vector3D v) throws IllegalStateException {
+ double normProduct = getNorm() * v.getNorm();
+ if (normProduct == 0) {
+ throw new IllegalStateException(ZERO_NORM_MSG);
+ }
+
+ double dot = dotProduct(v);
+ double threshold = normProduct * 0.9999;
+ if ((dot < -threshold) || (dot > threshold)) {
+ // the vectors are almost aligned, compute using the sine
+ Vector3D cross = crossProduct(v);
+ if (dot >= 0) {
+ return Math.asin(cross.getNorm() / normProduct);
+ }
+ return Math.PI - Math.asin(cross.getNorm() / normProduct);
+ }
+
+ // the vectors are sufficiently separated to use the cosine
+ return Math.acos(dot / normProduct);
+ }
+
+ /** Compute the cross-product of the instance with another vector.
+ * @param v other vector
+ * @return the cross product this ^ v as a new Cartesian3D
+ */
+ public Vector3D crossProduct(final Vector3D v) {
+ return new Vector3D(LinearCombination.value(y, v.z, -z, v.y),
+ LinearCombination.value(z, v.x, -x, v.z),
+ LinearCombination.value(x, v.y, -y, v.x));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Vector3D scalarMultiply(double a) {
+ return new Vector3D(a * x, a * y, a * z);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distance1(Vector3D v) {
+ double dx = Math.abs(v.x - x);
+ double dy = Math.abs(v.y - y);
+ double dz = Math.abs(v.z - z);
+
+ return dx + dy + dz;
+ }
+ /** {@inheritDoc} */
+ @Override
+ public double distance(Vector3D v) {
+ return euclideanDistance(v);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distanceInf(Vector3D v) {
+ double dx = Math.abs(v.x - x);
+ double dy = Math.abs(v.y - y);
+ double dz = Math.abs(v.z - z);
+
+ return Math.max(Math.max(dx, dy), dz);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double distanceSq(Vector3D v) {
+ double dx = v.x - x;
+ double dy = v.y - y;
+ double dz = v.z - z;
+
+ return (dx * dx) + (dy * dy) + (dz * dz);
+ }
+
+ /** {@inheritDoc}
+ * <p>
+ * The implementation uses specific multiplication and addition
+ * algorithms to preserve accuracy and reduce cancellation effects.
+ * It should be very accurate even for nearly orthogonal vectors.
+ * </p>
+ * @see LinearCombination#value(double, double, double, double, double, double)
+ */
+ @Override
+ public double dotProduct(Vector3D v) {
+ return LinearCombination.value(x, v.x, y, v.y, z, v.z);
+ }
+
+ /**
+ * Get a hashCode for the vector.
+ * <p>All NaN values have the same hash code.</p>
+ *
+ * @return a hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ if (isNaN()) {
+ return 642;
+ }
+ return 643 * (164 * Double.hashCode(x) + 3 * Double.hashCode(y) + Double.hashCode(z));
+ }
+
+ /**
+ * Test for the equality of two vector instances.
+ * <p>
+ * If all coordinates of two vectors are exactly the same, and none are
+ * <code>Double.NaN</code>, the two instances are considered to be equal.
+ * </p>
+ * <p>
+ * <code>NaN</code> coordinates are considered to globally affect the vector
+ * and be equal to each other - i.e, if either (or all) coordinates of the
+ * vector are equal to <code>Double.NaN</code>, the vector is equal to
+ * {@link #NaN}.
+ * </p>
+ *
+ * @param other Object to test for equality to this
+ * @return true if two Vector3D objects are equal, false if
+ * object is null, not an instance of Vector3D, or
+ * not equal to this Vector3D instance
+ *
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other instanceof Vector3D) {
+ final Vector3D rhs = (Vector3D) other;
+ if (rhs.isNaN()) {
+ return this.isNaN();
+ }
+
+ return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "{" + x + "; " + y + "; " + z + "}";
+ }
+
+ /** Computes the dot product between to vectors. This method simply
+ * calls {@code v1.dotProduct(v2)}.
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return the dot product
+ * @see {@link #dotProduct(Vector3D)}
+ */
+ public static double dotProduct(Vector3D v1, Vector3D v2) {
+ return v1.dotProduct(v2);
+ }
+
+ /** Computes the angle in radians between two vectors. This method
+ * simply calls {@code v1.angle(v2)}.
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return the angle between the vectors in radians
+ * @see {@link #angle(Vector3D)}
+ */
+ public static double angle(Vector3D v1, Vector3D v2) {
+ return v1.angle(v2);
+ }
+
+ /** Computes the cross product between two vectors. This method simply
+ * calls {@code v1.crossProduct(v2)}.
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return the computed cross product vector
+ * @see {@link #crossProduct(Vector3D)}
+ */
+ public static Vector3D crossProduct(Vector3D v1, Vector3D v2) {
+ return v1.crossProduct(v2);
+ }
+
+ /** Returns a vector with the given coordinate values.
+ * @param x abscissa (first coordinate value)
+ * @param y abscissa (second coordinate value)
+ * @param z height (third coordinate value)
+ * @return vector instance
+ */
+ public static Vector3D of(double x, double y, double z) {
+ return new Vector3D(x, y, z);
+ }
+
+ /** Returns a vector instance with the given coordinate values.
+ * @param value vector coordinates
+ * @return vector instance
+ */
+ public static Vector3D of(Cartesian3D value) {
+ return new Vector3D(value.x, value.y, value.z);
+ }
+
+ /** Creates a vector from the coordinates in the given 3-element array.
+ * @param v coordinates array
+ * @return new vector
+ * @exception IllegalArgumentException if the array does not have 3 elements
+ */
+ public static Vector3D of(double[] v) {
+ if (v.length != 3) {
+ throw new IllegalArgumentException("Dimension mismatch: " + v.length + " != 3");
+ }
+ return new Vector3D(v[0], v[1], v[2]);
+ }
+
+ /** Builds a vector from its azimuthal coordinates
+ * @param alpha azimuth (α) around Z
+ * (0 is +X, π/2 is +Y, π is -X and 3π/2 is -Y)
+ * @param delta elevation (δ) above (XY) plane, from -π/2 to +π/2
+ * @see #getAlpha()
+ * @see #getDelta()
+ * @param alpha
+ * @param delta
+ * @return new vector instance with the given azimuthal coordinates
+ */
+ public static Vector3D fromSpherical(double alpha, double delta) {
+ double cosDelta = Math.cos(delta);
+ double x = Math.cos(alpha) * cosDelta;
+ double y = Math.sin(alpha) * cosDelta;
+ double z = Math.sin(delta);
+
+ return new Vector3D(x, y, z);
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a scale factor for first coordinate
+ * @param c first coordinate
+ * @return vector with coordinates calculated by {@code a * c}
+ */
+ public static Vector3D linearCombination(double a, Cartesian3D c) {
+ return new Vector3D(a * c.x, a * c.y, a * c.z);
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @return vector with coordinates calculated by {@code (a1 * c1) + (a2 * c2)}
+ */
+ public static Vector3D linearCombination(double a1, Cartesian3D c1, double a2, Cartesian3D c2) {
+ return new Vector3D(
+ LinearCombination.value(a1, c1.x, a2, c2.x),
+ LinearCombination.value(a1, c1.y, a2, c2.y),
+ LinearCombination.value(a1, c1.z, a2, c2.z));
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @return vector with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3)}
+ */
+ public static Vector3D linearCombination(double a1, Cartesian3D c1, double a2, Cartesian3D c2,
+ double a3, Cartesian3D c3) {
+ return new Vector3D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x),
+ LinearCombination.value(a1, c1.y, a2, c2.y, a3, c3.y),
+ LinearCombination.value(a1, c1.z, a2, c2.z, a3, c3.z));
+ }
+
+ /** Returns a vector consisting of the linear combination of the inputs.
+ * <p>
+ * A linear combination is the sum of all of the inputs multiplied by their
+ * corresponding scale factors. All inputs are interpreted as vectors. If points
+ * are to be passed, they should be viewed as representing the vector from the
+ * zero point to the given point.
+ * </p>
+ *
+ * @param a1 scale factor for first coordinate
+ * @param c1 first coordinate
+ * @param a2 scale factor for second coordinate
+ * @param c2 second coordinate
+ * @param a3 scale factor for third coordinate
+ * @param c3 third coordinate
+ * @param a4 scale factor for fourth coordinate
+ * @param c4 fourth coordinate
+ * @return point with coordinates calculated by {@code (a1 * c1) + (a2 * c2) + (a3 * c3) + (a4 * c4)}
+ */
+ public static Vector3D linearCombination(double a1, Cartesian3D c1, double a2, Cartesian3D c2,
+ double a3, Cartesian3D c3, double a4, Cartesian3D c4) {
+ return new Vector3D(
+ LinearCombination.value(a1, c1.x, a2, c2.x, a3, c3.x, a4, c4.x),
+ LinearCombination.value(a1, c1.y, a2, c2.y, a3, c3.y, a4, c4.y),
+ LinearCombination.value(a1, c1.z, a2, c2.z, a3, c3.z, a4, c4.z));
+ }
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java
index 483d341..29aedcd 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java
@@ -14,157 +14,51 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.geometry.euclidean.twod;
-import java.text.NumberFormat;
+package org.apache.commons.geometry.euclidean.twod;
-import org.apache.commons.geometry.core.Point;
-import org.apache.commons.geometry.core.Space;
-import org.apache.commons.geometry.core.Vector;
-import org.apache.commons.numbers.arrays.LinearCombination;
+import org.apache.commons.geometry.core.Spatial;
-/** This class represents a 2D point or a 2D vector.
- * <p>An instance of Cartesian2D represents the point with the corresponding
- * coordinates.</p>
- * <p>An instance of Cartesian2D also represents the vector which begins at
- * the origin and ends at the point corresponding to the coordinates.</p>
- * <p>Instances of this class are guaranteed to be immutable.</p>
+/** This class represents a set of Cartesian coordinates in
+ * two-dimensional Euclidean space.
*/
-public class Cartesian2D extends Vector2D implements Point<Euclidean2D> {
-
- /** Origin (coordinates: 0, 0). */
- public static final Cartesian2D ZERO = new Cartesian2D(0, 0);
-
- // CHECKSTYLE: stop ConstantName
- /** A vector with all coordinates set to NaN. */
- public static final Cartesian2D NaN = new Cartesian2D(Double.NaN, Double.NaN);
- // CHECKSTYLE: resume ConstantName
-
- /** A vector with all coordinates set to positive infinity. */
- public static final Cartesian2D POSITIVE_INFINITY =
- new Cartesian2D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
+public abstract class Cartesian2D implements Spatial {
- /** A vector with all coordinates set to negative infinity. */
- public static final Cartesian2D NEGATIVE_INFINITY =
- new Cartesian2D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
+ /** Serializable UID */
+ private static final long serialVersionUID = 2918583078965478552L;
- /** Serializable UID. */
- private static final long serialVersionUID = 266938651998679754L;
+ /** Abscissa (first coordinate) */
+ protected final double x;
- /** Error message when norms are zero. */
- private static final String ZERO_NORM_MSG = "Norm is zero";
+ /** Ordinate (second coordinate) */
+ protected final double y;
- /** Abscissa. */
- private final double x;
-
- /** Ordinate. */
- private final double y;
-
- /** Simple constructor.
- * Build a vector from its coordinates
- * @param x abscissa
- * @param y ordinate
- * @see #getX()
- * @see #getY()
+ /**
+ * Simple Cartesian constructor.
+ * @param x abscissa (first coordinate)
+ * @param y ordinate (second coordinate)
*/
- public Cartesian2D(double x, double y) {
+ protected Cartesian2D(double x, double y) {
this.x = x;
this.y = y;
}
- /** Simple constructor.
- * Build a vector from its coordinates
- * @param v coordinates array
- * @exception DimensionMismatchException if array does not have 2 elements
- * @see #toArray()
- */
- public Cartesian2D(double[] v) throws IllegalArgumentException {
- if (v.length != 2) {
- throw new IllegalArgumentException("Dimension mismatch: " + v.length + " != 2");
- }
- this.x = v[0];
- this.y = v[1];
- }
-
- /** Multiplicative constructor
- * Build a vector from another one and a scale factor.
- * The vector built will be a * u
- * @param a scale factor
- * @param u base (unscaled) vector
- */
- public Cartesian2D(double a, Cartesian2D u) {
- this.x = a * u.x;
- this.y = a * u.y;
- }
-
- /** Linear constructor
- * Build a vector from two other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
+ /** Returns the abscissa (first coordinate value) of the instance.
+ * @return the abscissa
*/
- public Cartesian2D(double a1, Cartesian2D u1, double a2, Cartesian2D u2) {
- this.x = a1 * u1.x + a2 * u2.x;
- this.y = a1 * u1.y + a2 * u2.y;
- }
-
- /** Linear constructor
- * Build a vector from three other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- * @param a3 third scale factor
- * @param u3 third base (unscaled) vector
- */
- public Cartesian2D(double a1, Cartesian2D u1, double a2, Cartesian2D u2,
- double a3, Cartesian2D u3) {
- this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x;
- this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y;
- }
-
- /** Linear constructor
- * Build a vector from four other ones and corresponding scale factors.
- * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
- * @param a1 first scale factor
- * @param u1 first base (unscaled) vector
- * @param a2 second scale factor
- * @param u2 second base (unscaled) vector
- * @param a3 third scale factor
- * @param u3 third base (unscaled) vector
- * @param a4 fourth scale factor
- * @param u4 fourth base (unscaled) vector
- */
- public Cartesian2D(double a1, Cartesian2D u1, double a2, Cartesian2D u2,
- double a3, Cartesian2D u3, double a4, Cartesian2D u4) {
- this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x;
- this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y + a4 * u4.y;
- }
-
- /** Get the abscissa of the vector.
- * @return abscissa of the vector
- * @see #Cartesian2D(double, double)
- */
- @Override
public double getX() {
return x;
}
- /** Get the ordinate of the vector.
- * @return ordinate of the vector
- * @see #Cartesian2D(double, double)
+ /** Returns the ordinate (second coordinate value) of the instance.
+ * @return the ordinate
*/
- @Override
public double getY() {
return y;
}
- /** Get the vector coordinates as a dimension 2 array.
- * @return vector coordinates
- * @see #Cartesian2D(double[])
+ /** Get the coordinates for this instance as a dimension 2 array.
+ * @return coordinates for this instance
*/
public double[] toArray() {
return new double[] { x, y };
@@ -172,122 +66,8 @@ public class Cartesian2D extends Vector2D implements Point<Euclidean2D> {
/** {@inheritDoc} */
@Override
- public Space getSpace() {
- return Euclidean2D.getInstance();
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D getZero() {
- return ZERO;
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNorm1() {
- return Math.abs(x) + Math.abs(y);
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNorm() {
- return Math.sqrt (x * x + y * y);
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNormSq() {
- return x * x + y * y;
- }
-
- /** {@inheritDoc} */
- @Override
- public double getNormInf() {
- return Math.max(Math.abs(x), Math.abs(y));
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D add(Vector<Euclidean2D> v) {
- Cartesian2D v2 = (Cartesian2D) v;
- return new Cartesian2D(x + v2.getX(), y + v2.getY());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D add(double factor, Vector<Euclidean2D> v) {
- Cartesian2D v2 = (Cartesian2D) v;
- return new Cartesian2D(x + factor * v2.getX(), y + factor * v2.getY());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D subtract(Vector<Euclidean2D> p) {
- Cartesian2D p3 = (Cartesian2D) p;
- return new Cartesian2D(x - p3.x, y - p3.y);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D subtract(double factor, Vector<Euclidean2D> v) {
- Cartesian2D v2 = (Cartesian2D) v;
- return new Cartesian2D(x - factor * v2.getX(), y - factor * v2.getY());
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D normalize() throws IllegalStateException {
- double s = getNorm();
- if (s == 0) {
- throw new IllegalStateException(ZERO_NORM_MSG);
- }
- return scalarMultiply(1 / s);
- }
-
- /** Compute the angular separation between two vectors.
- * <p>This method computes the angular separation between two
- * vectors using the dot product for well separated vectors and the
- * cross product for almost aligned vectors. This allows to have a
- * good accuracy in all cases, even for vectors very close to each
- * other.</p>
- * @param v1 first vector
- * @param v2 second vector
- * @return angular separation between v1 and v2
- * @exception IllegalArgumentException if either vector has a zero norm
- */
- public static double angle(Cartesian2D v1, Cartesian2D v2) throws IllegalArgumentException {
-
- double normProduct = v1.getNorm() * v2.getNorm();
- if (normProduct == 0) {
- throw new IllegalArgumentException(ZERO_NORM_MSG);
- }
-
- double dot = v1.dotProduct(v2);
- double threshold = normProduct * 0.9999;
- if ((dot < -threshold) || (dot > threshold)) {
- // the vectors are almost aligned, compute using the sine
- final double n = Math.abs(LinearCombination.value(v1.x, v2.y, -v1.y, v2.x));
- if (dot >= 0) {
- return Math.asin(n / normProduct);
- }
- return Math.PI - Math.asin(n / normProduct);
- }
-
- // the vectors are sufficiently separated to use the cosine
- return Math.acos(dot / normProduct);
-
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D negate() {
- return new Cartesian2D(-x, -y);
- }
-
- /** {@inheritDoc} */
- @Override
- public Cartesian2D scalarMultiply(double a) {
- return new Cartesian2D(a * x, a * y);
+ public int getDimension() {
+ return 2;
}
/** {@inheritDoc} */
@@ -302,190 +82,13 @@ public class Cartesian2D extends Vector2D implements Point<Euclidean2D> {
return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y));
}
- /** {@inheritDoc} */
- @Override
- public double distance1(Vector<Euclidean2D> p) {
- Cartesian2D p3 = (Cartesian2D) p;
- final double dx = Math.abs(p3.x - x);
- final double dy = Math.abs(p3.y - y);
- return dx + dy;
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance(Point<Euclidean2D> p) {
- return distance((Cartesian2D) p);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distance(Vector<Euclidean2D> v) {
- return distance((Cartesian2D) v);
- }
-
- /** Compute the distance between the instance and other coordinates.
- * @param c other coordinates
- * @return the distance between the instance and c
+ /** Returns the Euclidean distance from this value to the given value.
+ * @param other the set of coordinates to compute the distance to
+ * @return Euclidean distance
*/
- public double distance(Cartesian2D c) {
- final double dx = c.x - x;
- final double dy = c.y - y;
- return Math.sqrt(dx * dx + dy * dy);
+ protected double euclideanDistance(Cartesian2D other) {
+ double dx = x - other.x;
+ double dy = y - other.y;
+ return Math.sqrt((dx * dx) + (dy * dy));
}
-
- /** {@inheritDoc} */
- @Override
- public double distanceInf(Vector<Euclidean2D> p) {
- Cartesian2D p3 = (Cartesian2D) p;
- final double dx = Math.abs(p3.x - x);
- final double dy = Math.abs(p3.y - y);
- return Math.max(dx, dy);
- }
-
- /** {@inheritDoc} */
- @Override
- public double distanceSq(Vector<Euclidean2D> p) {
- Cartesian2D p3 = (Cartesian2D) p;
- final double dx = p3.x - x;
- final double dy = p3.y - y;
- return dx * dx + dy * dy;
- }
-
- /** {@inheritDoc} */
- @Override
- public double dotProduct(final Vector<Euclidean2D> v) {
- final Cartesian2D v2 = (Cartesian2D) v;
- return LinearCombination.value(x, v2.x, y, v2.y);
- }
-
- /**
- * Compute the cross-product of the instance and the given vector.
- * <p>
- * The cross product can be used to determine the location of a point
- * with regard to the line formed by (p1, p2) and is calculated as:
- * \[
- * P = (x_2 - x_1)(y_3 - y_1) - (y_2 - y_1)(x_3 - x_1)
- * \]
- * with \(p3 = (x_3, y_3)\) being this instance.
- * <p>
- * If the result is 0, the points are collinear, i.e. lie on a single straight line L;
- * if it is positive, this point lies to the left, otherwise to the right of the line
- * formed by (p1, p2).
- *
- * @param p1 first point of the line
- * @param p2 second point of the line
- * @return the cross-product
- *
- * @see <a href="http://en.wikipedia.org/wiki/Cross_product">Cross product (Wikipedia)</a>
- */
- public double crossProduct(final Cartesian2D p1, final Cartesian2D p2) {
- final double x1 = p2.getX() - p1.getX();
- final double y1 = getY() - p1.getY();
- final double x2 = getX() - p1.getX();
- final double y2 = p2.getY() - p1.getY();
- return LinearCombination.value(x1, y1, -x2, y2);
- }
-
- /** Compute the distance between two points according to the L<sub>2</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>p1.subtract(p2).getNorm()</code> except that no intermediate
- * vector is built</p>
- * @param p1 first point
- * @param p2 second point
- * @return the distance between p1 and p2 according to the L<sub>2</sub> norm
- */
- public static double distance(Cartesian2D p1, Cartesian2D p2) {
- return p1.distance(p2);
- }
-
- /** Compute the distance between two points according to the L<sub>∞</sub> norm.
- * <p>Calling this method is equivalent to calling:
- * <code>p1.subtract(p2).getNormInf()</code> except that no intermediate
- * vector is built</p>
- * @param p1 first point
- * @param p2 second point
- * @return the distance between p1 and p2 according to the L<sub>∞</sub> norm
- */
- public static double distanceInf(Cartesian2D p1, Cartesian2D p2) {
- return p1.distanceInf(p2);
- }
-
- /** Compute the square of the distance between two points.
- * <p>Calling this method is equivalent to calling:
- * <code>p1.subtract(p2).getNormSq()</code> except that no intermediate
- * vector is built</p>
- * @param p1 first point
- * @param p2 second point
- * @return the square of the distance between p1 and p2
- */
- public static double distanceSq(Cartesian2D p1, Cartesian2D p2) {
- return p1.distanceSq(p2);
- }
-
- /**
- * Test for the equality of two 2D instances.
- * <p>
- * If all coordinates of two 2D vectors are exactly the same, and none are
- * <code>Double.NaN</code>, the two 2D instances are considered to be equal.
- * </p>
- * <p>
- * <code>NaN</code> coordinates are considered to affect globally the vector
- * and be equals to each other - i.e, if either (or all) coordinates of the
- * 2D vector are equal to <code>Double.NaN</code>, the 2D vector is equal to
- * {@link #NaN}.
- * </p>
- *
- * @param other Object to test for equality to this
- * @return true if two 2D Cartesian objects are equal, false if
- * object is null, not an instance of Cartesian2D, or
- * not equal to this Cartesian2D instance
- *
- */
- @Override
- public boolean equals(Object other) {
-
- if (this == other) {
- return true;
- }
-
- if (other instanceof Cartesian2D) {
- final Cartesian2D rhs = (Cartesian2D)other;
- if (rhs.isNaN()) {
- return this.isNaN();
- }
-
- return (x == rhs.x) && (y == rhs.y);
- }
- return false;
- }
-
- /**
- * Get a hashCode for the 2D coordinates.
- * <p>
- * All NaN values have the same hash code.</p>
- *
- * @return a hash code value for this object
- */
- @Override
- public int hashCode() {
- if (isNaN()) {
- return 542;
- }
- return 122 * (76 * Double.hashCode(x) + Double.hashCode(y));
- }
-
- /** Get a string representation of this vector.
- * @return a string representation of this vector
- */
- @Override
- public String toString() {
- return toString(NumberFormat.getInstance());
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString(final NumberFormat format) {
- return "{" + format.format(x) + "; " + format.format(y) + "}";
- }
-
}
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Euclidean2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Euclidean2D.java
deleted file mode 100644
index 83ec10c..0000000
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Euclidean2D.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.
... 17390 lines suppressed ...
--
To stop receiving notification emails like this one, please contact
erans@apache.org.