
com.io7m.jtensors.VectorM2F Maven / Gradle / Ivy
/*
* Copyright © 2013 http://io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package com.io7m.jtensors;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import com.io7m.jaux.AlmostEqualDouble.ContextRelative;
import com.io7m.jaux.AlmostEqualFloat;
import com.io7m.jaux.functional.Pair;
/**
*
* A two-dimensional mutable vector type with single precision elements.
*
*
*
* Values of this type cannot be accessed safely from multiple threads without
* explicit synchronization.
*
*/
@NotThreadSafe public class VectorM2F implements VectorReadable2F
{
/**
* Calculate the absolute values of the elements in vector v
,
* saving the result to out
.
*
* @param v
* The input vector
* @param out
* The output vector
*
* @return (abs v.x, abs v.y)
*/
public final static @Nonnull VectorM2F absolute(
final @Nonnull VectorReadable2F v,
final @Nonnull VectorM2F out)
{
final float x = Math.abs(v.getXF());
final float y = Math.abs(v.getYF());
out.x = x;
out.y = y;
return out;
}
/**
* Calculate the absolute values of the elements in vector v
,
* modifying the vector in-place.
*
* @param v
* The input vector
*
* @return (abs v.x, abs v.y)
*/
public final static @Nonnull VectorM2F absoluteInPlace(
final @Nonnull VectorM2F v)
{
return VectorM2F.absolute(v, v);
}
/**
* Calculate the element-wise sum of the vectors v0
and
* v1
, saving the result to out
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
* @param out
* The output vector
*
* @return (v0.x + v1.x, v0.y + v1.y)
*/
public final static @Nonnull VectorM2F add(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1,
final @Nonnull VectorM2F out)
{
final float x = v0.getXF() + v1.getXF();
final float y = v0.getYF() + v1.getYF();
out.x = x;
out.y = y;
return out;
}
/**
* Calculate the element-wise sum of the vectors v0
and
* v1
, saving the result to v0
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return (v0.x + v1.x, v0.y + v1.y)
*/
public final static @Nonnull VectorM2F addInPlace(
final @Nonnull VectorM2F v0,
final @Nonnull VectorReadable2F v1)
{
return VectorM2F.add(v0, v1, v0);
}
/**
* Calculate the element-wise sum of the vectors v0
and the
* element-wise product of v1
and r
, saving the
* result to out
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
* @param out
* The output vector
* @param r
* The scaling value
*
* @return (v0.x + (v1.x * r), v0.y + (v1.y * r))
*/
public final static @Nonnull VectorM2F addScaled(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1,
final double r,
final @Nonnull VectorM2F out)
{
final double x = v0.getXF() + (v1.getXF() * r);
final double y = v0.getYF() + (v1.getYF() * r);
out.x = (float) x;
out.y = (float) y;
return out;
}
/**
* Calculate the element-wise sum of the vectors v0
and the
* element-wise product of v1
and r
, saving the
* result to v0
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
* @param r
* The scaling value
*
* @return (v0.x + (v1.x * r), v0.y + (v1.y * r))
*/
public final static @Nonnull VectorM2F addScaledInPlace(
final @Nonnull VectorM2F v0,
final @Nonnull VectorReadable2F v1,
final double r)
{
return VectorM2F.addScaled(v0, v1, r, v0);
}
/**
* Determine whether or not the vectors qa
and qb
* are equal to within the degree of error given in context
.
*
* @see AlmostEqualFloat#almostEqual(ContextRelative, float, float)
*
* @param context
* The equality context
* @param qa
* The left input vector
* @param qb
* The right input vector
* @since 5.0.0
*/
public final static boolean almostEqual(
final @Nonnull AlmostEqualFloat.ContextRelative context,
final @Nonnull VectorReadable2F qa,
final @Nonnull VectorReadable2F qb)
{
final boolean xs =
AlmostEqualFloat.almostEqual(context, qa.getXF(), qb.getXF());
final boolean ys =
AlmostEqualFloat.almostEqual(context, qa.getYF(), qb.getYF());
return xs && ys;
}
/**
* Calculate the angle between vectors v0
and v1
,
* in radians.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return The angle between the two vectors, in radians.
*/
public final static double angle(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1)
{
final double m0 = VectorM2F.magnitude(v0);
final double m1 = VectorM2F.magnitude(v1);
final double dp =
Math.min(Math.max(-1.0, VectorM2F.dotProduct(v0, v1)), 1.0);
final double f = m0 * m1;
final double r = dp / f;
return Math.acos(r);
}
/**
* Clamp the elements of the vector v
to the range
* [minimum .. maximum]
inclusive, saving the result to
* out
.
*
* @param v
* The input vector
* @param minimum
* The minimum allowed value
* @param maximum
* The maximum allowed value
* @param out
* The output vector
*
* @return A vector with both elements equal to at most maximum
* and at least minimum
*/
public final static @Nonnull VectorM2F clamp(
final @Nonnull VectorReadable2F v,
final float minimum,
final float maximum,
final @Nonnull VectorM2F out)
{
final float x = Math.min(Math.max(v.getXF(), minimum), maximum);
final float y = Math.min(Math.max(v.getYF(), minimum), maximum);
out.x = x;
out.y = y;
return out;
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in minimum
and
* maximum
, saving the result to out
.
*
* @param v
* The input vector
* @param minimum
* The vector containing the minimum acceptable values
* @param maximum
* The vector containing the maximum acceptable values
* @param out
* The output vector
*
* @return (min(max(v.x, minimum.x), maximum.x), min(max(v.y, minimum.y), maximum.y))
*/
public final static @Nonnull VectorM2F clampByVector(
final @Nonnull VectorReadable2F v,
final @Nonnull VectorReadable2F minimum,
final @Nonnull VectorReadable2F maximum,
final @Nonnull VectorM2F out)
{
final float x =
Math.min(Math.max(v.getXF(), minimum.getXF()), maximum.getXF());
final float y =
Math.min(Math.max(v.getYF(), minimum.getYF()), maximum.getYF());
out.x = x;
out.y = y;
return out;
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in minimum
and
* maximum
, saving the result to v
.
*
* @param v
* The input vector
* @param minimum
* The vector containing the minimum acceptable values
* @param maximum
* The vector containing the maximum acceptable values
*
* @return (min(max(v.x, minimum.x), maximum.x), min(max(v.y, minimum.y), maximum.y))
*/
public final static @Nonnull VectorM2F clampByVectorInPlace(
final @Nonnull VectorM2F v,
final @Nonnull VectorReadable2F minimum,
final @Nonnull VectorReadable2F maximum)
{
return VectorM2F.clampByVector(v, minimum, maximum, v);
}
/**
* Clamp the elements of the vector v
to the range
* [minimum .. maximum]
inclusive, saving the result to
* v
.
*
* @param v
* The input vector
* @param minimum
* The minimum allowed value
* @param maximum
* The maximum allowed value
*
* @return A vector with both elements equal to at most maximum
* and at least minimum
, in v
*/
public final static @Nonnull VectorM2F clampInPlace(
final @Nonnull VectorM2F v,
final float minimum,
final float maximum)
{
return VectorM2F.clamp(v, minimum, maximum, v);
}
/**
* Clamp the elements of the vector v
to the range
* [-Infinity .. maximum]
inclusive, saving the result to
* out
.
*
* @param v
* The input vector
* @param out
* The output vector
* @param maximum
* The maximum allowed value
*
* @return A vector with both elements equal to at most maximum
*/
public final static @Nonnull VectorM2F clampMaximum(
final @Nonnull VectorReadable2F v,
final float maximum,
final @Nonnull VectorM2F out)
{
final float x = Math.min(v.getXF(), maximum);
final float y = Math.min(v.getYF(), maximum);
out.x = x;
out.y = y;
return out;
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in maximum
, saving the
* result to out
.
*
* @param v
* The input vector
* @param maximum
* The vector containing the maximum acceptable values
* @param out
* The output vector
*
* @return (min(v.x, maximum.x), min(v.y, maximum.y))
*/
public final static @Nonnull VectorM2F clampMaximumByVector(
final @Nonnull VectorReadable2F v,
final @Nonnull VectorReadable2F maximum,
final @Nonnull VectorM2F out)
{
final float x = Math.min(v.getXF(), maximum.getXF());
final float y = Math.min(v.getYF(), maximum.getYF());
out.x = x;
out.y = y;
return out;
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in maximum
, saving the
* result to v
.
*
* @param v
* The input vector
* @param maximum
* The vector containing the maximum acceptable values
*
* @return (min(v.x, maximum.x), min(v.y, maximum.y))
*/
public final static @Nonnull VectorM2F clampMaximumByVectorInPlace(
final @Nonnull VectorM2F v,
final @Nonnull VectorReadable2F maximum)
{
return VectorM2F.clampMaximumByVector(v, maximum, v);
}
/**
* Clamp the elements of the vector v
to the range
* [-Infinity .. maximum]
inclusive, saving the result to
* v
.
*
* @param v
* The input vector
* @param maximum
* The maximum allowed value
*
* @return A vector with both elements equal to at most maximum
* , in v
*/
public final static @Nonnull VectorM2F clampMaximumInPlace(
final @Nonnull VectorM2F v,
final float maximum)
{
return VectorM2F.clampMaximum(v, maximum, v);
}
/**
* Clamp the elements of the vector v
to the range
* [minimum .. Infinity]
inclusive, saving the result to
* out
.
*
* @param v
* The input vector
* @param out
* The output vector
* @param minimum
* The minimum allowed value
*
* @return A vector with both elements equal to at least
* minimum
*/
public final static @Nonnull VectorM2F clampMinimum(
final @Nonnull VectorReadable2F v,
final float minimum,
final @Nonnull VectorM2F out)
{
final float x = Math.max(v.getXF(), minimum);
final float y = Math.max(v.getYF(), minimum);
out.x = x;
out.y = y;
return out;
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in minimum
, saving the
* result to out
.
*
* @param v
* The input vector
* @param out
* The output vector
* @param minimum
* The vector containing the minimum acceptable values
*
* @return (max(v.x, minimum.x), max(v.y, minimum.y))
*/
public final static @Nonnull VectorM2F clampMinimumByVector(
final @Nonnull VectorReadable2F v,
final @Nonnull VectorReadable2F minimum,
final @Nonnull VectorM2F out)
{
final float x = Math.max(v.getXF(), minimum.getXF());
final float y = Math.max(v.getYF(), minimum.getYF());
out.x = x;
out.y = y;
return out;
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in minimum
, saving the
* result to v
.
*
* @param v
* The input vector
* @param minimum
* The vector containing the minimum acceptable values
*
* @return (max(v.x, minimum.x), max(v.y, minimum.y))
, in
* v
*/
public final static @Nonnull VectorM2F clampMinimumByVectorInPlace(
final @Nonnull VectorM2F v,
final @Nonnull VectorReadable2F minimum)
{
return VectorM2F.clampMinimumByVector(v, minimum, v);
}
/**
* Clamp the elements of the vector v
to the range
* [minimum .. Infinity]
inclusive, saving the result to
* v
.
*
* @param v
* The input vector
* @param minimum
* The minimum allowed value
*
* @return A vector with both elements equal to at least
* minimum
, in v
.
*/
public final static @Nonnull VectorM2F clampMinimumInPlace(
final @Nonnull VectorM2F v,
final float minimum)
{
return VectorM2F.clampMinimum(v, minimum, v);
}
/**
* Copy all elements of the vector input
to the vector
* output
.
*
* @param input
* The input vector
* @param output
* The output vector
*
* @return output
*/
public final static @Nonnull VectorM2F copy(
final @Nonnull VectorReadable2F input,
final @Nonnull VectorM2F output)
{
output.x = input.getXF();
output.y = input.getYF();
return output;
}
/**
* Calculate the distance between the two vectors v0
and
* v1
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return The distance between the two vectors.
*/
public final static double distance(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1)
{
final @Nonnull VectorM2F vr = new VectorM2F();
return VectorM2F.magnitude(VectorM2F.subtract(v0, v1, vr));
}
/**
* Calculate the scalar product of the vectors v0
and
* v1
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return The scalar product of the two vectors
*/
public final static float dotProduct(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1)
{
final float x = v0.getXF() * v1.getXF();
final float y = v0.getYF() * v1.getYF();
return x + y;
}
/**
* Linearly interpolate between v0
and v1
by the
* amount alpha
, saving the result to r
.
*
* The alpha
parameter controls the degree of interpolation,
* such that:
*
*
* interpolateLinear(v0, v1, 0.0, r) -> r = v0
* interpolateLinear(v0, v1, 1.0, r) -> r = v1
*
*
* @param v0
* The left input vector.
* @param v1
* The right input vector.
* @param alpha
* The interpolation value, between 0.0
and
* 1.0
.
* @param r
* The result vector.
*
* @return r
*/
public final static @Nonnull VectorM2F interpolateLinear(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1,
final double alpha,
final @Nonnull VectorM2F r)
{
final @Nonnull VectorM2F w0 = new VectorM2F();
final @Nonnull VectorM2F w1 = new VectorM2F();
VectorM2F.scale(v0, 1.0f - alpha, w0);
VectorM2F.scale(v1, alpha, w1);
return VectorM2F.add(w0, w1, r);
}
/**
* Calculate the magnitude of the vector v
.
*
* Correspondingly, magnitude(normalize(v)) == 1.0
.
*
* @param v
* The input vector
*
* @return The magnitude of the input vector
*/
public final static double magnitude(
final @Nonnull VectorReadable2F v)
{
return Math.sqrt(VectorM2F.magnitudeSquared(v));
}
/**
* Calculate the squared magnitude of the vector v
.
*
* @param v
* The input vector
*
* @return The squared magnitude of the input vector
*/
public final static double magnitudeSquared(
final @Nonnull VectorReadable2F v)
{
return VectorM2F.dotProduct(v, v);
}
/**
* Returns a vector with the same orientation as v
but with
* magnitude equal to 1.0
in out
. The function
* returns the zero vector iff the input is the zero vector.
*
* @param v
* The input vector
* @param out
* The output vector
*
* @return out
*/
public final static @Nonnull VectorM2F normalize(
final @Nonnull VectorReadable2F v,
final @Nonnull VectorM2F out)
{
final double m = VectorM2F.magnitudeSquared(v);
if (m > 0.0) {
final double reciprocal = 1.0 / Math.sqrt(m);
return VectorM2F.scale(v, reciprocal, out);
}
out.x = v.getXF();
out.y = v.getYF();
return out;
}
/**
* Returns a vector with the same orientation as v
but with
* magnitude equal to 1.0
in v
. The function
* returns the zero vector iff the input is the zero vector.
*
* @param v
* The input vector
*
* @return v
*/
public final static @Nonnull VectorM2F normalizeInPlace(
final @Nonnull VectorM2F v)
{
return VectorM2F.normalize(v, v);
}
/**
*
* Orthonormalize and return the vectors v0
and v1
* .
*
*
* See GSP
*
*
* @return A pair (v0, v1)
, orthonormalized.
*
* @since 5.0.0
*/
public final static @Nonnull Pair orthoNormalize(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1)
{
final VectorM2F v0n = new VectorM2F();
final VectorM2F vr = new VectorM2F();
final VectorM2F vp = new VectorM2F();
VectorM2F.normalize(v0, v0n);
VectorM2F.scale(v0n, VectorM2F.dotProduct(v1, v0n), vp);
VectorM2F.normalizeInPlace(VectorM2F.subtract(v1, vp, vr));
return new Pair(v0n, vr);
}
/**
*
* Orthonormalize and the vectors v0
and v1
.
*
*
* See GSP
*
*
* @since 5.0.0
*/
public final static void orthoNormalizeInPlace(
final @Nonnull VectorM2F v0,
final @Nonnull VectorM2F v1)
{
final VectorM2F projection = new VectorM2F();
VectorM2F.normalizeInPlace(v0);
VectorM2F.scale(v0, VectorM2F.dotProduct(v1, v0), projection);
VectorM2F.subtractInPlace(v1, projection);
VectorM2F.normalizeInPlace(v1);
}
/**
* Calculate the projection of the vector p
onto the vector
* q
, saving the result in r
.
*
* @return ((dotProduct p q) / magnitudeSquared q) * q
*/
public final static @Nonnull VectorM2F projection(
final @Nonnull VectorReadable2F p,
final @Nonnull VectorReadable2F q,
final @Nonnull VectorM2F r)
{
final double dot = VectorM2F.dotProduct(p, q);
final double qms = VectorM2F.magnitudeSquared(q);
final double s = dot / qms;
return VectorM2F.scale(p, s, r);
}
/**
* Scale the vector v
by the scalar r
, saving the
* result to out
.
*
* @param v
* The input vector
* @param r
* The scaling value
* @param out
* The output vector
*
* @return (v.x * r, v.y * r)
*/
public final static @Nonnull VectorM2F scale(
final @Nonnull VectorReadable2F v,
final double r,
final @Nonnull VectorM2F out)
{
final double x = v.getXF() * r;
final double y = v.getYF() * r;
out.x = (float) x;
out.y = (float) y;
return out;
}
/**
* Scale the vector v
by the scalar r
, saving the
* result to v
.
*
* @param v
* The input vector
* @param r
* The scaling value
*
* @return (v.x * r, v.y * r)
*/
public final static @Nonnull VectorM2F scaleInPlace(
final @Nonnull VectorM2F v,
final double r)
{
return VectorM2F.scale(v, r, v);
}
/**
* Subtract the vector v1
from the vector v0
,
* saving the result to out
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
* @param out
* The output vector
*
* @return (v0.x - v1.x, v0.y - v1.y)
*/
public final static @Nonnull VectorM2F subtract(
final @Nonnull VectorReadable2F v0,
final @Nonnull VectorReadable2F v1,
final @Nonnull VectorM2F out)
{
final float x = v0.getXF() - v1.getXF();
final float y = v0.getYF() - v1.getYF();
out.x = x;
out.y = y;
return out;
}
/**
* Subtract the vector v1
from the vector v0
,
* saving the result to v0
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return (v0.x - v1.x, v0.y - v1.y)
*/
public final static @Nonnull VectorM2F subtractInPlace(
final @Nonnull VectorM2F v0,
final @Nonnull VectorReadable2F v1)
{
return VectorM2F.subtract(v0, v1, v0);
}
public float x = 0.0f;
public float y = 0.0f;
/**
* Default constructor, initializing the vector with values
* [0.0, 0.0]
.
*/
public VectorM2F()
{
}
/**
* Construct a vector initialized with the given values.
*/
public VectorM2F(
final float x,
final float y)
{
this.x = x;
this.y = y;
}
/**
* Construct a vector initialized with the values given in the vector
* v
.
*/
public VectorM2F(
final @Nonnull VectorReadable2F v)
{
this.x = v.getXF();
this.y = v.getYF();
}
@Override public final boolean equals(
final Object obj)
{
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final @Nonnull VectorM2F other = (VectorM2F) obj;
if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) {
return false;
}
if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) {
return false;
}
return true;
}
@Override public final float getXF()
{
return this.x;
}
@Override public final float getYF()
{
return this.y;
}
@Override public final int hashCode()
{
final int prime = 31;
int result = 1;
result = (prime * result) + Float.floatToIntBits(this.x);
result = (prime * result) + Float.floatToIntBits(this.y);
return result;
}
@Override public final String toString()
{
final StringBuilder builder = new StringBuilder();
builder.append("[VectorM2F ");
builder.append(this.x);
builder.append(" ");
builder.append(this.y);
builder.append("]");
return builder.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy