diff --git a/src/main/java/br/com/rafael/math/vector/Vector3D.java b/src/main/java/br/com/rafael/math/vector/Vector3D.java new file mode 100644 index 0000000..8b4ab7d --- /dev/null +++ b/src/main/java/br/com/rafael/math/vector/Vector3D.java @@ -0,0 +1,295 @@ +package br.com.rafael.math.vector; +/** + * Copyright© 2020 Victor Rafael Pereira Alves + * + *

This file is part of MathUtils. + * + *

MathUtils is free software: you can redistribute it and/or modify it under the terms of the + * Lesser GNU General Public License as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + *

MathUtils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser + * GNU General Public License for more details. + * + *

You should have received a copy of the Lesser GNU General Public License along with MathUtils. + * If not, see < https://www.gnu.org/licenses/ > . + * + */ + +import br.com.rafael.math.vector.Vector3D; +import java.io.Serializable; + +public class Vector3D implements Cloneable, Comparable, Serializable { + + private static final long serialVersionUID = 0l; + + private double _x; + private double _y; + private double _z; + + public Vector3D() { + _x = _y = _z = 0; + } + + public Vector3D(double x, double y, double z) { + _x = x; + _y = y; + _z = z; + } + + public Vector3D(Vector2D plane) { + this(plane, 0); + } + + public Vector3D(Vector2D plane, double depth) { + _x = plane.getX(); + _y = plane.getY(); + _z = depth; + } + + public Vector3D(Vector3D old) { + _x = old._x; + _y = old._y; + _z = old._z; + } + + public void setX(double x) { + _x = x; + } + + public void setY(double y) { + _y = y; + } + + public void setZ(double z) { + _z = z; + } + + public double getX() { + return _x; + } + + public double getY() { + return _y; + } + + public double getZ() { + return _z; + } + + public double size() { + return Math.sqrt(_x * _x + _y * _y + _z * _z); + } + + public Vector3D negateMe() { + _x = -_x; + _y = -_y; + _z = -_z; + return this; + } + + public Vector3D negate() { + return clone().negateMe(); + } + + public Vector3D addMe(Vector3D other) { + this._x += other._x; + this._y += other._y; + this._z += other._z; + return this; + } + + public Vector3D add(Vector3D other) { + return clone().addMe(other); + } + + public Vector3D subtractMe(Vector3D other) { + this._x -= other._x; + this._y -= other._y; + this._z -= other._z; + return this; + } + + public Vector3D subtract(Vector3D other) { + return clone().subtractMe(other); + } + + public Vector3D multiplyMe(double scalar) { + this._x *= scalar; + this._y *= scalar; + this._z *= scalar; + return this; + } + + public Vector3D multiply(double scalar) { + return clone().multiplyMe(scalar); + } + + public Vector3D divideMe(double scalar) { + this._x /= scalar; + this._y /= scalar; + this._z /= scalar; + return this; + } + + public Vector3D divide(double scalar) { + return clone().divideMe(scalar); + } + + public Vector3D normalizeMe() { + return divideMe(size()); + } + + public Vector3D normalize() { + return clone().normalizeMe(); + } + + public Vector3D resizeMe(float size) { + return normalizeMe().multiplyMe(size); + } + + public Vector3D resize(float size) { + return clone().resizeMe(size); + } + + public double distance(Vector3D other) { + return this.subtractMe(other).size(); + } + + public double dot(Vector3D other) { + return Math.sqrt(this._x * other._x + this._y * other._y + this._z * other._z); + } + + public Vector3D crossMe(Vector3D other) { + double newX = this._y * other._z - this._z * other._y; + double newY = this._z * other._x - this._x * other._z; + double newZ = this._x * other._y - this._y * other._x; + + this._x = newX; + this._y = newY; + this._z = newZ; + + return this; + } + + public Vector3D cross(Vector3D other) { + return this.clone().crossMe(other); + } + + public Vector3D rotateMeX(double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + + double newY = cos * _y - sin * _z; + double newZ = sin * _y + cos * _z; + + this._y = newY; + this._z = newZ; + + return this; + } + + public Vector3D rotateX(double angle) { + return clone().rotateMeX(angle); + } + + public Vector3D rotateMeY(double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + + double newZ = cos * _z - sin * _x; + double newX = sin * _z + cos * _x; + + this._x = newX; + this._z = newZ; + + return this; + } + + public Vector3D rotateY(double angle) { + return clone().rotateMeY(angle); + } + + public Vector3D rotateMeZ(double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + + double newX = cos * _x - sin * _y; + double newY = sin * _x + cos * _y; + + this._x = newX; + this._y = newY; + + return this; + } + + public Vector3D rotateZ(double angle) { + return clone().rotateMeZ(angle); + } + + public Vector3D rotateMeAxis(Vector3D axis, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double k = 1.0 - cos; + + double newX = _x * (cos + k * axis._x * axis._x) + _y * (k * axis._x * axis._y - sin * axis._z) + _z * (k * axis._x * axis._z + sin * axis._y); + + double newY = _x * (k * axis._x * axis._y + sin * axis._z) + _y * (cos + k * axis._y * axis._y) + _z * (k * axis._y * axis._z - sin * axis._x); + + double newZ = _x * (k * axis._x * axis._z - sin * axis._y) + _y * (k * axis._y * axis._z + sin * axis._x) + _z * (cos + k * axis._z * axis._z); + + _x = newX; + _y = newY; + _z = newZ; + + return this; + } + + public Vector3D rotateAxis(Vector3D axis, double angle) { + return this.clone().rotateMeAxis(axis, angle); + } + + @Override + public Vector3D clone() { + try { + return (Vector3D) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + + @Override + public int compareTo(Vector3D other) { + return (int) (this.size() - other.size()); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Vector3D)) return false; + Vector3D other = (Vector3D) o; + return _x == other._x && _y == other._y && _z == other._z; + } + + @Override + public int hashCode() { + int result = 17; + + result = result * 31 + hashDouble(_x); + result = result * 31 + hashDouble(_y); + result = result * 31 + hashDouble(_z); + + return result; + } + + private int hashDouble(double d) { + long longBits = Double.doubleToLongBits(d); + return (int) (longBits ^ (longBits >>> 32)); + } + + @Override + public String toString() { + return "{x: " + _x + ", y:" + _y + ", z: " + _z + "}"; + } +}