org.joml.AABBd Maven / Gradle / Ivy
/*
* The MIT License
*
* Copyright (c) 2017-2019 JOML
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.joml;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.joml.internal.Options;
import org.joml.internal.Runtime;
/**
* Represents an axis-aligned box defined via the minimum and maximum corner coordinates.
*
* @author Kai Burjack
*/
public class AABBd {
public double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY, minZ = Double.POSITIVE_INFINITY;
public double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY, maxZ = Double.NEGATIVE_INFINITY;
/**
* Create a new {@link AABBd} representing the box with
* (minX, minY, minZ)=(+inf, +inf, +inf)
and (maxX, maxY, maxZ)=(-inf, -inf, -inf)
.
*/
public AABBd() {
}
/**
* Create a new {@link AABBd} as a copy of the given source
.
*
* @param source
* the {@link AABBd} to copy from
*/
public AABBd(AABBd source) {
this.minX = source.minX;
this.minY = source.minY;
this.minZ = source.minZ;
this.maxX = source.maxX;
this.maxY = source.maxY;
this.maxZ = source.maxZ;
}
/**
* Create a new {@link AABBd} with the given minimum and maximum corner coordinates.
*
* @param min
* the minimum coordinates
* @param max
* the maximum coordinates
*/
public AABBd(Vector3dc min, Vector3dc max) {
this.minX = min.x();
this.minY = min.y();
this.minZ = min.z();
this.maxX = max.x();
this.maxY = max.y();
this.maxZ = max.z();
}
/**
* Create a new {@link AABBd} with the given minimum and maximum corner coordinates.
*
* @param minX
* the x coordinate of the minimum corner
* @param minY
* the y coordinate of the minimum corner
* @param minZ
* the z coordinate of the minimum corner
* @param maxX
* the x coordinate of the maximum corner
* @param maxY
* the y coordinate of the maximum corner
* @param maxZ
* the z coordinate of the maximum corner
*/
public AABBd(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
/**
* Set the minimum corner coordinates.
*
* @param minX
* the x coordinate of the minimum corner
* @param minY
* the y coordinate of the minimum corner
* @param minZ
* the z coordinate of the minimum corner
* @return this
*/
public AABBd setMin(double minX, double minY, double minZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
return this;
}
/**
* Set the maximum corner coordinates.
*
* @param maxX
* the x coordinate of the maximum corner
* @param maxY
* the y coordinate of the maximum corner
* @param maxZ
* the z coordinate of the maximum corner
* @return this
*/
public AABBd setMax(double maxX, double maxY, double maxZ) {
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
return this;
}
/**
* Set the minimum corner coordinates.
*
* @param min
* the minimum coordinates
* @return this
*/
public AABBd setMin(Vector3dc min) {
return this.setMin(min.x(), min.y(), min.z());
}
/**
* Set the maximum corner coordinates.
*
* @param max
* the maximum coordinates
* @return this
*/
public AABBd setMax(Vector3dc max) {
return this.setMax(max.x(), max.y(), max.z());
}
/**
* Set this
to the union of this
and the given point (x, y, z)
.
*
* @param x
* the x coordinate of the point
* @param y
* the y coordinate of the point
* @param z
* the z coordinate of the point
* @return this
*/
public AABBd union(double x, double y, double z) {
return union(x, y, z, this);
}
/**
* Set this
to the union of this
and the given point p
.
*
* @param p
* the point
* @return this
*/
public AABBd union(Vector3dc p) {
return union(p.x(), p.y(), p.z(), this);
}
/**
* Compute the union of this
and the given point (x, y, z)
and store the result in dest
.
*
* @param x
* the x coordinate of the point
* @param y
* the y coordinate of the point
* @param z
* the z coordinate of the point
* @param dest
* will hold the result
* @return dest
*/
public AABBd union(double x, double y, double z, AABBd dest) {
dest.minX = this.minX < x ? this.minX : x;
dest.minY = this.minY < y ? this.minY : y;
dest.minZ = this.minZ < z ? this.minZ : z;
dest.maxX = this.maxX > x ? this.maxX : x;
dest.maxY = this.maxY > y ? this.maxY : y;
dest.maxZ = this.maxZ > z ? this.maxZ : z;
return dest;
}
/**
* Compute the union of this
and the given point p
and store the result in dest
.
*
* @param p
* the point
* @param dest
* will hold the result
* @return dest
*/
public AABBd union(Vector3dc p, AABBd dest) {
return union(p.x(), p.y(), p.z(), dest);
}
/**
* Set this
to the union of this
and other
.
*
* @param other
* the other {@link AABBd}
* @return this
*/
public AABBd union(AABBd other) {
return this.union(other, this);
}
/**
* Compute the union of this
and other
and store the result in dest
.
*
* @param other
* the other {@link AABBd}
* @param dest
* will hold the result
* @return dest
*/
public AABBd union(AABBd other, AABBd dest) {
dest.minX = this.minX < other.minX ? this.minX : other.minX;
dest.minY = this.minY < other.minY ? this.minY : other.minY;
dest.minZ = this.minZ < other.minZ ? this.minZ : other.minZ;
dest.maxX = this.maxX > other.maxX ? this.maxX : other.maxX;
dest.maxY = this.maxY > other.maxY ? this.maxY : other.maxY;
dest.maxZ = this.maxZ > other.maxZ ? this.maxZ : other.maxZ;
return dest;
}
/**
* Ensure that the minimum coordinates are strictly less than or equal to the maximum coordinates by swapping
* them if necessary.
*
* @return this
*/
public AABBd correctBounds() {
double tmp;
if (this.minX > this.maxX) {
tmp = this.minX;
this.minX = this.maxX;
this.maxX = tmp;
}
if (this.minY > this.maxY) {
tmp = this.minY;
this.minY = this.maxY;
this.maxY = tmp;
}
if (this.minZ > this.maxZ) {
tmp = this.minZ;
this.minZ = this.maxZ;
this.maxZ = tmp;
}
return this;
}
/**
* Test whether the point (x, y, z)
lies inside this AABB.
*
* @param x
* the x coordinate of the point
* @param y
* the y coordinate of the point
* @param z
* the z coordinate of the point
* @return true
iff the given point lies inside this AABB; false
otherwise
*/
public boolean testPoint(double x, double y, double z) {
return x >= minX && y >= minY && z >= minZ && x <= maxX && y <= maxY && z <= maxZ;
}
/**
* Test whether the given point lies inside this AABB.
*
* @param point
* the coordinates of the point
* @return true
iff the given point lies inside this AABB; false
otherwise
*/
public boolean testPoint(Vector3dc point) {
return testPoint(point.x(), point.y(), point.z());
}
/**
* Test whether the plane given via its plane equation a*x + b*y + c*z + d = 0
intersects this AABB.
*
* Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II")
*
* @param a
* the x factor in the plane equation
* @param b
* the y factor in the plane equation
* @param c
* the z factor in the plane equation
* @param d
* the constant in the plane equation
* @return true
iff the plane intersects this AABB; false
otherwise
*/
public boolean testPlane(double a, double b, double c, double d) {
return Intersectiond.testAabPlane(minX, minY, minZ, maxX, maxY, maxZ, a, b, c, d);
}
/**
* Test whether the given plane intersects this AABB.
*
* Reference: http://www.lighthouse3d.com ("Geometric Approach - Testing Boxes II")
*
* @param plane
* the plane
* @return true
iff the plane intersects this AABB; false
otherwise
*/
public boolean testPlane(Planed plane) {
return Intersectiond.testAabPlane(this, plane);
}
/**
* Test whether this
and other
intersect.
*
* @param other
* the other AABB
* @return true
iff both AABBs intersect; false
otherwise
*/
public boolean testAABB(AABBd other) {
return this.maxX >= other.minX && this.maxY >= other.minY && this.maxZ >= other.minZ &&
this.minX <= other.maxX && this.minY <= other.maxY && this.minZ <= other.maxZ;
}
/**
* Test whether this AABB intersects the given sphere with equation
* (x - centerX)^2 + (y - centerY)^2 + (z - centerZ)^2 - radiusSquared = 0
.
*
* Reference: http://stackoverflow.com
*
* @param centerX
* the x coordinate of the center of the sphere
* @param centerY
* the y coordinate of the center of the sphere
* @param centerZ
* the z coordinate of the center of the sphere
* @param radiusSquared
* the square radius of the sphere
* @return true
iff this AABB and the sphere intersect; false
otherwise
*/
public boolean testSphere(double centerX, double centerY, double centerZ, double radiusSquared) {
return Intersectiond.testAabSphere(minX, minY, minZ, maxX, maxY, maxZ, centerX, centerY, centerZ, radiusSquared);
}
/**
* Test whether this AABB intersects the given sphere.
*
* Reference: http://stackoverflow.com
*
* @param sphere
* the sphere
* @return true
iff this AABB and the sphere intersect; false
otherwise
*/
public boolean testSphere(Spheref sphere) {
return Intersectiond.testAabSphere(this, sphere);
}
/**
* Test whether the given ray with the origin (originX, originY, originZ)
and direction (dirX, dirY, dirZ)
* intersects this AABB.
*
* This method returns true
for a ray whose origin lies inside this AABB.
*
* Reference: An Efficient and Robust Ray–Box Intersection
*
* @param originX
* the x coordinate of the ray's origin
* @param originY
* the y coordinate of the ray's origin
* @param originZ
* the z coordinate of the ray's origin
* @param dirX
* the x coordinate of the ray's direction
* @param dirY
* the y coordinate of the ray's direction
* @param dirZ
* the z coordinate of the ray's direction
* @return true
if this AABB and the ray intersect; false
otherwise
*/
public boolean testRay(double originX, double originY, double originZ, double dirX, double dirY, double dirZ) {
return Intersectiond.testRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Test whether the given ray intersects this AABB.
*
* This method returns true
for a ray whose origin lies inside this AABB.
*
* Reference: An Efficient and Robust Ray–Box Intersection
*
* @param ray
* the ray
* @return true
if this AABB and the ray intersect; false
otherwise
*/
public boolean testRay(Rayd ray) {
return Intersectiond.testRayAab(ray, this);
}
/**
* Determine whether the given ray with the origin (originX, originY, originZ)
and direction (dirX, dirY, dirZ)
* intersects this AABB, and return the values of the parameter t in the ray equation
* p(t) = origin + t * dir of the near and far point of intersection.
*
* This method returns true
for a ray whose origin lies inside this AABB.
*
* Reference: An Efficient and Robust Ray–Box Intersection
*
* @param originX
* the x coordinate of the ray's origin
* @param originY
* the y coordinate of the ray's origin
* @param originZ
* the z coordinate of the ray's origin
* @param dirX
* the x coordinate of the ray's direction
* @param dirY
* the y coordinate of the ray's direction
* @param dirZ
* the z coordinate of the ray's direction
* @param result
* a vector which will hold the resulting values of the parameter
* t in the ray equation p(t) = origin + t * dir of the near and far point of intersection
* iff the ray intersects this AABB
* @return true
if the given ray intersects this AABB; false
otherwise
*/
public boolean intersectRay(double originX, double originY, double originZ, double dirX, double dirY, double dirZ, Vector2d result) {
return Intersectiond.intersectRayAab(originX, originY, originZ, dirX, dirY, dirZ, minX, minY, minZ, maxX, maxY, maxZ, result);
}
/**
* Determine whether the given ray intersects this AABB, and return the values of the parameter t in the ray equation
* p(t) = origin + t * dir of the near and far point of intersection.
*
* This method returns true
for a ray whose origin lies inside this AABB.
*
* Reference: An Efficient and Robust Ray–Box Intersection
*
* @param ray
* the ray
* @param result
* a vector which will hold the resulting values of the parameter
* t in the ray equation p(t) = origin + t * dir of the near and far point of intersection
* iff the ray intersects this AABB
* @return true
if the given ray intersects this AABB; false
otherwise
*/
public boolean intersectRay(Rayd ray, Vector2d result) {
return Intersectiond.intersectRayAab(ray, this, result);
}
/**
* Determine whether the undirected line segment with the end points (p0X, p0Y, p0Z)
and (p1X, p1Y, p1Z)
* intersects this AABB, and return the values of the parameter t in the ray equation
* p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection.
*
* This method returns true
for a line segment whose either end point lies inside this AABB.
*
* Reference: An Efficient and Robust Ray–Box Intersection
*
* @param p0X
* the x coordinate of the line segment's first end point
* @param p0Y
* the y coordinate of the line segment's first end point
* @param p0Z
* the z coordinate of the line segment's first end point
* @param p1X
* the x coordinate of the line segment's second end point
* @param p1Y
* the y coordinate of the line segment's second end point
* @param p1Z
* the z coordinate of the line segment's second end point
* @param result
* a vector which will hold the resulting values of the parameter
* t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection
* iff the line segment intersects this AABB
* @return {@link Intersectiond#INSIDE} if the line segment lies completely inside of this AABB; or
* {@link Intersectiond#OUTSIDE} if the line segment lies completely outside of this AABB; or
* {@link Intersectiond#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or
* {@link Intersectiond#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB
*/
public int intersectLineSegment(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z, Vector2d result) {
return Intersectiond.intersectLineSegmentAab(p0X, p0Y, p0Z, p1X, p1Y, p1Z, minX, minY, minZ, maxX, maxY, maxZ, result);
}
/**
* Determine whether the given undirected line segment intersects this AABB, and return the values of the parameter t in the ray equation
* p(t) = origin + p0 * (p1 - p0) of the near and far point of intersection.
*
* This method returns true
for a line segment whose either end point lies inside this AABB.
*
* Reference: An Efficient and Robust Ray–Box Intersection
*
* @param lineSegment
* the line segment
* @param result
* a vector which will hold the resulting values of the parameter
* t in the ray equation p(t) = p0 + t * (p1 - p0) of the near and far point of intersection
* iff the line segment intersects this AABB
* @return {@link Intersectiond#INSIDE} if the line segment lies completely inside of this AABB; or
* {@link Intersectiond#OUTSIDE} if the line segment lies completely outside of this AABB; or
* {@link Intersectiond#ONE_INTERSECTION} if one of the end points of the line segment lies inside of this AABB; or
* {@link Intersectiond#TWO_INTERSECTION} if the line segment intersects two sides of this AABB or lies on an edge or a side of this AABB
*/
public int intersectLineSegment(LineSegmentf lineSegment, Vector2d result) {
return Intersectiond.intersectLineSegmentAab(lineSegment, this, result);
}
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(maxX);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(maxY);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(maxZ);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(minX);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(minY);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(minZ);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AABBd other = (AABBd) obj;
if (Double.doubleToLongBits(maxX) != Double.doubleToLongBits(other.maxX))
return false;
if (Double.doubleToLongBits(maxY) != Double.doubleToLongBits(other.maxY))
return false;
if (Double.doubleToLongBits(maxZ) != Double.doubleToLongBits(other.maxZ))
return false;
if (Double.doubleToLongBits(minX) != Double.doubleToLongBits(other.minX))
return false;
if (Double.doubleToLongBits(minY) != Double.doubleToLongBits(other.minY))
return false;
if (Double.doubleToLongBits(minZ) != Double.doubleToLongBits(other.minZ))
return false;
return true;
}
/**
* Return a string representation of this AABB.
*
* This method creates a new {@link DecimalFormat} on every invocation with the format string "0.000E0;-
".
*
* @return the string representation
*/
public String toString() {
return Runtime.formatNumbers(toString(Options.NUMBER_FORMAT));
}
/**
* Return a string representation of this AABB by formatting the vector components with the given {@link NumberFormat}.
*
* @param formatter
* the {@link NumberFormat} used to format the vector components with
* @return the string representation
*/
public String toString(NumberFormat formatter) {
return "(" + formatter.format(minX) + " " + formatter.format(minY) + " " + formatter.format(minZ) + ") < "
+ "(" + formatter.format(maxX) + " " + formatter.format(maxY) + " " + formatter.format(maxZ) + ")";
}
}