
com.io7m.jtensors.VectorI2I 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.Immutable;
import com.io7m.jaux.CheckedMath;
/**
*
* A two-dimensional immutable vector type with integer elements.
*
*
* Values of this type are immutable and can therefore be safely accessed from
* multiple threads.
*
*/
@Immutable public class VectorI2I implements VectorReadable2I
{
/**
* The zero vector.
*/
public static final @Nonnull VectorI2I ZERO = new VectorI2I(0, 0);
/**
* Calculate the absolute values of the elements in vector v
.
*
* @param v
* The input vector
*
* @return (abs v.x, abs v.y, abs v.z)
*
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorI2I absolute(
final @Nonnull VectorReadable2I v)
{
final int x = CheckedMath.absolute(v.getXI());
final int y = CheckedMath.absolute(v.getYI());
return new VectorI2I(x, y);
}
/**
* Calculate the element-wise sum of the vectors v0
and
* v1
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return (v0.x + v1.x, v0.y + v1.y)
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorI2I add(
final @Nonnull VectorReadable2I v0,
final @Nonnull VectorReadable2I v1)
{
final int x = CheckedMath.add(v0.getXI(), v1.getXI());
final int y = CheckedMath.add(v0.getYI(), v1.getYI());
return new VectorI2I(x, y);
}
/**
* Calculate the element-wise sum of the vectors v0
and the
* element-wise product of v1
and r
.
*
* @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))
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorI2I addScaled(
final @Nonnull VectorReadable2I v0,
final @Nonnull VectorReadable2I v1,
final double r)
{
final int mx = CheckedMath.multiply(v1.getXI(), r);
final int my = CheckedMath.multiply(v1.getYI(), r);
final int x = CheckedMath.add(v0.getXI(), mx);
final int y = CheckedMath.add(v0.getYI(), my);
return new VectorI2I(x, y);
}
/**
* Calculate the angle between the 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 VectorReadable2I v0,
final @Nonnull VectorReadable2I v1)
{
final double m0 = VectorI2I.magnitude(v0);
final double m1 = VectorI2I.magnitude(v1);
return Math.acos(VectorI2I.dotProduct(v0, v1) / (m0 * m1));
}
private final static int cast(
final double x)
{
return (int) Math.round(x);
}
/**
* Clamp the elements of the vector v
to the range
* [minimum .. maximum]
inclusive.
*
* @param v
* The input vector
* @param minimum
* The minimum allowed value
* @param maximum
* The maximum allowed value
* @since 5.0.0
* @return A vector with both elements equal to at most maximum
* and at least minimum
*/
public final static @Nonnull VectorI2I clamp(
final @Nonnull VectorReadable2I v,
final int minimum,
final int maximum)
{
final int x = Math.min(Math.max(v.getXI(), minimum), maximum);
final int y = Math.min(Math.max(v.getYI(), minimum), maximum);
return new VectorI2I(x, y);
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in minimum
and
* maximum
.
*
* @param v
* The input vector
* @param minimum
* The vector containing the minimum acceptable values
* @param maximum
* The vector containing the maximum acceptable values
* @since 5.0.0
* @return (min(max(v.x, minimum.x), maximum.x), min(max(v.y, minimum.y), maximum.y))
*/
public final static @Nonnull VectorI2I clampByVector(
final @Nonnull VectorReadable2I v,
final @Nonnull VectorReadable2I minimum,
final @Nonnull VectorReadable2I maximum)
{
final int x =
Math.min(Math.max(v.getXI(), minimum.getXI()), maximum.getXI());
final int y =
Math.min(Math.max(v.getYI(), minimum.getYI()), maximum.getYI());
return new VectorI2I(x, y);
}
/**
* Clamp the elements of the vector v
to the range
* [-Infinity .. maximum]
inclusive.
*
* @param v
* The input vector
* @param maximum
* The maximum allowed value
* @since 5.0.0
* @return A vector with both elements equal to at most maximum
*/
public final static @Nonnull VectorI2I clampMaximum(
final @Nonnull VectorReadable2I v,
final int maximum)
{
final int x = Math.min(v.getXI(), maximum);
final int y = Math.min(v.getYI(), maximum);
return new VectorI2I(x, y);
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in maximum
.
*
* @param v
* The input vector
* @param maximum
* The vector containing the maximum acceptable values
* @since 5.0.0
* @return (min(v.x, maximum.x), min(v.y, maximum.y))
*/
public final static @Nonnull VectorI2I clampMaximumByVector(
final @Nonnull VectorReadable2I v,
final @Nonnull VectorReadable2I maximum)
{
final int x = Math.min(v.getXI(), maximum.getXI());
final int y = Math.min(v.getYI(), maximum.getYI());
return new VectorI2I(x, y);
}
/**
* Clamp the elements of the vector v
to the range
* [minimum .. Infinity]
inclusive.
*
* @param v
* The input vector
* @param minimum
* The minimum allowed value
* @since 5.0.0
* @return A vector with both elements equal to at least
* minimum
*/
public final static @Nonnull VectorI2I clampMinimum(
final @Nonnull VectorReadable2I v,
final int minimum)
{
final int x = Math.max(v.getXI(), minimum);
final int y = Math.max(v.getYI(), minimum);
return new VectorI2I(x, y);
}
/**
* Clamp the elements of the vector v
to the inclusive range
* given by the corresponding elements in minimum
.
*
* @param v
* The input vector
* @param minimum
* The vector containing the minimum acceptable values
* @since 5.0.0
*
* @return (max(v.x, minimum.x), max(v.y, minimum.y))
*/
public final static @Nonnull VectorI2I clampMinimumByVector(
final @Nonnull VectorReadable2I v,
final @Nonnull VectorReadable2I minimum)
{
final int x = Math.max(v.getXI(), minimum.getXI());
final int y = Math.max(v.getYI(), minimum.getYI());
return new VectorI2I(x, y);
}
/**
* 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.
*
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static int distance(
final @Nonnull VectorReadable2I v0,
final @Nonnull VectorReadable2I v1)
{
return VectorI2I.magnitude(VectorI2I.subtract(v0, v1));
}
/**
* 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
*
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static int dotProduct(
final @Nonnull VectorReadable2I v0,
final @Nonnull VectorReadable2I v1)
{
final int mx = CheckedMath.multiply(v0.getXI(), v1.getXI());
final int my = CheckedMath.multiply(v0.getYI(), v1.getYI());
return CheckedMath.add(mx, my);
}
/**
* Linearly interpolate between v0
and v1
by the
* amount alpha
.
*
* 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
.
*
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer
* overflow.
*/
public final static @Nonnull VectorI2I interpolateLinear(
final @Nonnull VectorReadable2I v0,
final @Nonnull VectorReadable2I v1,
final double alpha)
{
final VectorI2I w0 = VectorI2I.scale(v0, 1.0 - alpha);
final VectorI2I w1 = VectorI2I.scale(v1, alpha);
return VectorI2I.add(w0, w1);
}
/**
* 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
*
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static int magnitude(
final @Nonnull VectorReadable2I v)
{
return VectorI2I.cast(Math.sqrt(VectorI2I.magnitudeSquared(v)));
}
/**
* Calculate the squared magnitude of the vector v
.
*
* @param v
* The input vector
*
* @return The squared magnitude of the input vector
*
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static int magnitudeSquared(
final @Nonnull VectorReadable2I v)
{
return VectorI2I.dotProduct(v, v);
}
/**
* Calculate the projection of the vector p
onto the vector
* q
.
*
* @return ((dotProduct p q) / magnitudeSquared q) * q
* @since 5.0.0
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorI2I projection(
final @Nonnull VectorReadable2I p,
final @Nonnull VectorReadable2I q)
{
final int dot = VectorI2I.dotProduct(p, q);
final int qms = VectorI2I.magnitudeSquared(q);
final int s = dot / qms;
return VectorI2I.scale(p, s);
}
/**
* Scale the vector v
by the scalar r
.
*
* @param v
* The input vector
* @param r
* The scaling value
*
* @return (v.x * r, v.y * r)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorI2I scale(
final @Nonnull VectorReadable2I v,
final double r)
{
final int mx = CheckedMath.multiply(v.getXI(), r);
final int my = CheckedMath.multiply(v.getYI(), r);
return new VectorI2I(mx, my);
}
/**
* Subtract the vector v1
from the vector v0
.
*
* @param v0
* The left input vector
* @param v1
* The right input vector
*
* @return (v0.x - v1.x, v0.y - v1.y)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorI2I subtract(
final @Nonnull VectorReadable2I v0,
final @Nonnull VectorReadable2I v1)
{
final int x = CheckedMath.subtract(v0.getXI(), v1.getXI());
final int y = CheckedMath.subtract(v0.getYI(), v1.getYI());
return new VectorI2I(x, y);
}
public final int x;
public final int y;
/**
* Default constructor, initializing the vector with values
* [0, 0, 0]
.
*/
public VectorI2I()
{
this.x = 0;
this.y = 0;
}
/**
* Construct a vector initialized with the given values.
*/
public VectorI2I(
final int x,
final int y)
{
this.x = x;
this.y = y;
}
/**
* Construct a vector initialized with the values given in the vector
* v
.
*/
public VectorI2I(
final @Nonnull VectorReadable2I v)
{
this.x = v.getXI();
this.y = v.getYI();
}
@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 VectorI2I other = (VectorI2I) obj;
if (this.x != other.x) {
return false;
}
if (this.y != other.y) {
return false;
}
return true;
}
@Override public final int getXI()
{
return this.x;
}
@Override public final int getYI()
{
return this.y;
}
@Override public final int hashCode()
{
final int prime = 31;
int result = 1;
result = (prime * result) + this.x;
result = (prime * result) + this.y;
return result;
}
@Override public final String toString()
{
final StringBuilder builder = new StringBuilder();
builder.append("[VectorI2I ");
builder.append(this.x);
builder.append(" ");
builder.append(this.y);
builder.append("]");
return builder.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy