http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java deleted file mode 100644 index 64fe1ed..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/SubPlane.java +++ /dev/null @@ -1,144 +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.math3.geometry.euclidean.threed; - -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; -import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; -import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; -import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; -import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; -import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; -import org.apache.commons.math3.geometry.partitioning.BSPTree; -import org.apache.commons.math3.geometry.partitioning.Hyperplane; -import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.geometry.partitioning.Side; -import org.apache.commons.math3.geometry.partitioning.SubHyperplane; - -/** This class represents a sub-hyperplane for {@link Plane}. - * @since 3.0 - */ -public class SubPlane extends AbstractSubHyperplane<Euclidean3D, Euclidean2D> { - - /** Simple constructor. - * @param hyperplane underlying hyperplane - * @param remainingRegion remaining region of the hyperplane - */ - public SubPlane(final Hyperplane<Euclidean3D> hyperplane, - final Region<Euclidean2D> remainingRegion) { - super(hyperplane, remainingRegion); - } - - /** {@inheritDoc} */ - @Override - protected AbstractSubHyperplane<Euclidean3D, Euclidean2D> buildNew(final Hyperplane<Euclidean3D> hyperplane, - final Region<Euclidean2D> remainingRegion) { - return new SubPlane(hyperplane, remainingRegion); - } - - /** {@inheritDoc} */ - @Override - public Side side(Hyperplane<Euclidean3D> hyperplane) { - - final Plane otherPlane = (Plane) hyperplane; - final Plane thisPlane = (Plane) getHyperplane(); - final Line inter = otherPlane.intersection(thisPlane); - final double tolerance = thisPlane.getTolerance(); - - if (inter == null) { - // the hyperplanes are parallel, - // any point can be used to check their relative position - final double global = otherPlane.getOffset(thisPlane); - return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER); - } - - // create a 2D line in the otherPlane canonical 2D frame such that: - // - the line is the crossing line of the two planes in 3D - // - the line splits the otherPlane in two half planes with an - // orientation consistent with the orientation of the instance - // (i.e. the 3D half space on the plus side (resp. minus side) - // of the instance contains the 2D half plane on the plus side - // (resp. minus side) of the 2D line - Vector2D p = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ZERO)); - Vector2D q = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ONE)); - Vector3D crossP = Vector3D.crossProduct(inter.getDirection(), thisPlane.getNormal()); - if (crossP.dotProduct(otherPlane.getNormal()) < 0) { - final Vector2D tmp = p; - p = q; - q = tmp; - } - final org.apache.commons.math3.geometry.euclidean.twod.Line line2D = - new org.apache.commons.math3.geometry.euclidean.twod.Line(p, q, tolerance); - - // check the side on the 2D plane - return getRemainingRegion().side(line2D); - - } - - /** Split the instance in two parts by an hyperplane. - * @param hyperplane splitting hyperplane - * @return an object containing both the part of the instance - * on the plus side of the instance and the part of the - * instance on the minus side of the instance - */ - @Override - public SplitSubHyperplane<Euclidean3D> split(Hyperplane<Euclidean3D> hyperplane) { - - final Plane otherPlane = (Plane) hyperplane; - final Plane thisPlane = (Plane) getHyperplane(); - final Line inter = otherPlane.intersection(thisPlane); - final double tolerance = thisPlane.getTolerance(); - - if (inter == null) { - // the hyperplanes are parallel - final double global = otherPlane.getOffset(thisPlane); - return (global < -1.0e-10) ? - new SplitSubHyperplane<Euclidean3D>(null, this) : - new SplitSubHyperplane<Euclidean3D>(this, null); - } - - // the hyperplanes do intersect - Vector2D p = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ZERO)); - Vector2D q = thisPlane.toSubSpace((Point<Euclidean3D>) inter.toSpace((Point<Euclidean1D>) Vector1D.ONE)); - Vector3D crossP = Vector3D.crossProduct(inter.getDirection(), thisPlane.getNormal()); - if (crossP.dotProduct(otherPlane.getNormal()) < 0) { - final Vector2D tmp = p; - p = q; - q = tmp; - } - final SubHyperplane<Euclidean2D> l2DMinus = - new org.apache.commons.math3.geometry.euclidean.twod.Line(p, q, tolerance).wholeHyperplane(); - final SubHyperplane<Euclidean2D> l2DPlus = - new org.apache.commons.math3.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<Euclidean2D>(l2DPlus, new BSPTree<Euclidean2D>(Boolean.FALSE), - splitTree.getPlus(), null); - - final BSPTree<Euclidean2D> minusTree = getRemainingRegion().isEmpty(splitTree.getMinus()) ? - new BSPTree<Euclidean2D>(Boolean.FALSE) : - new BSPTree<Euclidean2D>(l2DMinus, new BSPTree<Euclidean2D>(Boolean.FALSE), - splitTree.getMinus(), null); - - return new SplitSubHyperplane<Euclidean3D>(new SubPlane(thisPlane.copySelf(), new PolygonsSet(plusTree, tolerance)), - new SubPlane(thisPlane.copySelf(), new PolygonsSet(minusTree, tolerance))); - - } - -}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3D.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3D.java deleted file mode 100644 index 3eaea3a..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3D.java +++ /dev/null @@ -1,588 +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.math3.geometry.euclidean.threed; - -import java.io.Serializable; -import java.text.NumberFormat; - -import org.apache.commons.math3.exception.DimensionMismatchException; -import org.apache.commons.math3.exception.MathArithmeticException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.Space; -import org.apache.commons.math3.geometry.Vector; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathArrays; -import org.apache.commons.math3.util.MathUtils; - -/** - * This class implements vectors in a three-dimensional space. - * <p>Instance of this class are guaranteed to be immutable.</p> - * @since 1.2 - */ -public class Vector3D implements Serializable, Vector<Euclidean3D> { - - /** 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_I = new Vector3D(1, 0, 0); - - /** Opposite of the first canonical vector (coordinates: -1, 0, 0). */ - public static final Vector3D MINUS_I = new Vector3D(-1, 0, 0); - - /** Second canonical vector (coordinates: 0, 1, 0). */ - public static final Vector3D PLUS_J = new Vector3D(0, 1, 0); - - /** Opposite of the second canonical vector (coordinates: 0, -1, 0). */ - public static final Vector3D MINUS_J = new Vector3D(0, -1, 0); - - /** Third canonical vector (coordinates: 0, 0, 1). */ - public static final Vector3D PLUS_K = new Vector3D(0, 0, 1); - - /** Opposite of the third canonical vector (coordinates: 0, 0, -1). */ - public static final Vector3D MINUS_K = 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); - - /** 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 version identifier. */ - private static final long serialVersionUID = 1313493323784566947L; - - /** Abscissa. */ - private final double x; - - /** Ordinate. */ - private final double y; - - /** Height. */ - private 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() - */ - public Vector3D(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 Vector3D(double[] v) throws DimensionMismatchException { - if (v.length != 3) { - throw new DimensionMismatchException(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() - */ - public Vector3D(double alpha, double delta) { - double cosDelta = FastMath.cos(delta); - this.x = FastMath.cos(alpha) * cosDelta; - this.y = FastMath.sin(alpha) * cosDelta; - this.z = FastMath.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 Vector3D(double a, Vector3D 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 Vector3D(double a1, Vector3D u1, double a2, Vector3D u2) { - this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x); - this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y); - this.z = MathArrays.linearCombination(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 Vector3D(double a1, Vector3D u1, double a2, Vector3D u2, - double a3, Vector3D u3) { - this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x, a3, u3.x); - this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y, a3, u3.y); - this.z = MathArrays.linearCombination(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 Vector3D(double a1, Vector3D u1, double a2, Vector3D u2, - double a3, Vector3D u3, double a4, Vector3D u4) { - this.x = MathArrays.linearCombination(a1, u1.x, a2, u2.x, a3, u3.x, a4, u4.x); - this.y = MathArrays.linearCombination(a1, u1.y, a2, u2.y, a3, u3.y, a4, u4.y); - this.z = MathArrays.linearCombination(a1, u1.z, a2, u2.z, a3, u3.z, a4, u4.z); - } - - /** Get the abscissa of the vector. - * @return abscissa of the vector - * @see #Vector3D(double, double, double) - */ - public double getX() { - return x; - } - - /** Get the ordinate of the vector. - * @return ordinate of the vector - * @see #Vector3D(double, double, double) - */ - public double getY() { - return y; - } - - /** Get the height of the vector. - * @return height of the vector - * @see #Vector3D(double, double, double) - */ - public double getZ() { - return z; - } - - /** Get the vector coordinates as a dimension 3 array. - * @return vector coordinates - * @see #Vector3D(double[]) - */ - public double[] toArray() { - return new double[] { x, y, z }; - } - - /** {@inheritDoc} */ - public Space getSpace() { - return Euclidean3D.getInstance(); - } - - /** {@inheritDoc} */ - public Vector3D getZero() { - return ZERO; - } - - /** {@inheritDoc} */ - public double getNorm1() { - return FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z); - } - - /** {@inheritDoc} */ - public double getNorm() { - // there are no cancellation problems here, so we use the straightforward formula - return FastMath.sqrt (x * x + y * y + z * z); - } - - /** {@inheritDoc} */ - public double getNormSq() { - // there are no cancellation problems here, so we use the straightforward formula - return x * x + y * y + z * z; - } - - /** {@inheritDoc} */ - public double getNormInf() { - return FastMath.max(FastMath.max(FastMath.abs(x), FastMath.abs(y)), FastMath.abs(z)); - } - - /** Get the azimuth of the vector. - * @return azimuth (α) of the vector, between -π and +π - * @see #Vector3D(double, double) - */ - public double getAlpha() { - return FastMath.atan2(y, x); - } - - /** Get the elevation of the vector. - * @return elevation (δ) of the vector, between -π/2 and +π/2 - * @see #Vector3D(double, double) - */ - public double getDelta() { - return FastMath.asin(z / getNorm()); - } - - /** {@inheritDoc} */ - public Vector3D add(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return new Vector3D(x + v3.x, y + v3.y, z + v3.z); - } - - /** {@inheritDoc} */ - public Vector3D add(double factor, final Vector<Euclidean3D> v) { - return new Vector3D(1, this, factor, (Vector3D) v); - } - - /** {@inheritDoc} */ - public Vector3D subtract(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return new Vector3D(x - v3.x, y - v3.y, z - v3.z); - } - - /** {@inheritDoc} */ - public Vector3D subtract(final double factor, final Vector<Euclidean3D> v) { - return new Vector3D(1, this, -factor, (Vector3D) v); - } - - /** {@inheritDoc} */ - public Vector3D normalize() throws MathArithmeticException { - double s = getNorm(); - if (s == 0) { - throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); - } - 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></p> - * @return a new normalized vector orthogonal to the instance - * @exception MathArithmeticException if the norm of the instance is null - */ - public Vector3D orthogonal() throws MathArithmeticException { - - double threshold = 0.6 * getNorm(); - if (threshold == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - if (FastMath.abs(x) <= threshold) { - double inverse = 1 / FastMath.sqrt(y * y + z * z); - return new Vector3D(0, inverse * z, -inverse * y); - } else if (FastMath.abs(y) <= threshold) { - double inverse = 1 / FastMath.sqrt(x * x + z * z); - return new Vector3D(-inverse * z, 0, inverse * x); - } - double inverse = 1 / FastMath.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 v1 first vector - * @param v2 second vector - * @return angular separation between v1 and v2 - * @exception MathArithmeticException if either vector has a null norm - */ - public static double angle(Vector3D v1, Vector3D v2) throws MathArithmeticException { - - double normProduct = v1.getNorm() * v2.getNorm(); - if (normProduct == 0) { - throw new MathArithmeticException(LocalizedFormats.ZERO_NORM); - } - - double dot = v1.dotProduct(v2); - double threshold = normProduct * 0.9999; - if ((dot < -threshold) || (dot > threshold)) { - // the vectors are almost aligned, compute using the sine - Vector3D v3 = crossProduct(v1, v2); - if (dot >= 0) { - return FastMath.asin(v3.getNorm() / normProduct); - } - return FastMath.PI - FastMath.asin(v3.getNorm() / normProduct); - } - - // the vectors are sufficiently separated to use the cosine - return FastMath.acos(dot / normProduct); - - } - - /** {@inheritDoc} */ - public Vector3D negate() { - return new Vector3D(-x, -y, -z); - } - - /** {@inheritDoc} */ - public Vector3D scalarMultiply(double a) { - return new Vector3D(a * x, a * y, a * z); - } - - /** {@inheritDoc} */ - public boolean isNaN() { - return Double.isNaN(x) || Double.isNaN(y) || Double.isNaN(z); - } - - /** {@inheritDoc} */ - public boolean isInfinite() { - 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 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; - } - - /** - * 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 * MathUtils.hash(x) + 3 * MathUtils.hash(y) + MathUtils.hash(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 MathArrays#linearCombination(double, double, double, double, double, double) - */ - public double dotProduct(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return MathArrays.linearCombination(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 Vector3D - */ - public Vector3D crossProduct(final Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - return new Vector3D(MathArrays.linearCombination(y, v3.z, -z, v3.y), - MathArrays.linearCombination(z, v3.x, -x, v3.z), - MathArrays.linearCombination(x, v3.y, -y, v3.x)); - } - - /** {@inheritDoc} */ - public double distance1(Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - final double dx = FastMath.abs(v3.x - x); - final double dy = FastMath.abs(v3.y - y); - final double dz = FastMath.abs(v3.z - z); - return dx + dy + dz; - } - - /** {@inheritDoc} */ - public double distance(Vector<Euclidean3D> v) { - return distance((Point<Euclidean3D>) v); - } - - /** {@inheritDoc} */ - public double distance(Point<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - final double dx = v3.x - x; - final double dy = v3.y - y; - final double dz = v3.z - z; - return FastMath.sqrt(dx * dx + dy * dy + dz * dz); - } - - /** {@inheritDoc} */ - public double distanceInf(Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) v; - final double dx = FastMath.abs(v3.x - x); - final double dy = FastMath.abs(v3.y - y); - final double dz = FastMath.abs(v3.z - z); - return FastMath.max(FastMath.max(dx, dy), dz); - } - - /** {@inheritDoc} */ - public double distanceSq(Vector<Euclidean3D> v) { - final Vector3D v3 = (Vector3D) 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(Vector3D v1, Vector3D 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 - */ - public static Vector3D crossProduct(final Vector3D v1, final Vector3D 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(Vector3D v1, Vector3D 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(Vector3D v1, Vector3D 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(Vector3D v1, Vector3D 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(Vector3D v1, Vector3D v2) { - return v1.distanceSq(v2); - } - - /** Get a string representation of this vector. - * @return a string representation of this vector - */ - @Override - public String toString() { - return Vector3DFormat.getInstance().format(this); - } - - /** {@inheritDoc} */ - public String toString(final NumberFormat format) { - return new Vector3DFormat(format).format(this); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3DFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3DFormat.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3DFormat.java deleted file mode 100644 index da3f71e..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/Vector3DFormat.java +++ /dev/null @@ -1,155 +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.math3.geometry.euclidean.threed; - -import java.text.FieldPosition; -import java.text.NumberFormat; -import java.text.ParsePosition; -import java.util.Locale; - -import org.apache.commons.math3.exception.MathParseException; -import org.apache.commons.math3.geometry.Vector; -import org.apache.commons.math3.geometry.VectorFormat; -import org.apache.commons.math3.util.CompositeFormat; - -/** - * Formats a 3D vector in components list format "{x; y; z}". - * <p>The prefix and suffix "{" and "}" and the separator "; " can be replaced by - * any user-defined strings. The number format for components can be configured.</p> - * <p>White space is ignored at parse time, even if it is in the prefix, suffix - * or separator specifications. So even if the default separator does include a space - * character that is used at format time, both input string "{1;1;1}" and - * " { 1 ; 1 ; 1 } " will be parsed without error and the same vector will be - * returned. In the second case, however, the parse position after parsing will be - * just after the closing curly brace, i.e. just before the trailing space.</p> - * <p><b>Note:</b> using "," as a separator may interfere with the grouping separator - * of the default {@link NumberFormat} for the current locale. Thus it is advised - * to use a {@link NumberFormat} instance with disabled grouping in such a case.</p> - * - */ -public class Vector3DFormat extends VectorFormat<Euclidean3D> { - - /** - * Create an instance with default settings. - * <p>The instance uses the default prefix, suffix and separator: - * "{", "}", and "; " and the default number format for components.</p> - */ - public Vector3DFormat() { - super(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, - CompositeFormat.getDefaultNumberFormat()); - } - - /** - * Create an instance with a custom number format for components. - * @param format the custom format for components. - */ - public Vector3DFormat(final NumberFormat format) { - super(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, format); - } - - /** - * Create an instance with custom prefix, suffix and separator. - * @param prefix prefix to use instead of the default "{" - * @param suffix suffix to use instead of the default "}" - * @param separator separator to use instead of the default "; " - */ - public Vector3DFormat(final String prefix, final String suffix, - final String separator) { - super(prefix, suffix, separator, CompositeFormat.getDefaultNumberFormat()); - } - - /** - * Create an instance with custom prefix, suffix, separator and format - * for components. - * @param prefix prefix to use instead of the default "{" - * @param suffix suffix to use instead of the default "}" - * @param separator separator to use instead of the default "; " - * @param format the custom format for components. - */ - public Vector3DFormat(final String prefix, final String suffix, - final String separator, final NumberFormat format) { - super(prefix, suffix, separator, format); - } - - /** - * Returns the default 3D vector format for the current locale. - * @return the default 3D vector format. - */ - public static Vector3DFormat getInstance() { - return getInstance(Locale.getDefault()); - } - - /** - * Returns the default 3D vector format for the given locale. - * @param locale the specific locale used by the format. - * @return the 3D vector format specific to the given locale. - */ - public static Vector3DFormat getInstance(final Locale locale) { - return new Vector3DFormat(CompositeFormat.getDefaultNumberFormat(locale)); - } - - /** - * Formats a {@link Vector3D} object to produce a string. - * @param vector the object to format. - * @param toAppendTo where the text is to be appended - * @param pos On input: an alignment field, if desired. On output: the - * offsets of the alignment field - * @return the value passed in as toAppendTo. - */ - @Override - public StringBuffer format(final Vector<Euclidean3D> vector, final StringBuffer toAppendTo, - final FieldPosition pos) { - final Vector3D v3 = (Vector3D) vector; - return format(toAppendTo, pos, v3.getX(), v3.getY(), v3.getZ()); - } - - /** - * Parses a string to produce a {@link Vector3D} object. - * @param source the string to parse - * @return the parsed {@link Vector3D} object. - * @throws MathParseException if the beginning of the specified string - * cannot be parsed. - */ - @Override - public Vector3D parse(final String source) throws MathParseException { - ParsePosition parsePosition = new ParsePosition(0); - Vector3D result = parse(source, parsePosition); - if (parsePosition.getIndex() == 0) { - throw new MathParseException(source, - parsePosition.getErrorIndex(), - Vector3D.class); - } - return result; - } - - /** - * Parses a string to produce a {@link Vector3D} object. - * @param source the string to parse - * @param pos input/ouput parsing parameter. - * @return the parsed {@link Vector3D} object. - */ - @Override - public Vector3D parse(final String source, final ParsePosition pos) { - final double[] coordinates = parseCoordinates(3, source, pos); - if (coordinates == null) { - return null; - } - return new Vector3D(coordinates[0], coordinates[1], coordinates[2]); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/package-info.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/package-info.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/package-info.java deleted file mode 100644 index eaa3c6a..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/threed/package-info.java +++ /dev/null @@ -1,24 +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. - */ -/** - * - * <p> - * This package provides basic 3D geometry components. - * </p> - * - */ -package org.apache.commons.math3.geometry.euclidean.threed; http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/DiskGenerator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/DiskGenerator.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/DiskGenerator.java deleted file mode 100644 index 332b1b7..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/DiskGenerator.java +++ /dev/null @@ -1,108 +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.math3.geometry.euclidean.twod; - -import java.util.List; - -import org.apache.commons.math3.fraction.BigFraction; -import org.apache.commons.math3.geometry.enclosing.EnclosingBall; -import org.apache.commons.math3.geometry.enclosing.SupportBallGenerator; -import org.apache.commons.math3.util.FastMath; - -/** Class generating an enclosing ball from its support points. - * @since 3.3 - */ -public class DiskGenerator implements SupportBallGenerator<Euclidean2D, Vector2D> { - - /** {@inheritDoc} */ - public EnclosingBall<Euclidean2D, Vector2D> ballOnSupport(final List<Vector2D> support) { - - if (support.size() < 1) { - return new EnclosingBall<Euclidean2D, Vector2D>(Vector2D.ZERO, Double.NEGATIVE_INFINITY); - } else { - final Vector2D vA = support.get(0); - if (support.size() < 2) { - return new EnclosingBall<Euclidean2D, Vector2D>(vA, 0, vA); - } else { - final Vector2D vB = support.get(1); - if (support.size() < 3) { - return new EnclosingBall<Euclidean2D, Vector2D>(new Vector2D(0.5, vA, 0.5, vB), - 0.5 * vA.distance(vB), - vA, vB); - } else { - final Vector2D 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: - // (2) (x^2 + y^2) - 2 x_0 x - 2 y_0 y + (x_0^2 + y_0^2 - r^2) = 0 - // or simply: - // (3) (x^2 + y^2) + a x + b y + c = 0 - // with disk center coordinates -a/2, -b/2 - // If the disk exists, a, b and c are a non-zero solution to - // [ (x^2 + y^2 ) x y 1 ] [ 1 ] [ 0 ] - // [ (xA^2 + yA^2) xA yA 1 ] [ a ] [ 0 ] - // [ (xB^2 + yB^2) xB yB 1 ] * [ b ] = [ 0 ] - // [ (xC^2 + yC^2) xC yC 1 ] [ c ] [ 0 ] - // So the determinant of the matrix is zero. Computing this determinant - // by expanding it using the minors m_ij of first row leads to - // (4) m_11 (x^2 + y^2) - m_12 x + m_13 y - m_14 = 0 - // So by identifying equations (2) and (4) we get the coordinates - // of center as: - // x_0 = +m_12 / (2 m_11) - // y_0 = -m_13 / (2 m_11) - // Note that the minors m_11, m_12 and m_13 all have the last column - // filled with 1.0, hence simplifying the computation - final BigFraction[] c2 = new BigFraction[] { - new BigFraction(vA.getX()), new BigFraction(vB.getX()), new BigFraction(vC.getX()) - }; - final BigFraction[] c3 = new BigFraction[] { - new BigFraction(vA.getY()), new BigFraction(vB.getY()), new BigFraction(vC.getY()) - }; - final BigFraction[] c1 = new BigFraction[] { - c2[0].multiply(c2[0]).add(c3[0].multiply(c3[0])), - c2[1].multiply(c2[1]).add(c3[1].multiply(c3[1])), - c2[2].multiply(c2[2]).add(c3[2].multiply(c3[2])) - }; - final BigFraction twoM11 = minor(c2, c3).multiply(2); - final BigFraction m12 = minor(c1, c3); - final BigFraction m13 = minor(c1, c2); - final BigFraction centerX = m12.divide(twoM11); - final BigFraction centerY = m13.divide(twoM11).negate(); - 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<Euclidean2D, Vector2D>(new Vector2D(centerX.doubleValue(), - centerY.doubleValue()), - FastMath.sqrt(r2.doubleValue()), - vA, vB, vC); - } - } - } - } - - /** Compute a dimension 3 minor, when 3<sup>d</sup> column is known to be filled with 1.0. - * @param c1 first column - * @param c2 second column - * @return value of the minor computed has an exact fraction - */ - private BigFraction minor(final BigFraction[] c1, final BigFraction[] c2) { - return c2[0].multiply(c1[2].subtract(c1[1])). - add(c2[1].multiply(c1[0].subtract(c1[2]))). - add(c2[2].multiply(c1[1].subtract(c1[0]))); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Euclidean2D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Euclidean2D.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Euclidean2D.java deleted file mode 100644 index af7630d..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Euclidean2D.java +++ /dev/null @@ -1,74 +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.math3.geometry.euclidean.twod; - -import java.io.Serializable; - -import org.apache.commons.math3.geometry.Space; -import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; - -/** - * This class implements a two-dimensional space. - * @since 3.0 - */ -public class Euclidean2D implements Serializable, Space { - - /** Serializable version identifier. */ - private static final long serialVersionUID = 4793432849757649566L; - - /** Private constructor for the singleton. - */ - private Euclidean2D() { - } - - /** Get the unique instance. - * @return the unique instance - */ - public static Euclidean2D getInstance() { - return LazyHolder.INSTANCE; - } - - /** {@inheritDoc} */ - public int getDimension() { - return 2; - } - - /** {@inheritDoc} */ - public Euclidean1D getSubSpace() { - return Euclidean1D.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 Euclidean2D INSTANCE = new Euclidean2D(); - } - // CHECKSTYLE: resume HideUtilityClassConstructor - - /** Handle deserialization of the singleton. - * @return the singleton instance - */ - private Object readResolve() { - // return the singleton instance - return LazyHolder.INSTANCE; - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Line.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Line.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Line.java deleted file mode 100644 index d6fd487..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/Line.java +++ /dev/null @@ -1,540 +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.math3.geometry.euclidean.twod; - -import java.awt.geom.AffineTransform; - -import org.apache.commons.math3.exception.MathIllegalArgumentException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.Vector; -import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; -import org.apache.commons.math3.geometry.euclidean.oned.IntervalsSet; -import org.apache.commons.math3.geometry.euclidean.oned.OrientedPoint; -import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; -import org.apache.commons.math3.geometry.partitioning.Embedding; -import org.apache.commons.math3.geometry.partitioning.Hyperplane; -import org.apache.commons.math3.geometry.partitioning.SubHyperplane; -import org.apache.commons.math3.geometry.partitioning.Transform; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathArrays; -import org.apache.commons.math3.util.MathUtils; - -/** This class represents an oriented line in the 2D plane. - - * <p>An oriented line can be defined either by prolongating a line - * segment between two points past these points, or by one point and - * an angular direction (in trigonometric orientation).</p> - - * <p>Since it is oriented the two half planes at its two sides are - * unambiguously identified as a left half plane and a right half - * plane. This can be used to identify the interior and the exterior - * in a simple way by local properties only when part of a line is - * used to define part of a polygon boundary.</p> - - * <p>A line can also be used to completely define a reference frame - * in the plane. It is sufficient to select one specific point in the - * line (the orthogonal projection of the original reference frame on - * the line) and to use the unit vector in the line direction and the - * orthogonal vector oriented from left half plane to right half - * plane. We define two coordinates by the process, the - * <em>abscissa</em> along the line, and the <em>offset</em> across - * the line. All points of the plane are uniquely identified by these - * two coordinates. The line is the set of points at zero offset, the - * left half plane is the set of points with negative offsets and the - * right half plane is the set of points with positive offsets.</p> - - * @since 3.0 - */ -public class Line implements Hyperplane<Euclidean2D>, Embedding<Euclidean2D, Euclidean1D> { - - /** Default value for tolerance. */ - private static final double DEFAULT_TOLERANCE = 1.0e-10; - - /** Angle with respect to the abscissa axis. */ - private double angle; - - /** Cosine of the line angle. */ - private double cos; - - /** Sine of the line angle. */ - private double sin; - - /** Offset of the frame origin. */ - private double originOffset; - - /** Tolerance below which points are considered identical. */ - private final double tolerance; - - /** Reverse line. */ - private Line reverse; - - /** Build a line from two points. - * <p>The line is oriented from p1 to p2</p> - * @param p1 first point - * @param p2 second point - * @param tolerance tolerance below which points are considered identical - * @since 3.3 - */ - public Line(final Vector2D p1, final Vector2D p2, final double tolerance) { - reset(p1, p2); - this.tolerance = tolerance; - } - - /** Build a line from a point and an angle. - * @param p point belonging to the line - * @param angle angle of the line with respect to abscissa axis - * @param tolerance tolerance below which points are considered identical - * @since 3.3 - */ - public Line(final Vector2D p, final double angle, final double tolerance) { - reset(p, angle); - this.tolerance = tolerance; - } - - /** Build a line from its internal characteristics. - * @param angle angle of the line with respect to abscissa axis - * @param cos cosine of the angle - * @param sin sine of the angle - * @param originOffset offset of the origin - * @param tolerance tolerance below which points are considered identical - * @since 3.3 - */ - private Line(final double angle, final double cos, final double sin, - final double originOffset, final double tolerance) { - this.angle = angle; - this.cos = cos; - this.sin = sin; - this.originOffset = originOffset; - this.tolerance = tolerance; - this.reverse = null; - } - - /** Build a line from two points. - * <p>The line is oriented from p1 to p2</p> - * @param p1 first point - * @param p2 second point - * @deprecated as of 3.3, replaced with {@link #Line(Vector2D, Vector2D, double)} - */ - @Deprecated - public Line(final Vector2D p1, final Vector2D p2) { - this(p1, p2, DEFAULT_TOLERANCE); - } - - /** Build a line from a point and an angle. - * @param p point belonging to the line - * @param angle angle of the line with respect to abscissa axis - * @deprecated as of 3.3, replaced with {@link #Line(Vector2D, double, double)} - */ - @Deprecated - public Line(final Vector2D p, final double angle) { - this(p, angle, DEFAULT_TOLERANCE); - } - - /** Copy constructor. - * <p>The created instance is completely independent from the - * original instance, it is a deep copy.</p> - * @param line line to copy - */ - public Line(final Line line) { - angle = MathUtils.normalizeAngle(line.angle, FastMath.PI); - cos = line.cos; - sin = line.sin; - originOffset = line.originOffset; - tolerance = line.tolerance; - reverse = null; - } - - /** {@inheritDoc} */ - public Line copySelf() { - return new Line(this); - } - - /** Reset the instance as if built from two points. - * <p>The line is oriented from p1 to p2</p> - * @param p1 first point - * @param p2 second point - */ - public void reset(final Vector2D p1, final Vector2D p2) { - unlinkReverse(); - final double dx = p2.getX() - p1.getX(); - final double dy = p2.getY() - p1.getY(); - final double d = FastMath.hypot(dx, dy); - if (d == 0.0) { - angle = 0.0; - cos = 1.0; - sin = 0.0; - originOffset = p1.getY(); - } else { - angle = FastMath.PI + FastMath.atan2(-dy, -dx); - cos = dx / d; - sin = dy / d; - originOffset = MathArrays.linearCombination(p2.getX(), p1.getY(), -p1.getX(), p2.getY()) / d; - } - } - - /** Reset the instance as if built from a line and an angle. - * @param p point belonging to the line - * @param alpha angle of the line with respect to abscissa axis - */ - public void reset(final Vector2D p, final double alpha) { - unlinkReverse(); - this.angle = MathUtils.normalizeAngle(alpha, FastMath.PI); - cos = FastMath.cos(this.angle); - sin = FastMath.sin(this.angle); - originOffset = MathArrays.linearCombination(cos, p.getY(), -sin, p.getX()); - } - - /** Revert the instance. - */ - public void revertSelf() { - unlinkReverse(); - if (angle < FastMath.PI) { - angle += FastMath.PI; - } else { - angle -= FastMath.PI; - } - cos = -cos; - sin = -sin; - originOffset = -originOffset; - } - - /** Unset the link between an instance and its reverse. - */ - private void unlinkReverse() { - if (reverse != null) { - reverse.reverse = null; - } - reverse = null; - } - - /** Get the reverse of the instance. - * <p>Get a line with reversed orientation with respect to the - * instance.</p> - * <p> - * As long as neither the instance nor its reverse are modified - * (i.e. as long as none of the {@link #reset(Vector2D, Vector2D)}, - * {@link #reset(Vector2D, double)}, {@link #revertSelf()}, - * {@link #setAngle(double)} or {@link #setOriginOffset(double)} - * methods are called), then the line and its reverse remain linked - * together so that {@code line.getReverse().getReverse() == line}. - * When one of the line is modified, the link is deleted as both - * instance becomes independent. - * </p> - * @return a new line, with orientation opposite to the instance orientation - */ - public Line getReverse() { - if (reverse == null) { - reverse = new Line((angle < FastMath.PI) ? (angle + FastMath.PI) : (angle - FastMath.PI), - -cos, -sin, -originOffset, tolerance); - reverse.reverse = this; - } - return reverse; - } - - /** 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 Vector1D toSubSpace(Vector<Euclidean2D> vector) { - return toSubSpace((Point<Euclidean2D>) 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 Vector2D toSpace(Vector<Euclidean1D> vector) { - return toSpace((Point<Euclidean1D>) vector); - } - - /** {@inheritDoc} */ - public Vector1D toSubSpace(final Point<Euclidean2D> point) { - Vector2D p2 = (Vector2D) point; - return new Vector1D(MathArrays.linearCombination(cos, p2.getX(), sin, p2.getY())); - } - - /** {@inheritDoc} */ - public Vector2D toSpace(final Point<Euclidean1D> point) { - final double abscissa = ((Vector1D) point).getX(); - return new Vector2D(MathArrays.linearCombination(abscissa, cos, -originOffset, sin), - MathArrays.linearCombination(abscissa, sin, originOffset, cos)); - } - - /** Get the intersection point of the instance and another line. - * @param other other line - * @return intersection point of the instance and the other line - * or null if there are no intersection points - */ - public Vector2D intersection(final Line other) { - final double d = MathArrays.linearCombination(sin, other.cos, -other.sin, cos); - if (FastMath.abs(d) < tolerance) { - return null; - } - return new Vector2D(MathArrays.linearCombination(cos, other.originOffset, -other.cos, originOffset) / d, - MathArrays.linearCombination(sin, other.originOffset, -other.sin, originOffset) / d); - } - - /** {@inheritDoc} - * @since 3.3 - */ - public Point<Euclidean2D> project(Point<Euclidean2D> point) { - return toSpace(toSubSpace(point)); - } - - /** {@inheritDoc} - * @since 3.3 - */ - public double getTolerance() { - return tolerance; - } - - /** {@inheritDoc} */ - public SubLine wholeHyperplane() { - return new SubLine(this, new IntervalsSet(tolerance)); - } - - /** Build a region covering the whole space. - * @return a region containing the instance (really a {@link - * PolygonsSet PolygonsSet} instance) - */ - public PolygonsSet wholeSpace() { - return new PolygonsSet(tolerance); - } - - /** Get the offset (oriented distance) of a parallel line. - * <p>This method should be called only for parallel lines otherwise - * the result is not meaningful.</p> - * <p>The offset is 0 if both lines are the same, it is - * positive if the line is on the right side of the instance and - * negative if it is on the left side, according to its natural - * orientation.</p> - * @param line line to check - * @return offset of the line - */ - public double getOffset(final Line line) { - return originOffset + - (MathArrays.linearCombination(cos, line.cos, sin, line.sin) > 0 ? -line.originOffset : line.originOffset); - } - - /** Get the offset (oriented distance) of a vector. - * @param vector vector to check - * @return offset of the vector - */ - public double getOffset(Vector<Euclidean2D> vector) { - return getOffset((Point<Euclidean2D>) vector); - } - - /** {@inheritDoc} */ - public double getOffset(final Point<Euclidean2D> point) { - Vector2D p2 = (Vector2D) point; - return MathArrays.linearCombination(sin, p2.getX(), -cos, p2.getY(), 1.0, originOffset); - } - - /** {@inheritDoc} */ - public boolean sameOrientationAs(final Hyperplane<Euclidean2D> other) { - final Line otherL = (Line) other; - return MathArrays.linearCombination(sin, otherL.sin, cos, otherL.cos) >= 0.0; - } - - /** Get one point from the plane. - * @param abscissa desired abscissa for the point - * @param offset desired offset for the point - * @return one point in the plane, with given abscissa and offset - * relative to the line - */ - public Vector2D getPointAt(final Vector1D abscissa, final double offset) { - final double x = abscissa.getX(); - final double dOffset = offset - originOffset; - return new Vector2D(MathArrays.linearCombination(x, cos, dOffset, sin), - MathArrays.linearCombination(x, sin, -dOffset, cos)); - } - - /** Check if the line contains a point. - * @param p point to check - * @return true if p belongs to the line - */ - public boolean contains(final Vector2D p) { - return FastMath.abs(getOffset(p)) < tolerance; - } - - /** Compute the distance between the instance and a point. - * <p>This is a shortcut for invoking FastMath.abs(getOffset(p)), - * and provides consistency with what is in the - * org.apache.commons.math3.geometry.euclidean.threed.Line class.</p> - * - * @param p to check - * @return distance between the instance and the point - * @since 3.1 - */ - public double distance(final Vector2D p) { - return FastMath.abs(getOffset(p)); - } - - /** Check the instance is parallel to another line. - * @param line other line to check - * @return true if the instance is parallel to the other line - * (they can have either the same or opposite orientations) - */ - public boolean isParallelTo(final Line line) { - return FastMath.abs(MathArrays.linearCombination(sin, line.cos, -cos, line.sin)) < tolerance; - } - - /** Translate the line to force it passing by a point. - * @param p point by which the line should pass - */ - public void translateToPoint(final Vector2D p) { - originOffset = MathArrays.linearCombination(cos, p.getY(), -sin, p.getX()); - } - - /** Get the angle of the line. - * @return the angle of the line with respect to the abscissa axis - */ - public double getAngle() { - return MathUtils.normalizeAngle(angle, FastMath.PI); - } - - /** Set the angle of the line. - * @param angle new angle of the line with respect to the abscissa axis - */ - public void setAngle(final double angle) { - unlinkReverse(); - this.angle = MathUtils.normalizeAngle(angle, FastMath.PI); - cos = FastMath.cos(this.angle); - sin = FastMath.sin(this.angle); - } - - /** Get the offset of the origin. - * @return the offset of the origin - */ - public double getOriginOffset() { - return originOffset; - } - - /** Set the offset of the origin. - * @param offset offset of the origin - */ - public void setOriginOffset(final double offset) { - unlinkReverse(); - originOffset = offset; - } - - /** Get a {@link org.apache.commons.math3.geometry.partitioning.Transform - * Transform} embedding an affine transform. - * @param transform affine transform to embed (must be inversible - * otherwise the {@link - * org.apache.commons.math3.geometry.partitioning.Transform#apply(Hyperplane) - * apply(Hyperplane)} method would work only for some lines, and - * fail for other ones) - * @return a new transform that can be applied to either {@link - * Vector2D Vector2D}, {@link Line Line} or {@link - * org.apache.commons.math3.geometry.partitioning.SubHyperplane - * SubHyperplane} instances - * @exception MathIllegalArgumentException if the transform is non invertible - */ - public static Transform<Euclidean2D, Euclidean1D> getTransform(final AffineTransform transform) - throws MathIllegalArgumentException { - return new LineTransform(transform); - } - - /** Class embedding an affine transform. - * <p>This class is used in order to apply an affine transform to a - * line. Using a specific object allow to perform some computations - * on the transform only once even if the same transform is to be - * applied to a large number of lines (for example to a large - * polygon)./<p> - */ - private static class LineTransform implements Transform<Euclidean2D, Euclidean1D> { - - // CHECKSTYLE: stop JavadocVariable check - private double cXX; - private double cXY; - private double cX1; - private double cYX; - private double cYY; - private double cY1; - - private double c1Y; - private double c1X; - private double c11; - // CHECKSTYLE: resume JavadocVariable check - - /** Build an affine line transform from a n {@code AffineTransform}. - * @param transform transform to use (must be invertible otherwise - * the {@link LineTransform#apply(Hyperplane)} method would work - * only for some lines, and fail for other ones) - * @exception MathIllegalArgumentException if the transform is non invertible - */ - public LineTransform(final AffineTransform transform) throws MathIllegalArgumentException { - - final double[] m = new double[6]; - transform.getMatrix(m); - cXX = m[0]; - cXY = m[2]; - cX1 = m[4]; - cYX = m[1]; - cYY = m[3]; - cY1 = m[5]; - - c1Y = MathArrays.linearCombination(cXY, cY1, -cYY, cX1); - c1X = MathArrays.linearCombination(cXX, cY1, -cYX, cX1); - c11 = MathArrays.linearCombination(cXX, cYY, -cYX, cXY); - - if (FastMath.abs(c11) < 1.0e-20) { - throw new MathIllegalArgumentException(LocalizedFormats.NON_INVERTIBLE_TRANSFORM); - } - - } - - /** {@inheritDoc} */ - public Vector2D apply(final Point<Euclidean2D> point) { - final Vector2D p2D = (Vector2D) point; - final double x = p2D.getX(); - final double y = p2D.getY(); - return new Vector2D(MathArrays.linearCombination(cXX, x, cXY, y, cX1, 1), - MathArrays.linearCombination(cYX, x, cYY, y, cY1, 1)); - } - - /** {@inheritDoc} */ - public Line apply(final Hyperplane<Euclidean2D> hyperplane) { - final Line line = (Line) hyperplane; - final double rOffset = MathArrays.linearCombination(c1X, line.cos, c1Y, line.sin, c11, line.originOffset); - final double rCos = MathArrays.linearCombination(cXX, line.cos, cXY, line.sin); - final double rSin = MathArrays.linearCombination(cYX, line.cos, cYY, line.sin); - final double inv = 1.0 / FastMath.sqrt(rSin * rSin + rCos * rCos); - return new Line(FastMath.PI + FastMath.atan2(-rSin, -rCos), - inv * rCos, inv * rSin, - inv * rOffset, line.tolerance); - } - - /** {@inheritDoc} */ - public SubHyperplane<Euclidean1D> apply(final SubHyperplane<Euclidean1D> sub, - final Hyperplane<Euclidean2D> original, - final Hyperplane<Euclidean2D> transformed) { - final OrientedPoint op = (OrientedPoint) sub.getHyperplane(); - final Line originalLine = (Line) original; - final Line transformedLine = (Line) transformed; - final Vector1D newLoc = - transformedLine.toSubSpace(apply(originalLine.toSpace(op.getLocation()))); - return new OrientedPoint(newLoc, op.isDirect(), originalLine.tolerance).wholeHyperplane(); - } - - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/NestedLoops.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/NestedLoops.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/NestedLoops.java deleted file mode 100644 index a58caf1..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/NestedLoops.java +++ /dev/null @@ -1,200 +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.math3.geometry.euclidean.twod; - -import java.util.ArrayList; -import java.util.Iterator; - -import org.apache.commons.math3.exception.MathIllegalArgumentException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.euclidean.oned.IntervalsSet; -import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.geometry.partitioning.RegionFactory; -import org.apache.commons.math3.geometry.partitioning.SubHyperplane; - -/** This class represent a tree of nested 2D boundary loops. - - * <p>This class is used for piecewise polygons construction. - * Polygons are built using the outline edges as - * representative of boundaries, the orientation of these lines are - * meaningful. However, we want to allow the user to specify its - * outline loops without having to take care of this orientation. This - * class is devoted to correct mis-oriented loops.<p> - - * <p>Orientation is computed assuming the piecewise polygon is finite, - * i.e. the outermost loops have their exterior side facing points at - * infinity, and hence are oriented counter-clockwise. The orientation of - * internal loops is computed as the reverse of the orientation of - * their immediate surrounding loop.</p> - - * @since 3.0 - */ -class NestedLoops { - - /** Boundary loop. */ - private Vector2D[] loop; - - /** Surrounded loops. */ - private ArrayList<NestedLoops> surrounded; - - /** Polygon enclosing a finite region. */ - private Region<Euclidean2D> polygon; - - /** Indicator for original loop orientation. */ - private boolean originalIsClockwise; - - /** Tolerance below which points are considered identical. */ - private final double tolerance; - - /** Simple Constructor. - * <p>Build an empty tree of nested loops. This instance will become - * the root node of a complete tree, it is not associated with any - * loop by itself, the outermost loops are in the root tree child - * nodes.</p> - * @param tolerance tolerance below which points are considered identical - * @since 3.3 - */ - public NestedLoops(final double tolerance) { - this.surrounded = new ArrayList<NestedLoops>(); - this.tolerance = tolerance; - } - - /** Constructor. - * <p>Build a tree node with neither parent nor children</p> - * @param loop boundary loop (will be reversed in place if needed) - * @param tolerance tolerance below which points are considered identical - * @exception MathIllegalArgumentException if an outline has an open boundary loop - * @since 3.3 - */ - private NestedLoops(final Vector2D[] loop, final double tolerance) - throws MathIllegalArgumentException { - - if (loop[0] == null) { - throw new MathIllegalArgumentException(LocalizedFormats.OUTLINE_BOUNDARY_LOOP_OPEN); - } - - this.loop = loop; - this.surrounded = new ArrayList<NestedLoops>(); - this.tolerance = tolerance; - - // build the polygon defined by the loop - final ArrayList<SubHyperplane<Euclidean2D>> edges = new ArrayList<SubHyperplane<Euclidean2D>>(); - Vector2D current = loop[loop.length - 1]; - for (int i = 0; i < loop.length; ++i) { - final Vector2D previous = current; - current = loop[i]; - final Line line = new Line(previous, current, tolerance); - final IntervalsSet region = - new IntervalsSet(line.toSubSpace((Point<Euclidean2D>) previous).getX(), - line.toSubSpace((Point<Euclidean2D>) current).getX(), - tolerance); - edges.add(new SubLine(line, region)); - } - polygon = new PolygonsSet(edges, tolerance); - - // ensure the polygon encloses a finite region of the plane - if (Double.isInfinite(polygon.getSize())) { - polygon = new RegionFactory<Euclidean2D>().getComplement(polygon); - originalIsClockwise = false; - } else { - originalIsClockwise = true; - } - - } - - /** Add a loop in a tree. - * @param bLoop boundary loop (will be reversed in place if needed) - * @exception MathIllegalArgumentException if an outline has crossing - * boundary loops or open boundary loops - */ - public void add(final Vector2D[] bLoop) throws MathIllegalArgumentException { - add(new NestedLoops(bLoop, tolerance)); - } - - /** Add a loop in a tree. - * @param node boundary loop (will be reversed in place if needed) - * @exception MathIllegalArgumentException if an outline has boundary - * loops that cross each other - */ - private void add(final NestedLoops node) throws MathIllegalArgumentException { - - // check if we can go deeper in the tree - for (final NestedLoops child : surrounded) { - if (child.polygon.contains(node.polygon)) { - child.add(node); - return; - } - } - - // check if we can absorb some of the instance children - for (final Iterator<NestedLoops> iterator = surrounded.iterator(); iterator.hasNext();) { - final NestedLoops child = iterator.next(); - if (node.polygon.contains(child.polygon)) { - node.surrounded.add(child); - iterator.remove(); - } - } - - // we should be separate from the remaining children - RegionFactory<Euclidean2D> factory = new RegionFactory<Euclidean2D>(); - for (final NestedLoops child : surrounded) { - if (!factory.intersection(node.polygon, child.polygon).isEmpty()) { - throw new MathIllegalArgumentException(LocalizedFormats.CROSSING_BOUNDARY_LOOPS); - } - } - - surrounded.add(node); - - } - - /** Correct the orientation of the loops contained in the tree. - * <p>This is this method that really inverts the loops that where - * provided through the {@link #add(Vector2D[]) add} method if - * they are mis-oriented</p> - */ - public void correctOrientation() { - for (NestedLoops child : surrounded) { - child.setClockWise(true); - } - } - - /** Set the loop orientation. - * @param clockwise if true, the loop should be set to clockwise - * orientation - */ - private void setClockWise(final boolean clockwise) { - - if (originalIsClockwise ^ clockwise) { - // we need to inverse the original loop - int min = -1; - int max = loop.length; - while (++min < --max) { - final Vector2D tmp = loop[min]; - loop[min] = loop[max]; - loop[max] = tmp; - } - } - - // go deeper in the tree - for (final NestedLoops child : surrounded) { - child.setClockWise(!clockwise); - } - - } - -}