All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.io7m.jtensors.VectorI3F 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.AlmostEqualDouble.ContextRelative;
import com.io7m.jaux.AlmostEqualFloat;
import com.io7m.jaux.functional.Pair;

/**
 * 

* A three-dimensional immutable vector type with single precision elements. *

*

* Values of this type are immutable and can therefore be safely accessed from * multiple threads. *

*/ @Immutable public class VectorI3F implements VectorReadable3F { /** * 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.getXF() + (v1.getXF() * r), v0.getYF() + (v1.getYF() * r), v0.getZF() + (v1.getZF() * r)) */ public final static @Nonnull VectorI3F addScaled( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1, final float r) { return VectorI3F.add(v0, VectorI3F.scale(v1, r)); } /** * Determine whether or not the vectors va and vb * are equal to within the degree of error given in context. * * @see AlmostEqualFloat#almostEqual(ContextRelative, float, float) * * @param context * The equality context * @param va * The left input vector * @param vb * The right input vector * @since 5.0.0 */ public final static boolean almostEqual( final @Nonnull AlmostEqualFloat.ContextRelative context, final @Nonnull VectorReadable3F va, final @Nonnull VectorReadable3F vb) { final boolean xs = AlmostEqualFloat.almostEqual(context, va.getXF(), vb.getXF()); final boolean ys = AlmostEqualFloat.almostEqual(context, va.getYF(), vb.getYF()); final boolean zs = AlmostEqualFloat.almostEqual(context, va.getZF(), vb.getZF()); return xs && ys && zs; } /** * 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 * * @return A vector with both elements equal to at most maximum * and at least minimum. */ public final static @Nonnull VectorI3F clamp( final @Nonnull VectorReadable3F v, final float minimum, final float maximum) { final float x = Math.min(Math.max(v.getXF(), minimum), maximum); final float y = Math.min(Math.max(v.getYF(), minimum), maximum); final float z = Math.min(Math.max(v.getZF(), minimum), maximum); return new VectorI3F(x, y, z); } /** * 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 * * @return (min(max(v.getXF(), minimum.getXF()), maximum.getXF()), min(max(v.getYF(), minimum.getYF()), maximum.getYF()), min(max(v.getZF(), minimum.getZF()), maximum.getZF())) */ public final static @Nonnull VectorI3F clampByVector( final @Nonnull VectorReadable3F v, final @Nonnull VectorReadable3F minimum, final @Nonnull VectorReadable3F maximum) { 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()); final float z = Math.min(Math.max(v.getZF(), minimum.getZF()), maximum.getZF()); return new VectorI3F(x, y, z); } /** * Clamp the elements of the vector v to the range * [-Infinity .. maximum] inclusive. * * @param v * The input vector * @param maximum * The maximum allowed value * * @return A vector with both elements equal to at most maximum */ public final static @Nonnull VectorI3F clampMaximum( final @Nonnull VectorReadable3F v, final float maximum) { final float x = Math.min(v.getXF(), maximum); final float y = Math.min(v.getYF(), maximum); final float z = Math.min(v.getZF(), maximum); return new VectorI3F(x, y, z); } /** * 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 * * @return (min(v.getXF(), maximum.getXF()), min(v.getYF(), maximum.getYF()), min(v.getZF(), maximum.getZF())) */ public final static @Nonnull VectorI3F clampMaximumByVector( final @Nonnull VectorReadable3F v, final @Nonnull VectorReadable3F maximum) { final float x = Math.min(v.getXF(), maximum.getXF()); final float y = Math.min(v.getYF(), maximum.getYF()); final float z = Math.min(v.getZF(), maximum.getZF()); return new VectorI3F(x, y, z); } /** * Clamp the elements of the vector v to the range * [minimum .. Infinity] inclusive. * * @param v * The input vector * @param minimum * The minimum allowed value * * @return A vector with both elements equal to at least * minimum */ public final static @Nonnull VectorI3F clampMinimum( final @Nonnull VectorReadable3F v, final float minimum) { final float x = Math.max(v.getXF(), minimum); final float y = Math.max(v.getYF(), minimum); final float z = Math.max(v.getZF(), minimum); return new VectorI3F(x, y, z); } /** * 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 * * @return (max(v.getXF(), minimum.getXF()), max(v.getYF(), minimum.getYF()), max(v.getZF(), minimum.getZF())) */ public final static @Nonnull VectorI3F clampMinimumByVector( final @Nonnull VectorReadable3F v, final @Nonnull VectorReadable3F minimum) { final float x = Math.max(v.getXF(), minimum.getXF()); final float y = Math.max(v.getYF(), minimum.getYF()); final float z = Math.max(v.getZF(), minimum.getZF()); return new VectorI3F(x, y, z); } /** * Calculate the cross product of the vectors v0 and * v1. The result is a vector perpendicular to both vectors. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return A vector perpendicular to both v0 and * v1 */ public final static @Nonnull VectorI3F crossProduct( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1) { final float x = (v0.getYF() * v1.getZF()) - (v0.getZF() * v1.getYF()); final float y = (v0.getZF() * v1.getXF()) - (v0.getXF() * v1.getZF()); final float z = (v0.getXF() * v1.getYF()) - (v0.getYF() * v1.getXF()); return new VectorI3F(x, y, z); } /** * 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 float distance( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1) { return VectorI3F.magnitude(VectorI3F.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 */ public final static float dotProduct( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1) { final float x = v0.getXF() * v1.getXF(); final float y = v0.getYF() * v1.getYF(); final float z = v0.getZF() * v1.getZF(); return x + y + z; } /** * 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) = v0
  • *
  • interpolateLinear(v0, v1, 1.0) = v1
  • *
* * @param v0 * The left input vector. * @param v1 * The right input vector. * @param alpha * The interpolation value, between 0.0 and * 1.0. * * @return (1 - alpha) * v0 + alpha * v1 */ public final static @Nonnull VectorI3F interpolateLinear( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1, final float alpha) { final @Nonnull VectorReadable3F w0 = VectorI3F.scale(v0, 1.0f - alpha); final @Nonnull VectorReadable3F w1 = VectorI3F.scale(v1, alpha); return VectorI3F.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 */ public final static float magnitude( final @Nonnull VectorReadable3F v) { return (float) Math.sqrt(VectorI3F.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 float magnitudeSquared( final @Nonnull VectorReadable3F v) { return VectorI3F.dotProduct(v, v); } /** * Normalize the vector v, preserving its direction but * reducing it to unit length. * * @param v * The input vector * * @return A vector with the same orientation as v but with * magnitude equal to 1.0 */ public final static @Nonnull VectorI3F normalize( final @Nonnull VectorReadable3F v) { final float m = VectorI3F.magnitudeSquared(v); if (m > 0) { final float reciprocal = (float) (1.0f / Math.sqrt(m)); return VectorI3F.scale(v, reciprocal); } return new VectorI3F(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 VectorReadable3F v0, final @Nonnull VectorReadable3F v1) { final VectorI3F v0n = VectorI3F.normalize(v0); final VectorI3F projection = VectorI3F.scale(v0n, VectorI3F.dotProduct(v1, v0n)); final VectorI3F vr = VectorI3F.normalize(VectorI3F.subtract(v1, projection)); return new Pair(v0n, vr); } /** * Calculate the projection of the vector p onto the vector * q. * * @return ((dotProduct p q) / magnitudeSquared q) * q */ public final static @Nonnull VectorI3F projection( final @Nonnull VectorReadable3F p, final @Nonnull VectorReadable3F q) { final float dot = VectorI3F.dotProduct(p, q); final float qms = VectorI3F.magnitudeSquared(q); final float s = dot / qms; return VectorI3F.scale(p, s); } /** * Scale the vector v by the scalar r. * * @param v * The input vector * @param r * The scaling value * * @return (v.getXF() * r, v.getYF() * r, v.getZF() * r) */ public final static @Nonnull VectorI3F scale( final @Nonnull VectorReadable3F v, final float r) { return new VectorI3F(v.getXF() * r, v.getYF() * r, v.getZF() * r); } /** * Subtract the vector v1 from the vector v0. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return (v0.getXF() - v1.getXF(), v0.getYF() - v1.getYF(), v0.getZF() - v1.getZF()) */ public final static @Nonnull VectorI3F subtract( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1) { return new VectorI3F( v0.getXF() - v1.getXF(), v0.getYF() - v1.getYF(), v0.getZF() - v1.getZF()); } public final float x; public final float y; public final float z; /** * The zero vector. */ public static final @Nonnull VectorI3F ZERO = new VectorI3F( 0.0f, 0.0f, 0.0f); /** * Calculate the absolute value of the vector v. * * @param v * The input vector * * @return (abs v.getXF(), abs v.getYF(), abs v.getZF()) */ public final static @Nonnull VectorI3F absolute( final @Nonnull VectorReadable3F v) { return new VectorI3F(Math.abs(v.getXF()), Math.abs(v.getYF()), Math.abs(v .getZF())); } /** * 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.getXF() + v1.getXF(), v0.getYF() + v1.getYF(), v0.getZF() + v1.getZF()) */ public final static @Nonnull VectorI3F add( final @Nonnull VectorReadable3F v0, final @Nonnull VectorReadable3F v1) { return new VectorI3F( v0.getXF() + v1.getXF(), v0.getYF() + v1.getYF(), v0.getZF() + v1.getZF()); } /** * Default constructor, initializing the vector with values * [0.0, 0.0, 0.0]. */ public VectorI3F() { this.x = 0.0f; this.y = 0.0f; this.z = 0.0f; } /** * Construct a vector initialized with the given values. */ public VectorI3F( final float x, final float y, final float z) { this.x = x; this.y = y; this.z = z; } /** * Construct a vector initialized with the values given in the vector * v. */ public VectorI3F( final VectorReadable3F v) { this.x = v.getXF(); this.y = v.getYF(); this.z = v.getZF(); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @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 VectorI3F other = (VectorI3F) obj; if (Float.floatToIntBits(this.getXF()) != Float.floatToIntBits(other .getXF())) { return false; } if (Float.floatToIntBits(this.getYF()) != Float.floatToIntBits(other .getYF())) { return false; } if (Float.floatToIntBits(this.getZF()) != Float.floatToIntBits(other .getZF())) { return false; } return true; } @Override public final float getXF() { return this.x; } @Override public final float getYF() { return this.y; } @Override public final float getZF() { return this.z; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public final int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + Float.floatToIntBits(this.getXF()); result = (prime * result) + Float.floatToIntBits(this.getYF()); result = (prime * result) + Float.floatToIntBits(this.getZF()); return result; } @Override public final String toString() { final StringBuilder builder = new StringBuilder(); builder.append("[VectorI3F "); builder.append(this.getXF()); builder.append(" "); builder.append(this.getYF()); builder.append(" "); builder.append(this.getZF()); builder.append("]"); return builder.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy