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.euclidean; 018 019import org.apache.commons.geometry.core.Point; 020import org.apache.commons.geometry.core.Vector; 021import org.apache.commons.geometry.euclidean.internal.Vectors; 022import org.apache.commons.numbers.core.Precision; 023 024/** Abstract base class for Euclidean vectors <em>and</em> points. See 025 * {@link org.apache.commons.geometry.euclidean here} for a discussion 026 * of the combination of point and vector functionality into a single 027 * class hierarchy. 028 * 029 * @param <V> Vector implementation type 030 */ 031public abstract class EuclideanVector<V extends EuclideanVector<V>> 032 implements Vector<V>, Point<V> { 033 034 /** Return the vector representing the displacement from this vector 035 * to the given vector. This is exactly equivalent to {@code v.subtract(thisVector)} 036 * but with a method name that is much easier to visualize. 037 * @param v the vector that the returned vector will be directed toward 038 * @return vector representing the displacement <em>from</em> this vector <em>to</em> the given vector 039 */ 040 public abstract V vectorTo(V v); 041 042 /** Return the unit vector representing the direction of displacement from this 043 * vector to the given vector. This is exactly equivalent to {@code v.subtract(thisVector).normalize()} 044 * but without the intermediate vector instance. 045 * @param v the vector that the returned vector will be directed toward 046 * @return unit vector representing the direction of displacement <em>from</em> this vector 047 * <em>to</em> the given vector 048 * @throws IllegalArgumentException if the norm of the vector pointing 049 * from this instance to {@code v} is zero, NaN, or infinite 050 */ 051 public abstract V directionTo(V v); 052 053 /** Get a vector constructed by linearly interpolating between this vector and the given vector. 054 * The vector coordinates are generated by the equation {@code V = (1 - t)*A + t*B}, where {@code A} 055 * is the current vector and {@code B} is the given vector. This means that if {@code t = 0}, a 056 * vector equal to the current vector will be returned. If {@code t = 1}, a vector equal to the 057 * argument will be returned. The {@code t} parameter is not constrained to the range {@code [0, 1]}, 058 * meaning that linear extrapolation can also be performed with this method. 059 * @param v other vector 060 * @param t interpolation parameter 061 * @return interpolated or extrapolated vector 062 */ 063 public abstract V lerp(V v, double t); 064 065 /** Return true if the current instance and given vector are considered equal as evaluated by the 066 * given precision context. 067 * 068 * <p>Equality is determined by comparing each pair of components in turn from the two 069 * vectors. If all components evaluate as equal, then the vectors are considered equal. If any are 070 * not equal, then the vectors are not considered equal. Note that this approach means that the 071 * calculated distance between two "equal" vectors may be as much as <code>√(n * eps<sup>2</sup>)</code>, 072 * where {@code n} is the number of components in the vector and {@code eps} is the maximum epsilon 073 * value allowed by the precision context. 074 * @param v vector to check for equality 075 * @param precision precision context used to determine floating point equality 076 * @return true if the current instance is considered equal to the given vector when using 077 * the given precision context; otherwise false 078 */ 079 public abstract boolean eq(V v, Precision.DoubleEquivalence precision); 080 081 /** Return true if the current instance is considered equal to the zero vector as evaluated by the 082 * given precision context. This is a convenience method equivalent to 083 * {@code vec.equals(vec.getZero(), precision)}. 084 * 085 * @param precision precision context used to determine floating point equality 086 * @return true if the current instance is considered equal to the zero vector when using 087 * the given precision context; otherwise false 088 * @see #eq(EuclideanVector, Precision.DoubleEquivalence) 089 */ 090 public boolean isZero(final Precision.DoubleEquivalence precision) { 091 return eq(getZero(), precision); 092 } 093 094 /** Return the vector norm value, throwing an {@link IllegalArgumentException} if the value is not real 095 * (ie, NaN or infinite) or zero. 096 * @return the vector norm value, guaranteed to be real and non-zero 097 * @throws IllegalArgumentException if the vector norm is zero, NaN, or infinite 098 */ 099 protected double getCheckedNorm() { 100 return Vectors.checkedNorm(this); 101 } 102}