You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2011/06/03 20:02:49 UTC

svn commit: r1131123 [1/2] - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/geometry/ main/java/org/apache/commons/math/geometry/euclidean/oned/ main/java/org/apache/commons/math/geometry/euclidean/threed/ main/java/org/apache/com...

Author: luc
Date: Fri Jun  3 18:02:48 2011
New Revision: 1131123

URL: http://svn.apache.org/viewvc?rev=1131123&view=rev
Log:
Added a consistent classes hierarchy for Euclidean spaces in dimension 1, 2 and 3

Added:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Vector.java
      - copied, changed from r1124588, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/Point.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1D.java
      - copied, changed from r1128876, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Point1D.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3DFormat.java
      - copied, changed from r1124619, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3DFormat.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/twod/Euclidean2D.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/twod/Vector2D.java
      - copied, changed from r1128876, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/twod/Point2D.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/twod/Vector2DFormat.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/package.html   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/Embedding.java
      - copied, changed from r1124588, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/SubSpace.java
Removed:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Point1D.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Point3D.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/twod/Point2D.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/Point.java
Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3D.java
    commons/proper/math/trunk/src/site/xdoc/changes.xml

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java?rev=1131123&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java Fri Jun  3 18:02:48 2011
@@ -0,0 +1,39 @@
+/*
+ * 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.math.geometry;
+
+import java.io.Serializable;
+
+/** This interface represents a generic space, with affine and vectorial counterparts.
+ * @version $Id:$
+ * @see Vector
+ * @since 3.0
+ */
+public interface Space extends Serializable {
+
+    /** Get the dimension of the space.
+     * @return dimension of the space
+     */
+    int getDimension();
+
+    /** Get the n-1 dimension subspace of this space.
+     * @return n-1 dimension sub-space of this space
+     * @see #getDimension()
+     */
+    Space getSubSpace();
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Space.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Vector.java (from r1124588, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/Point.java)
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Vector.java?p2=commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Vector.java&p1=commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/Point.java&r1=1124588&r2=1131123&rev=1131123&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/partitioning/Point.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/Vector.java Fri Jun  3 18:02:48 2011
@@ -14,16 +14,128 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.commons.math.geometry.partitioning;
+package org.apache.commons.math.geometry;
 
-/** This interface represents a generic point to be used in a space partition.
- * <p>Points are completely virtual entities with no specification at
- * all, so this class is essentially a marker interface with no
- * methods. This allows to perform partition in traditional euclidean
- * n-dimensions spaces, but also in more exotic universes like for
- * example the surface of the unit sphere.</p>
- * @version $Revision$ $Date$
+import java.io.Serializable;
+import java.text.NumberFormat;
+
+/** This interface represents a generic vector in a vectorial space or a point in an affine space.
+ * @version $Id:$
+ * @see Space
+ * @see Vector
+ * @since 3.0
  */
-public interface Point {
-    // nothing here, this is only a marker interface
+public interface Vector<S extends Space> extends Serializable {
+
+    /** Get the space to which the vector belongs.
+     * @return containing space
+     */
+    Space getSpace();
+
+    /** Get the null vector of the vetorial space or origin point of the affine space.
+     * @return null vector of the vetorial space or origin point of the affine space
+     */
+    Vector<S> getZero();
+
+    /** Get the L<sub>1</sub> norm for the vector.
+     * @return L<sub>1</sub> norm for the vector
+     */
+    double getNorm1();
+
+    /** Get the L<sub>2</sub> norm for the vector.
+     * @return Euclidean norm for the vector
+     */
+    double getNorm();
+
+    /** Get the square of the norm for the vector.
+     * @return square of the Euclidean norm for the vector
+     */
+    double getNormSq();
+
+    /** Get the L<sub>&infin;</sub> norm for the vector.
+     * @return L<sub>&infin;</sub> norm for the vector
+     */
+    double getNormInf();
+
+    /** Add a vector to the instance.
+     * @param v vector to add
+     * @return a new vector
+     */
+    Vector<S> add(Vector<S> 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);
+
+    /** Subtract a vector from the instance.
+     * @param v vector to subtract
+     * @return a new vector
+     */
+    Vector<S> subtract(Vector<S> 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);
+
+    /**
+     * Returns true if any coordinate of this vector is NaN; false otherwise
+     * @return  true if any coordinate of this vector 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();
+
+    /** 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>
+     * @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);
+
+    /** Compute the distance between the instance and another vector according to the L<sub>2</sub> norm.
+     * <p>Calling this method is equivalent to calling:
+     * <code>q.subtract(p).getNorm()</code> except that no intermediate
+     * vector is built</p>
+     * @param v second vector
+     * @return the distance between the instance and p according to the L<sub>2</sub> norm
+     */
+    double distance(Vector<S> v);
+
+    /** Compute the distance between the instance and another vector according to the L<sub>&infin;</sub> norm.
+     * <p>Calling this method is equivalent to calling:
+     * <code>q.subtract(p).getNormInf()</code> except that no intermediate
+     * vector is built</p>
+     * @param v second vector
+     * @return the distance between the instance and p according to the L<sub>&infin;</sub> norm
+     */
+    double distanceInf(Vector<S> 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>
+     * @param v second vector
+     * @return the square of the distance between the instance and p
+     */
+    double distanceSq(Vector<S> v);
+
+    /** Get a string representation of this vector.
+     * @param format the custom format for components.
+     */
+    public String toString(final NumberFormat format);
+
 }

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java?rev=1131123&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java Fri Jun  3 18:02:48 2011
@@ -0,0 +1,289 @@
+/*
+ * 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.math.geometry;
+
+import java.text.FieldPosition;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+import org.apache.commons.math.util.CompositeFormat;
+import org.apache.commons.math.exception.MathParseException;
+
+/**
+ * Formats a vector in components list format "{x; y; ...}".
+ * <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>
+ *
+ * @version $Id:$
+ * @since 3.0
+ */
+public abstract class VectorFormat<S extends Space> {
+
+    /** The default prefix: "{". */
+    public static final String DEFAULT_PREFIX = "{";
+
+    /** The default suffix: "}". */
+    public static final String DEFAULT_SUFFIX = "}";
+
+    /** The default separator: ", ". */
+    public static final String DEFAULT_SEPARATOR = "; ";
+
+    /** Prefix. */
+    private final String prefix;
+
+    /** Suffix. */
+    private final String suffix;
+
+    /** Separator. */
+    private final String separator;
+
+    /** Trimmed prefix. */
+    private final String trimmedPrefix;
+
+    /** Trimmed suffix. */
+    private final String trimmedSuffix;
+
+    /** Trimmed separator. */
+    private final String trimmedSeparator;
+
+    /** The format used for components. */
+    private final NumberFormat format;
+
+    /**
+     * 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>
+     */
+    protected VectorFormat() {
+        this(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.
+     */
+    protected VectorFormat(final NumberFormat format) {
+        this(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 "; "
+     */
+    protected VectorFormat(final String prefix, final String suffix,
+                          final String separator) {
+        this(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.
+     */
+    protected VectorFormat(final String prefix, final String suffix,
+                          final String separator, final NumberFormat format) {
+        this.prefix      = prefix;
+        this.suffix      = suffix;
+        this.separator   = separator;
+        trimmedPrefix    = prefix.trim();
+        trimmedSuffix    = suffix.trim();
+        trimmedSeparator = separator.trim();
+        this.format      = format;
+    }
+
+    /**
+     * Get the set of locales for which point/vector formats are available.
+     * <p>This is the same set as the {@link NumberFormat} set.</p>
+     * @return available point/vector format locales.
+     */
+    public static Locale[] getAvailableLocales() {
+        return NumberFormat.getAvailableLocales();
+    }
+
+    /**
+     * Get the format prefix.
+     * @return format prefix.
+     */
+    public String getPrefix() {
+        return prefix;
+    }
+
+    /**
+     * Get the format suffix.
+     * @return format suffix.
+     */
+    public String getSuffix() {
+        return suffix;
+    }
+
+    /**
+     * Get the format separator between components.
+     * @return format separator.
+     */
+    public String getSeparator() {
+        return separator;
+    }
+
+    /**
+     * Get the components format.
+     * @return components format.
+     */
+    public NumberFormat getFormat() {
+        return format;
+    }
+
+    /**
+     * Formats a {@link Vector} object to produce a string.
+     * @param vector the object to format.
+     * @return a formatted string.
+     */
+    public String format(Vector<S> vector) {
+        return format(vector, new StringBuffer(), new FieldPosition(0)).toString();
+    }
+
+    /**
+     * Formats a {@link Vector} 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.
+     */
+    public abstract StringBuffer format(Vector<S> vector,
+                                        StringBuffer toAppendTo, FieldPosition pos);
+
+    /**
+     * Formats the coordinates of a {@link Vector} to produce a string.
+     * @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
+     * @param coordinates coordinates of the object to format.
+     * @return the value passed in as toAppendTo.
+     */
+    protected StringBuffer format(StringBuffer toAppendTo, FieldPosition pos,
+                                  double ... coordinates) {
+
+        pos.setBeginIndex(0);
+        pos.setEndIndex(0);
+
+        // format prefix
+        toAppendTo.append(prefix);
+
+        // format components
+        for (int i = 0; i < coordinates.length; ++i) {
+            if (i > 0) {
+                toAppendTo.append(separator);
+            }
+            CompositeFormat.formatDouble(coordinates[i], format, toAppendTo, pos);
+        }
+
+        // format suffix
+        toAppendTo.append(suffix);
+
+        return toAppendTo;
+
+    }
+
+    /**
+     * Parses a string to produce a {@link Vector} object.
+     * @param source the string to parse
+     * @return the parsed {@link Vector} object.
+     * @throws MathParseException if the beginning of the specified string
+     * cannot be parsed.
+     */
+    public abstract Vector<S> parse(String source);
+
+    /**
+     * Parses a string to produce a {@link Vector} object.
+     * @param source the string to parse
+     * @param pos input/ouput parsing parameter.
+     * @return the parsed {@link Vector} object.
+     */
+    public abstract Vector<S> parse(String source, ParsePosition pos);
+
+    /**
+     * Parses a string to produce an array of coordinates.
+     * @param dimension dimension of the space
+     * @param source the string to parse
+     * @param pos input/ouput parsing parameter.
+     * @return coordinates array.
+     */
+    protected double[] parseCoordinates(int dimension, String source, ParsePosition pos) {
+
+        int initialIndex = pos.getIndex();
+        double[] coordinates = new double[dimension];
+
+        // parse prefix
+        CompositeFormat.parseAndIgnoreWhitespace(source, pos);
+        if (!CompositeFormat.parseFixedstring(source, trimmedPrefix, pos)) {
+            return null;
+        }
+
+        for (int i = 0; i < dimension; ++i) {
+
+            // skip whitespace
+            CompositeFormat.parseAndIgnoreWhitespace(source, pos);
+
+            // parse separator
+            if (i > 0) {
+                if (!CompositeFormat.parseFixedstring(source, trimmedSeparator, pos)) {
+                    return null;
+                }
+            }
+
+            // skip whitespace
+            CompositeFormat.parseAndIgnoreWhitespace(source, pos);
+
+            // parse coordinate
+            Number c = CompositeFormat.parseNumber(source, format, pos);
+            if (c == null) {
+                // invalid coordinate
+                // set index back to initial, error index should already be set
+                pos.setIndex(initialIndex);
+                return null;
+            }
+
+            // store coordinate
+            coordinates[i] = c.doubleValue();
+
+        }
+
+        // parse suffix
+        CompositeFormat.parseAndIgnoreWhitespace(source, pos);
+        if (!CompositeFormat.parseFixedstring(source, trimmedSuffix, pos)) {
+            return null;
+        }
+
+        return coordinates;
+
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/VectorFormat.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java?rev=1131123&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java Fri Jun  3 18:02:48 2011
@@ -0,0 +1,83 @@
+/*
+ * 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.math.geometry.euclidean.oned;
+
+import java.io.Serializable;
+
+import org.apache.commons.math.exception.MathUnsupportedOperationException;
+import org.apache.commons.math.exception.util.LocalizedFormats;
+import org.apache.commons.math.geometry.Space;
+
+/**
+ * This class implements a one-dimensional space.
+ * @version $Id:$
+ * @since 3.0
+ */
+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} */
+    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 MathUnsupportedOperationException}
+     * </p>
+     * @return nothing
+     * @throws MathUnsupportedOperationException in all cases
+     */
+    public Space getSubSpace() throws MathUnsupportedOperationException {
+        throw new MathUnsupportedOperationException(LocalizedFormats.NOT_SUPPORTED_IN_DIMENSION_N, 1);
+    }
+
+    // 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;
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Euclidean1D.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1D.java (from r1128876, commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Point1D.java)
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1D.java?p2=commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1D.java&p1=commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Point1D.java&r1=1128876&r2=1131123&rev=1131123&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Point1D.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1D.java Fri Jun  3 18:02:48 2011
@@ -16,38 +16,307 @@
  */
 package org.apache.commons.math.geometry.euclidean.oned;
 
-import org.apache.commons.math.geometry.partitioning.Point;
+import java.text.NumberFormat;
 
-/** This class represents a 1D point.
+import org.apache.commons.math.geometry.Vector;
+import org.apache.commons.math.geometry.Space;
+import org.apache.commons.math.util.FastMath;
+import org.apache.commons.math.util.MathUtils;
+
+/** This class represents a 1D vector.
  * <p>Instances of this class are guaranteed to be immutable.</p>
- * @version $Revision$ $Date$
+ * @version $Id:$
+ * @since 3.0
  */
-public class Point1D implements Point {
+public class Vector1D implements Vector<Euclidean1D> {
+
+    /** Origin (coordinates: 0). */
+    public static final Vector1D ZERO = new Vector1D(0.0);
+
+    /** Unit (coordinates: 1). */
+    public static final Vector1D ONE  = new Vector1D(1.0);
 
-    /** Point at 0.0 abscissa. */
-    public static final Point1D ZERO = new Point1D(0.0);
+    // CHECKSTYLE: stop ConstantName
+    /** A vector with all coordinates set to NaN. */
+    public static final Vector1D NaN = new Vector1D(Double.NaN);
+    // CHECKSTYLE: resume ConstantName
 
-    /** Point at 1.0 abscissa. */
-    public static final Point1D ONE = new Point1D(1.0);
+    /** A vector with all coordinates set to positive infinity. */
+    public static final Vector1D POSITIVE_INFINITY =
+        new Vector1D(Double.POSITIVE_INFINITY);
 
-    /** Point at undefined (NaN) abscissa. */
-    public static final Point1D UNDEFINED = new Point1D(Double.NaN);
+    /** A vector with all coordinates set to negative infinity. */
+    public static final Vector1D NEGATIVE_INFINITY =
+        new Vector1D(Double.NEGATIVE_INFINITY);
 
-    /** Abscissa of the point. */
-    private double x;
+    /** Serializable UID. */
+    private static final long serialVersionUID = 7556674948671647925L;
+
+    /** Abscissa. */
+    private final double x;
 
     /** Simple constructor.
-     * @param x abscissa of the point
+     * Build a vector from its coordinates
+     * @param x abscissa
+     * @see #getX()
      */
-    public Point1D(final double x) {
+    public Vector1D(double x) {
         this.x = x;
     }
 
-    /** Get the abscissa of the point.
-     * @return abscissa of the point
+    /** 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 Vector1D(double a, Vector1D 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 Vector1D(double a1, Vector1D u1, double a2, Vector1D 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 double getAbscissa() {
+    public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2,
+                   double a3, Vector1D 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 Vector1D(double a1, Vector1D u1, double a2, Vector1D u2,
+                   double a3, Vector1D u3, double a4, Vector1D 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 #Vector1D(double)
+     */
+    public double getX() {
         return x;
     }
 
+    /** {@inheritDoc} */
+    public Space getSpace() {
+        return Euclidean1D.getInstance();
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D getZero() {
+        return ZERO;
+    }
+
+    /** {@inheritDoc} */
+    public double getNorm1() {
+        return FastMath.abs(x);
+    }
+
+    /** {@inheritDoc} */
+    public double getNorm() {
+        return FastMath.abs(x);
+    }
+
+    /** {@inheritDoc} */
+    public double getNormSq() {
+        return x * x;
+    }
+
+    /** {@inheritDoc} */
+    public double getNormInf() {
+        return FastMath.abs(x);
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D add(Vector<Euclidean1D> v) {
+        Vector1D v1 = (Vector1D) v;
+        return new Vector1D(x + v1.getX());
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D add(double factor, Vector<Euclidean1D> v) {
+        Vector1D v1 = (Vector1D) v;
+        return new Vector1D(x + factor * v1.getX());
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D subtract(Vector<Euclidean1D> p) {
+        Vector1D p3 = (Vector1D) p;
+        return new Vector1D(x - p3.x);
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D subtract(double factor, Vector<Euclidean1D> v) {
+        Vector1D v1 = (Vector1D) v;
+        return new Vector1D(x - factor * v1.getX());
+    }
+
+    /** {@inheritDoc} */
+    public boolean isNaN() {
+        return Double.isNaN(x);
+    }
+
+    /** {@inheritDoc} */
+    public boolean isInfinite() {
+        return !isNaN() && Double.isInfinite(x);
+    }
+
+    /** {@inheritDoc} */
+    public double distance1(Vector<Euclidean1D> p) {
+        Vector1D p3 = (Vector1D) p;
+        final double dx = FastMath.abs(p3.x - x);
+        return dx;
+    }
+
+    /** {@inheritDoc} */
+    public double distance(Vector<Euclidean1D> p) {
+        Vector1D p3 = (Vector1D) p;
+        final double dx = p3.x - x;
+        return FastMath.abs(dx);
+    }
+
+    /** {@inheritDoc} */
+    public double distanceInf(Vector<Euclidean1D> p) {
+        Vector1D p3 = (Vector1D) p;
+        final double dx = FastMath.abs(p3.x - x);
+        return dx;
+    }
+
+    /** {@inheritDoc} */
+    public double distanceSq(Vector<Euclidean1D> p) {
+        Vector1D p3 = (Vector1D) p;
+        final double dx = p3.x - x;
+        return dx * dx;
+    }
+
+    /** Compute the distance between two vectors 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(Vector1D p1, Vector1D p2) {
+        return p1.distance(p2);
+    }
+
+    /** Compute the distance between two vectors according to the L<sub>&infin;</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>&infin;</sub> norm
+     */
+    public static double distanceInf(Vector1D p1, Vector1D p2) {
+        return p1.distanceInf(p2);
+    }
+
+    /** Compute the square of the distance between two vectors.
+     * <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(Vector1D p1, Vector1D 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 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;
+    }
+
+    /**
+     * 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 * MathUtils.hash(x);
+    }
+
+    /** Get a string representation of this vector.
+     * @return a string representation of this vector
+     */
+    @Override
+    public String toString() {
+        return Vector1DFormat.getInstance().format(this);
+    }
+
+    /** {@inheritDoc} */
+    public String toString(final NumberFormat format) {
+        return new Vector1DFormat(format).format(this);
+    }
+
 }

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java?rev=1131123&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java Fri Jun  3 18:02:48 2011
@@ -0,0 +1,130 @@
+/*
+ * 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.math.geometry.euclidean.oned;
+
+import java.text.FieldPosition;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+import org.apache.commons.math.exception.MathParseException;
+import org.apache.commons.math.geometry.Vector;
+import org.apache.commons.math.geometry.VectorFormat;
+import org.apache.commons.math.util.CompositeFormat;
+
+/**
+ * Formats a 1D vector in components list format "{x}".
+ * <p>The prefix and suffix "{" and "}" 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}" and
+ * " { 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>
+ *
+ * @version $Id:$
+ * @since 3.0
+ */
+public class Vector1DFormat extends VectorFormat<Euclidean1D> {
+
+    /**
+     * 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 Vector1DFormat() {
+        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 Vector1DFormat(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 "}"
+     */
+    public Vector1DFormat(final String prefix, final String suffix) {
+        super(prefix, suffix, DEFAULT_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 format the custom format for components.
+     */
+    public Vector1DFormat(final String prefix, final String suffix,
+                         final NumberFormat format) {
+        super(prefix, suffix, DEFAULT_SEPARATOR, format);
+    }
+
+    /**
+     * Returns the default 1D vector format for the current locale.
+     * @return the default 1D vector format.
+     */
+    public static Vector1DFormat getInstance() {
+        return getInstance(Locale.getDefault());
+    }
+
+    /**
+     * Returns the default 1D vector format for the given locale.
+     * @param locale the specific locale used by the format.
+     * @return the 1D vector format specific to the given locale.
+     */
+    public static Vector1DFormat getInstance(final Locale locale) {
+        return new Vector1DFormat(CompositeFormat.getDefaultNumberFormat(locale));
+    }
+
+    /** {@inheritDoc} */
+    public StringBuffer format(final Vector<Euclidean1D> vector, final StringBuffer toAppendTo,
+                               final FieldPosition pos) {
+        final Vector1D p1 = (Vector1D) vector;
+        return format(toAppendTo, pos, p1.getX());
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D parse(final String source) {
+        ParsePosition parsePosition = new ParsePosition(0);
+        Vector1D result = parse(source, parsePosition);
+        if (parsePosition.getIndex() == 0) {
+            throw new MathParseException(source,
+                                         parsePosition.getErrorIndex(),
+                                         Vector1D.class);
+        }
+        return result;
+    }
+
+    /** {@inheritDoc} */
+    public Vector1D parse(final String source, final ParsePosition pos) {
+        final double[] coordinates = parseCoordinates(1, source, pos);
+        if (coordinates == null) {
+            return null;
+        }
+        return new Vector1D(coordinates[0]);
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/oned/Vector1DFormat.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java?rev=1131123&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java Fri Jun  3 18:02:48 2011
@@ -0,0 +1,75 @@
+/*
+ * 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.math.geometry.euclidean.threed;
+
+import java.io.Serializable;
+
+import org.apache.commons.math.geometry.Space;
+import org.apache.commons.math.geometry.euclidean.twod.Euclidean2D;
+
+/**
+ * This class implements a three-dimensional space.
+ * @version $Id:$
+ * @since 3.0
+ */
+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} */
+    public int getDimension() {
+        return 3;
+    }
+
+    /** {@inheritDoc} */
+    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;
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Euclidean3D.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3D.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3D.java?rev=1131123&r1=1131122&r2=1131123&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3D.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/geometry/euclidean/threed/Vector3D.java Fri Jun  3 18:02:48 2011
@@ -18,545 +18,564 @@
 package org.apache.commons.math.geometry.euclidean.threed;
 
 import java.io.Serializable;
+import java.text.NumberFormat;
 
 import org.apache.commons.math.exception.MathArithmeticException;
 import org.apache.commons.math.exception.util.LocalizedFormats;
-import org.apache.commons.math.util.MathUtils;
+import org.apache.commons.math.geometry.Vector;
+import org.apache.commons.math.geometry.Space;
 import org.apache.commons.math.util.FastMath;
+import org.apache.commons.math.util.MathUtils;
 
 /**
  * This class implements vectors in a three-dimensional space.
  * <p>Instance of this class are guaranteed to be immutable.</p>
- * @version $Revision$ $Date$
+ * @version $Id$
  * @since 1.2
  */
-public class Vector3D implements Serializable {
-  /** 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);
-
-  /** Default format. */
-  private static final Vector3DFormat DEFAULT_FORMAT =
-      Vector3DFormat.getInstance();
-
-  /** Serializable version identifier. */
-  private static final long serialVersionUID = 5133268763396045979L;
-
-  /** 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 azimuthal coordinates
-   * @param alpha azimuth (&alpha;) around Z
-   *              (0 is +X, &pi;/2 is +Y, &pi; is -X and 3&pi;/2 is -Y)
-   * @param delta elevation (&delta;) above (XY) plane, from -&pi;/2 to +&pi;/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 = a1 * u1.x + a2 * u2.x;
-    this.y = a1 * u1.y + a2 * u2.y;
-    this.z = 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 = a1 * u1.x + a2 * u2.x + a3 * u3.x;
-    this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y;
-    this.z = 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 = 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;
-    this.z = 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 L<sub>1</sub> norm for the vector.
-   * @return L<sub>1</sub> norm for the vector
-   */
-  public double getNorm1() {
-    return FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z);
-  }
-
-  /** Get the L<sub>2</sub> norm for the vector.
-   * @return euclidean norm for the vector
-   */
-  public double getNorm() {
-    return FastMath.sqrt (x * x + y * y + z * z);
-  }
-
-  /** Get the square of the norm for the vector.
-   * @return square of the euclidean norm for the vector
-   */
-  public double getNormSq() {
-    return x * x + y * y + z * z;
-  }
-
-  /** Get the L<sub>&infin;</sub> norm for the vector.
-   * @return L<sub>&infin;</sub> norm for the vector
-   */
-  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 (&alpha;) of the vector, between -&pi; and +&pi;
-   * @see #Vector3D(double, double)
-   */
-  public double getAlpha() {
-    return FastMath.atan2(y, x);
-  }
-
-  /** Get the elevation of the vector.
-   * @return elevation (&delta;) of the vector, between -&pi;/2 and +&pi;/2
-   * @see #Vector3D(double, double)
-   */
-  public double getDelta() {
-    return FastMath.asin(z / getNorm());
-  }
-
-  /** Add a vector to the instance.
-   * @param v vector to add
-   * @return a new vector
-   */
-  public Vector3D add(Vector3D v) {
-    return new Vector3D(x + v.x, y + v.y, z + v.z);
-  }
-
-  /** 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
-   */
-  public Vector3D add(double factor, Vector3D v) {
-    return new Vector3D(x + factor * v.x, y + factor * v.y, z + factor * v.z);
-  }
-
-  /** Subtract a vector from the instance.
-   * @param v vector to subtract
-   * @return a new vector
-   */
-  public Vector3D subtract(Vector3D v) {
-    return new Vector3D(x - v.x, y - v.y, z - v.z);
-  }
-
-  /** 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
-   */
-  public Vector3D subtract(double factor, Vector3D v) {
-    return new Vector3D(x - factor * v.x, y - factor * v.y, z - factor * v.z);
-  }
-
-  /** Get a normalized vector aligned with the instance.
-   * @return a new normalized vector
-   * @exception ArithmeticException if the norm is zero
-   */
-  public Vector3D normalize() {
-    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 ArithmeticException if the norm of the instance is null
-   */
-  public Vector3D orthogonal() {
-
-    double threshold = 0.6 * getNorm();
-    if (threshold == 0) {
-      throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
-    }
-
-    if ((x >= -threshold) && (x <= threshold)) {
-      double inverse  = 1 / FastMath.sqrt(y * y + z * z);
-      return new Vector3D(0, inverse * z, -inverse * y);
-    } else if ((y >= -threshold) && (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 ArithmeticException if either vector has a null norm
-   */
-  public static double angle(Vector3D v1, Vector3D v2) {
-
-    double normProduct = v1.getNorm() * v2.getNorm();
-    if (normProduct == 0) {
-      throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
-    }
-
-    double dot = dotProduct(v1, 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);
-
-  }
-
-  /** Get the opposite of the instance.
-   * @return a new vector which is opposite to the instance
-   */
-  public Vector3D negate() {
-    return new Vector3D(-x, -y, -z);
-  }
-
-  /** Multiply the instance by a scalar
-   * @param a scalar
-   * @return a new vector
-   */
-  public Vector3D scalarMultiply(double a) {
-    return new Vector3D(a * x, a * y, a * z);
-  }
-
-  /**
-   * Returns true if any coordinate of this vector is NaN; false otherwise
-   * @return  true if any coordinate of this vector is NaN; false otherwise
-   */
-  public boolean isNaN() {
-      return Double.isNaN(x) || Double.isNaN(y) || Double.isNaN(z);
-  }
-
-  /**
-   * 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
-   */
-  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 8;
-      }
-      return 31 * (23 * MathUtils.hash(x) +  19 * MathUtils.hash(y) +  MathUtils.hash(z));
-  }
-
-  /** 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.x * v2.x + v1.y * v2.y + v1.z * v2.z;
-  }
-
-  /** 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) {
-
-      final double n1 = v1.getNormSq();
-      final double n2 = v2.getNormSq();
-      if ((n1 * n2) < MathUtils.SAFE_MIN) {
-          return ZERO;
-      }
-
-      // rescale both vectors without losing precision,
-      // to ensure their norm are the same order of magnitude
-      final int deltaExp = (FastMath.getExponent(n1) - FastMath.getExponent(n2)) / 4;
-      final double x1    = FastMath.scalb(v1.x, -deltaExp);
-      final double y1    = FastMath.scalb(v1.y, -deltaExp);
-      final double z1    = FastMath.scalb(v1.z, -deltaExp);
-      final double x2    = FastMath.scalb(v2.x,  deltaExp);
-      final double y2    = FastMath.scalb(v2.y,  deltaExp);
-      final double z2    = FastMath.scalb(v2.z,  deltaExp);
-
-      // we reduce cancellation errors by preconditioning,
-      // we replace v1 by v3 = v1 - rho v2 with rho chosen in order to compute
-      // v3 without loss of precision. See Kahan lecture
-      // "Computing Cross-Products and Rotations in 2- and 3-Dimensional Euclidean Spaces"
-      // available at http://www.cs.berkeley.edu/~wkahan/MathH110/Cross.pdf
-
-      // compute rho as an 8 bits approximation of v1.v2 / v2.v2
-      final double ratio = (x1 * x2 + y1 * y2 + z1 * z2) / FastMath.scalb(n2, 2 * deltaExp);
-      final double rho   = FastMath.rint(256 * ratio) / 256;
-
-      final double x3 = x1 - rho * x2;
-      final double y3 = y1 - rho * y2;
-      final double z3 = z1 - rho * z2;
-
-      // compute cross product from v3 and v2 instead of v1 and v2
-      return new Vector3D(y3 * z2 - z3 * y2, z3 * x2 - x3 * z2, x3 * y2 - y3 * x2);
-
-  }
-
-  /** 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) {
-    final double dx = FastMath.abs(v2.x - v1.x);
-    final double dy = FastMath.abs(v2.y - v1.y);
-    final double dz = FastMath.abs(v2.z - v1.z);
-    return dx + dy + dz;
-  }
-
-  /** 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) {
-    final double dx = v2.x - v1.x;
-    final double dy = v2.y - v1.y;
-    final double dz = v2.z - v1.z;
-    return FastMath.sqrt(dx * dx + dy * dy + dz * dz);
-  }
-
-  /** Compute the distance between two vectors according to the L<sub>&infin;</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>&infin;</sub> norm
-   */
-  public static double distanceInf(Vector3D v1, Vector3D v2) {
-    final double dx = FastMath.abs(v2.x - v1.x);
-    final double dy = FastMath.abs(v2.y - v1.y);
-    final double dz = FastMath.abs(v2.z - v1.z);
-    return FastMath.max(FastMath.max(dx, dy), dz);
-  }
-
-  /** 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) {
-    final double dx = v2.x - v1.x;
-    final double dy = v2.y - v1.y;
-    final double dz = v2.z - v1.z;
-    return dx * dx + dy * dy + dz * dz;
-  }
-
-  /** Get a string representation of this vector.
-   * @return a string representation of this vector
-   */
-  @Override
-  public String toString() {
-      return DEFAULT_FORMAT.format(this);
-  }
+public class Vector3D implements Serializable, Vector<Euclidean3D> {
+
+    /** Serializable version id. */
+    private static final long serialVersionUID = 1313493323784566947L;
+
+    /** 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. */
+ 
+    /** 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 azimuthal coordinates
+     * @param alpha azimuth (&alpha;) around Z
+     *              (0 is +X, &pi;/2 is +Y, &pi; is -X and 3&pi;/2 is -Y)
+     * @param delta elevation (&delta;) above (XY) plane, from -&pi;/2 to +&pi;/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 = a1 * u1.x + a2 * u2.x;
+        this.y = a1 * u1.y + a2 * u2.y;
+        this.z = 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 = a1 * u1.x + a2 * u2.x + a3 * u3.x;
+        this.y = a1 * u1.y + a2 * u2.y + a3 * u3.y;
+        this.z = 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 = 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;
+        this.z = 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;
+    }
+
+    /** {@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() {
+        return FastMath.sqrt (x * x + y * y + z * z);
+    }
+
+    /** {@inheritDoc} */
+    public double getNormSq() {
+        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 (&alpha;) of the vector, between -&pi; and +&pi;
+     * @see #Vector3D(double, double)
+     */
+    public double getAlpha() {
+        return FastMath.atan2(y, x);
+    }
+
+    /** Get the elevation of the vector.
+     * @return elevation (&delta;) of the vector, between -&pi;/2 and +&pi;/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) {
+        final Vector3D v3 = (Vector3D) v;
+        return new Vector3D(x + factor * v3.x, y + factor * v3.y, z + factor * v3.z);
+    }
+
+    /** {@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) {
+        final Vector3D v3 = (Vector3D) v;
+        return new Vector3D(x - factor * v3.x, y - factor * v3.y, z - factor * v3.z);
+    }
+
+    /** {@inheritDoc} */
+    public Vector3D normalize() {
+        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() {
+
+        double threshold = 0.6 * getNorm();
+        if (threshold == 0) {
+            throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
+        }
+
+        if ((x >= -threshold) && (x <= threshold)) {
+            double inverse  = 1 / FastMath.sqrt(y * y + z * z);
+            return new Vector3D(0, inverse * z, -inverse * y);
+        } else if ((y >= -threshold) && (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) {
+
+        double normProduct = v1.getNorm() * v2.getNorm();
+        if (normProduct == 0) {
+            throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
+        }
+
+        double dot = dotProduct(v1, 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} */
+    public double dotProduct(final Vector<Euclidean3D> v) {
+        final Vector3D v3 = (Vector3D) v;
+        return x * v3.x + y * v3.y + z * v3.z;
+    }
+
+    /** {@inheritDoc} */
+    public Vector3D crossProduct(final Vector<Euclidean3D> v) {
+        final Vector3D v3 = (Vector3D) v;
+
+        final double n1 = getNormSq();
+        final double n2 = v.getNormSq();
+        if ((n1 * n2) < MathUtils.SAFE_MIN) {
+            return ZERO;
+        }
+
+        // rescale both vectors without losing precision,
+        // to ensure their norm are the same order of magnitude
+        final int deltaExp = (FastMath.getExponent(n1) - FastMath.getExponent(n2)) / 4;
+        final double x1    = FastMath.scalb(x,   -deltaExp);
+        final double y1    = FastMath.scalb(y,   -deltaExp);
+        final double z1    = FastMath.scalb(z,   -deltaExp);
+        final double x2    = FastMath.scalb(v3.x, deltaExp);
+        final double y2    = FastMath.scalb(v3.y, deltaExp);
+        final double z2    = FastMath.scalb(v3.z, deltaExp);
+
+        // we reduce cancellation errors by preconditioning,
+        // we replace v1 by v3 = v1 - rho v2 with rho chosen in order to compute
+        // v3 without loss of precision. See Kahan lecture
+        // "Computing Cross-Products and Rotations in 2- and 3-Dimensional Euclidean Spaces"
+        // available at http://www.cs.berkeley.edu/~wkahan/MathH110/Cross.pdf
+
+        // compute rho as an 8 bits approximation of v1.v2 / v2.v2
+        final double ratio = (x1 * x2 + y1 * y2 + z1 * z2) / FastMath.scalb(n2, 2 * deltaExp);
+        final double rho   = FastMath.rint(256 * ratio) / 256;
+
+        final double x3 = x1 - rho * x2;
+        final double y3 = y1 - rho * y2;
+        final double z3 = z1 - rho * z2;
+
+        // compute cross product from v3 and v2 instead of v1 and v2
+        return new Vector3D(y3 * z2 - z3 * y2, z3 * x2 - x3 * z2, x3 * y2 - y3 * x2);
+
+    }
+
+    /** {@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) {
+        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>&infin;</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>&infin;</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);
+    }
 
 }