View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.geometry.euclidean;
18  
19  import org.apache.commons.geometry.core.Point;
20  import org.apache.commons.geometry.core.Vector;
21  import org.apache.commons.geometry.euclidean.internal.Vectors;
22  import org.apache.commons.numbers.core.Precision;
23  
24  /** Abstract base class for Euclidean vectors <em>and</em> points. See
25   * {@link org.apache.commons.geometry.euclidean here} for a discussion
26   * of the combination of point and vector functionality into a single
27   * class hierarchy.
28   *
29   * @param <V> Vector implementation type
30   */
31  public abstract class EuclideanVector<V extends EuclideanVector<V>>
32      implements Vector<V>, Point<V> {
33  
34      /** Return the vector representing the displacement from this vector
35       * to the given vector. This is exactly equivalent to {@code v.subtract(thisVector)}
36       * but with a method name that is much easier to visualize.
37       * @param v the vector that the returned vector will be directed toward
38       * @return vector representing the displacement <em>from</em> this vector <em>to</em> the given vector
39       */
40      public abstract V vectorTo(V v);
41  
42      /** Return the unit vector representing the direction of displacement from this
43       * vector to the given vector. This is exactly equivalent to {@code v.subtract(thisVector).normalize()}
44       * but without the intermediate vector instance.
45       * @param v the vector that the returned vector will be directed toward
46       * @return unit vector representing the direction of displacement <em>from</em> this vector
47       *      <em>to</em> the given vector
48       * @throws IllegalArgumentException if the norm of the vector pointing
49       *      from this instance to {@code v} is zero, NaN, or infinite
50       */
51      public abstract V directionTo(V v);
52  
53      /** Get a vector constructed by linearly interpolating between this vector and the given vector.
54       * The vector coordinates are generated by the equation {@code V = (1 - t)*A + t*B}, where {@code A}
55       * is the current vector and {@code B} is the given vector. This means that if {@code t = 0}, a
56       * vector equal to the current vector will be returned. If {@code t = 1}, a vector equal to the
57       * argument will be returned. The {@code t} parameter is not constrained to the range {@code [0, 1]},
58       * meaning that linear extrapolation can also be performed with this method.
59       * @param v other vector
60       * @param t interpolation parameter
61       * @return interpolated or extrapolated vector
62       */
63      public abstract V lerp(V v, double t);
64  
65      /** Return true if the current instance and given vector are considered equal as evaluated by the
66       * given precision context.
67       *
68       * <p>Equality is determined by comparing each pair of components in turn from the two
69       * vectors. If all components evaluate as equal, then the vectors are considered equal. If any are
70       * not equal, then the vectors are not considered equal. Note that this approach means that the
71       * calculated distance between two "equal" vectors may be as much as <code>&radic;(n * eps<sup>2</sup>)</code>,
72       * where {@code n} is the number of components in the vector and {@code eps} is the maximum epsilon
73       * value allowed by the precision context.
74       * @param v vector to check for equality
75       * @param precision precision context used to determine floating point equality
76       * @return true if the current instance is considered equal to the given vector when using
77       *      the given precision context; otherwise false
78       */
79      public abstract boolean eq(V v, Precision.DoubleEquivalence precision);
80  
81      /** Return true if the current instance is considered equal to the zero vector as evaluated by the
82       * given precision context. This is a convenience method equivalent to
83       * {@code vec.equals(vec.getZero(), precision)}.
84       *
85       * @param precision precision context used to determine floating point equality
86       * @return true if the current instance is considered equal to the zero vector when using
87       *      the given precision context; otherwise false
88       * @see #eq(EuclideanVector, Precision.DoubleEquivalence)
89       */
90      public boolean isZero(final Precision.DoubleEquivalence precision) {
91          return eq(getZero(), precision);
92      }
93  
94      /** Return the vector norm value, throwing an {@link IllegalArgumentException} if the value is not real
95       * (ie, NaN or infinite) or zero.
96       * @return the vector norm value, guaranteed to be real and non-zero
97       * @throws IllegalArgumentException if the vector norm is zero, NaN, or infinite
98       */
99      protected double getCheckedNorm() {
100         return Vectors.checkedNorm(this);
101     }
102 }