/** * Vector3D.java * * Copyright (c) 2013-2016, F(X)yz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of F(X)yz, any associated website, nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.fxyz3d.geometry; /** * * @author Dub */ public final class Vector3D { public static final Vector3D// Homogenious public static final Vector3D// Homogenious FORWARD = new Vector3D(0, 0, 1), BACK = new Vector3D(0, 0, -1), LEFT = new Vector3D(-1, 0, 0), RIGHT = new Vector3D(1, 0, 0), UP = new Vector3D(0, 1, 0), DOWN = new Vector3D(0, -1, 0), ONE = new Vector3D(1, 1, 1), ZERO = new Vector3D(0, 0, 0), NAN = new Vector3D(Double.NaN, Double.NaN, Double.NaN); public double x; public double y; public double z; public Vector3D() { this.x = 0; this.y = 0; this.z = 0; } public Vector3D(Vector3D source) { this.x = source.x; this.y = source.y; this.z = source.z; } public Vector3D(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } public Vector3D(double... values) { if (values.length != size()) { throw new IllegalArgumentException(); } this.x = values[0]; this.y = values[1]; this.z = values[2]; } public double angle(Vector3D v) { double mag2 = (x * x) + (y * y) + (z * z); double vmag2 = (v.x * v.x) + (v.y * v.y) + (v.z * v.z); double dot = (x * v.x) + (y * v.y) + (z * v.z); return Math.acos(dot / Math.sqrt(mag2 * vmag2)); } public Vector3D add(double constant) { double nx = x + constant, ny = y + constant, nz = z + constant; return new Vector3D(nx, ny, nz); } public Vector3D add(double dx, double dy, double dz) { double nx = x + dx, ny = y + dy, nz = z + dz; return new Vector3D(nx, ny, nz); } public Vector3D add(Vector3D v) { double nx = x + v.x, ny = y += v.y, nz = z += v.z; return new Vector3D(nx, ny, nz); } public Vector3D addMultiply(double dx, double dy, double dz, double factor) { double nx = x + dx * factor, ny = y + dy * factor, nz = z + dz * factor; return new Vector3D(nx, ny, nz); } public Vector3D addMultiply(Vector3D v, double factor) { double nx = x + v.x * factor, ny = y + v.y * factor, nz = z + v.z * factor; return new Vector3D(nx, ny, nz); } public Vector3D addProduct(Vector3D a, Vector3D b) { x += a.x * b.x; y += a.y * b.y; z += a.z * b.z; return new Vector3D(x, y, z); } public Vector3D addProduct(Vector3D a, Vector3D b, double factor) { x += a.x * b.x * factor; y += a.y * b.y * factor; z += a.z * b.z * factor; return new Vector3D(x, y, z); } public double magnitudeSquared() { return (x * x) + (y * y) + (z * z); } public double distanceSquared(Vector3D v) { double dx = x - v.x, dy = y - v.y, dz = z - v.z; return (dx * dx) + (dy * dy) + (dz * dz); } public double distance(Vector3D v) { return Math.sqrt(distanceSquared(v)); } public double inverseMagnitude() { return 1.0 / Math.sqrt(magnitudeSquared()); } public double magnitude() { return Math.sqrt(magnitudeSquared()); } public void normalize() { double d = magnitude(); if (d == 0.0) { x = 0; y = 0; z = 0; } x /= d; y /= d; z /= d; } public void setAs(Vector3D a) { this.x = a.x; this.y = a.y; this.z = a.z; } public Vector3D multiply(double d) { return new Vector3D( x * d, y * d, z * d); } public Vector3D subtractMultiple(Vector3D v, double factor) { return new Vector3D( x - v.x * factor, y - v.y * factor, z - v.z * factor ); } public Vector3D sub(Vector3D v) { double nx = x - v.x, ny = y - v.y, nz = z - v.z; return new Vector3D(nx, ny, nz); } public Vector3D subMultiple(Vector3D v, double factor) { return addMultiply(v, -factor); } public double dotProduct(Vector3D a) { return (x * a.x) + (y * a.y) + (z * a.z); } public double dotProduct(double[] data, int offset) { return x * data[offset + 0] + y * data[offset + 1] + z * data[offset + 2]; } public Vector3D crossProduct(Vector3D a) { double tx = y * a.z - z * a.y; double ty = z * a.x - x * a.z; double tz = x * a.y - y * a.x; return new Vector3D(tx, ty, tz); } public Vector3D orthogonalTo(Vector3D v1, Vector3D v2){ return v1.crossProduct(v2); } public Vector3D projectToPlane(Vector3D normal, double distance) { double d = dotProduct(normal); return addMultiply(normal, distance - d); } public int size() { return 3; } public double getSum() { return x + y + z; } public double getProduct() { return x * y * z; } public Vector3D scaleAdd(double factor, double constant) { x = (x * factor) + constant; y = (y * factor) + constant; z = (z * factor) + constant; return new Vector3D(x, y, z); } public Vector3D scaleAdd(double factor, Vector3D constant) { x = (x * factor) + constant.x; y = (y * factor) + constant.y; z = (z * factor) + constant.z; return new Vector3D(x, y, z); } public void setValues(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } public Vector3D negate() { return new Vector3D(-x, -y, -z); } public void getElements(double[] data, int offset) { data[offset] = x; data[offset + 1] = y; data[offset + 2] = z; } public double[] toDoubleArray() { return new double[]{x, y, z}; } public Vector3D toNormal() { double d = this.magnitude(); return (d == 0) ? ZERO : new Vector3D(x / d, y / d, z / d); } public double getX() { return x; } public double getY() { return y; } public double getZ() { return z; } public boolean equals(Vector3D v) { return (x == v.x) && (y == v.y) && (z == v.z); } @Override public String toString() { return "Vector3: {X: " + x + ", Y: " + y + ", Z: " + z + "}"; } }