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>√(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 }