001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.geometry.core;
018
019/** Interface representing a vector in a vector space or displacement vectors
020 * in an affine space.
021 *
022 * <p>This interface uses self-referencing generic parameters to ensure
023 * that implementations are only used with instances of their own type.
024 * This removes the need for casting inside of methods in order to access
025 * implementation-specific data, such as coordinate values.
026 * </p>
027 *
028 * @see <a href="https://en.wikipedia.org/wiki/Vector_space">Vector space</a>
029 * @see <a href="https://en.wikipedia.org/wiki/Affine_space">Affine space</a>
030 *
031 * @param <V> Vector implementation type
032 */
033public interface Vector<V extends Vector<V>> extends Spatial {
034
035    /** Get the zero (null) vector of the space.
036     * @return zero vector of the space
037     */
038    V getZero();
039
040    /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector.
041     * This corresponds to the common notion of vector magnitude or length and
042     * is defined as the square root of the sum of the squares of all vector components.
043     * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
044     * @return L<sub>2</sub> norm for the vector
045     */
046    double norm();
047
048    /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
049     * for the vector. This is equal to the sum of the squares of all vector components.
050     * @see #norm()
051     * @return square of the L<sub>2</sub> norm for the vector
052     */
053    double normSq();
054
055    /** Returns a vector with the same direction but with the given
056     * norm. This is equivalent to calling {@code vec.normalize().scalarMultiply(mag)}
057     * but without the intermediate vector.
058     * @param norm The vector norm
059     * @return a vector with the same direction as the current instance but the given norm
060     */
061    V withNorm(double norm);
062
063    /** Add a vector to the instance.
064     * @param v vector to add
065     * @return a new vector
066     */
067    V add(V v);
068
069    /** Add a scaled vector to the instance.
070     * @param factor scale factor to apply to v before adding it
071     * @param v vector to add
072     * @return a new vector
073     */
074    V add(double factor, V v);
075
076    /** Subtract a vector from the instance.
077     * @param v vector to subtract
078     * @return a new vector
079     */
080    V subtract(V v);
081
082    /** Subtract a scaled vector from the instance.
083     * @param factor scale factor to apply to v before subtracting it
084     * @param v vector to subtract
085     * @return a new vector
086     */
087    V subtract(double factor, V v);
088
089    /** Get the negation of the instance.
090     * @return a new vector which is the negation of the instance
091     */
092    V negate();
093
094    /** Get a normalized vector aligned with the instance. The returned
095     * vector has a magnitude of 1.
096     * @return normalized vector
097     * @throws IllegalArgumentException if the norm is zero, NaN, or infinite
098     * @see #normalizeOrNull()
099     */
100    V normalize();
101
102    /** Attempt to compute a normalized vector aligned with the instance, returning null if
103     * such a vector cannot be computed. This method is equivalent to {@link #normalize()}
104     * but returns null instead of throwing an exception on failure.
105     * @return normalized vector or null if such a vector cannot be computed, i.e. if the
106     *      norm is zero, NaN, or infinite
107     * @see #normalize()
108     */
109    V normalizeOrNull();
110
111    /** Multiply the instance by a scalar.
112     * @param a scalar
113     * @return a new vector
114     */
115    V multiply(double a);
116
117    /** Compute the distance between the instance and another vector.
118     * @param v second vector
119     * @return the distance between the instance and v
120     */
121    double distance(V v);
122
123    /** Compute the square of the distance between the instance and another vector.
124     * <p>Calling this method is equivalent to calling:
125     * <code>q.subtract(p).getNormSq()</code> except that no intermediate
126     * vector is built</p>
127     * @see #normSq()
128     * @param v second vector
129     * @return the square of the distance between the instance and p
130     */
131    double distanceSq(V v);
132
133    /** Compute the dot-product of the instance and another vector.
134     * @param v second vector
135     * @return the dot product (this &middot; v)
136     */
137    double dot(V v);
138
139    /** Compute the angular separation between two vectors in radians.
140     * @param v other vector
141     * @return angular separation between this instance and v in radians
142     * @throws IllegalArgumentException if either vector has a zero, NaN, or infinite norm
143     */
144    double angle(V v);
145}