com.sun.javafx.geom.BoxBounds Maven / Gradle / Ivy
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javafx.geom;
import com.sun.javafx.geom.transform.Affine3D;
/**
*
*/
public class BoxBounds extends BaseBounds {
// minimum x value of boundining box
private float minX;
// maximum x value of boundining box
private float maxX;
// minimum y value of boundining box
private float minY;
// maximum y value of boundining box
private float maxY;
// minimum z value of boundining box
private float minZ;
// maximum z value of boundining box
private float maxZ;
/**
* Create an axis aligned bounding box object, with an empty bounds
* where maxX < minX, maxY < minY and maxZ < minZ.
*/
public BoxBounds() {
minX = minY = minZ = 0.0f;
maxX = maxY = maxZ = -1.0f;
}
public BaseBounds copy() {
return new BoxBounds(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Creates an axis aligned bounding box based on the minX, minY, minZ, maxX, maxY,
* and maxZ values specified.
*/
public BoxBounds(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
setBounds(minX, minY, minZ, maxX, maxY, maxZ);
}
/**
* Creates an axis aligned bounding box as a copy of the specified
* BoxBounds object.
*/
public BoxBounds(BoxBounds other) {
setBounds(other);
}
public BoundsType getBoundsType() {
return BoundsType.BOX;
}
public boolean is2D() {
return (Affine3D.almostZero(minZ) && Affine3D.almostZero(maxZ));
}
/**
* Convenience function for getting the width of this bounds.
* The dimension along the X-Axis.
*/
public float getWidth() {
return maxX - minX;
}
/**
* Convenience function for getting the height of this bounds.
* The dimension along the Y-Axis.
*/
public float getHeight() {
return maxY - minY;
}
/**
* Convenience function for getting the depth of this bounds.
* The dimension along the Z-Axis.
*/
public float getDepth() {
return maxZ - minZ;
}
public float getMinX() {
return minX;
}
public void setMinX(float minX) {
this.minX = minX;
}
public float getMinY() {
return minY;
}
public void setMinY(float minY) {
this.minY = minY;
}
public float getMinZ() {
return minZ;
}
public void setMinZ(float minZ) {
this.minZ = minZ;
}
public float getMaxX() {
return maxX;
}
public void setMaxX(float maxX) {
this.maxX = maxX;
}
public float getMaxY() {
return maxY;
}
public void setMaxY(float maxY) {
this.maxY = maxY;
}
public float getMaxZ() {
return maxZ;
}
public void setMaxZ(float maxZ) {
this.maxZ = maxZ;
}
public Vec2f getMin(Vec2f min) {
if (min == null) {
min = new Vec2f();
}
min.x = minX;
min.y = minY;
return min;
}
public Vec2f getMax(Vec2f max) {
if (max == null) {
max = new Vec2f();
}
max.x = maxX;
max.y = maxY;
return max;
}
public Vec3f getMin(Vec3f min) {
if (min == null) {
min = new Vec3f();
}
min.x = minX;
min.y = minY;
min.z = minZ;
return min;
}
public Vec3f getMax(Vec3f max) {
if (max == null) {
max = new Vec3f();
}
max.x = maxX;
max.y = maxY;
max.z = maxZ;
return max;
}
public BaseBounds deriveWithUnion(BaseBounds other) {
if ((other.getBoundsType() == BoundsType.RECTANGLE) ||
(other.getBoundsType() == BoundsType.BOX)) {
unionWith(other);
} else {
throw new UnsupportedOperationException("Unknown BoundsType");
}
return this;
}
public BaseBounds deriveWithNewBounds(Rectangle other) {
if (other.width < 0 || other.height < 0) return makeEmpty();
setBounds(other.x, other.y, 0,
other.x + other.width, other.y + other.height, 0);
return this;
}
public BaseBounds deriveWithNewBounds(BaseBounds other) {
if (other.isEmpty()) return makeEmpty();
if ((other.getBoundsType() == BoundsType.RECTANGLE) ||
(other.getBoundsType() == BoundsType.BOX)) {
minX = other.getMinX();
minY = other.getMinY();
minZ = other.getMinZ();
maxX = other.getMaxX();
maxY = other.getMaxY();
maxZ = other.getMaxZ();
} else {
throw new UnsupportedOperationException("Unknown BoundsType");
}
return this;
}
public BaseBounds deriveWithNewBounds(float minX, float minY, float minZ,
float maxX, float maxY, float maxZ) {
if ((maxX < minX) || (maxY < minY) || (maxZ < minZ)) return makeEmpty();
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
return this;
}
public BaseBounds deriveWithNewBoundsAndSort(float minX, float minY, float minZ,
float maxX, float maxY, float maxZ) {
setBoundsAndSort(minX, minY, minZ, maxX, maxY, maxZ);
return this;
}
@Override public RectBounds flattenInto(RectBounds bounds) {
// Create the bounds if we need to
if (bounds == null) bounds = new RectBounds();
// Make it empty if we need to
if (isEmpty()) return bounds.makeEmpty();
// Populate it with values otherwise
bounds.setBounds(minX, minY, maxX, maxY);
return bounds;
}
/**
* Set the bounds to match that of the BaseBounds object specified. The
* specified bounds object must not be null.
*/
public final void setBounds(BaseBounds other) {
minX = other.getMinX();
minY = other.getMinY();
minZ = other.getMinZ();
maxX = other.getMaxX();
maxY = other.getMaxY();
maxZ = other.getMaxZ();
}
/**
* Set the bounds to the given values.
*/
public final void setBounds(float minX, float minY, float minZ,
float maxX, float maxY, float maxZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
public void setBoundsAndSort(float minX, float minY, float minZ,
float maxX, float maxY, float maxZ) {
setBounds(minX, minY, minZ, maxX, maxY, maxZ);
sortMinMax();
}
public void setBoundsAndSort(Point2D p1, Point2D p2) {
setBoundsAndSort(p1.x, p1.y, 0.0f, p2.x, p2.y, 0.0f);
}
public void unionWith(BaseBounds other) {
// Short circuit union if either bounds is empty.
if (other.isEmpty()) return;
if (this.isEmpty()) {
setBounds(other);
return;
}
minX = Math.min(minX, other.getMinX());
minY = Math.min(minY, other.getMinY());
minZ = Math.min(minZ, other.getMinZ());
maxX = Math.max(maxX, other.getMaxX());
maxY = Math.max(maxY, other.getMaxY());
maxZ = Math.max(maxZ, other.getMaxZ());
}
public void unionWith(float minX, float minY, float minZ,
float maxX, float maxY, float maxZ) {
// Short circuit union if either bounds is empty.
if ((maxX < minX) || (maxY < minY) || (maxZ < minZ)) return;
if (this.isEmpty()) {
setBounds(minX, minY, minZ, maxX, maxY, maxZ);
return;
}
this.minX = Math.min(this.minX, minX);
this.minY = Math.min(this.minY, minY);
this.minZ = Math.min(this.minZ, minZ);
this.maxX = Math.max(this.maxX, maxX);
this.maxY = Math.max(this.maxY, maxY);
this.maxZ = Math.max(this.maxZ, maxZ);
}
public void add(float x, float y, float z) {
unionWith(x, y, z, x, y, z);
}
public void add(Point2D p) {
add(p.x, p.y, 0.0f);
}
public void intersectWith(Rectangle other) {
float x = other.x;
float y = other.y;
intersectWith(x, y, 0,
x + other.width, y + other.height, 0);
}
public void intersectWith(BaseBounds other) {
// Short circuit intersect if either bounds is empty.
if (this.isEmpty()) return;
if (other.isEmpty()) {
makeEmpty();
return;
}
minX = Math.max(minX, other.getMinX());
minY = Math.max(minY, other.getMinY());
minZ = Math.max(minZ, other.getMinZ());
maxX = Math.min(maxX, other.getMaxX());
maxY = Math.min(maxY, other.getMaxY());
maxZ = Math.min(maxZ, other.getMaxZ());
}
public void intersectWith(float minX, float minY, float minZ,
float maxX, float maxY, float maxZ) {
// Short circuit intersect if either bounds is empty.
if (this.isEmpty()) return;
if ((maxX < minX) || (maxY < minY) || (maxZ < minZ)) {
makeEmpty();
return;
}
this.minX = Math.max(this.minX, minX);
this.minY = Math.max(this.minY, minY);
this.minZ = Math.max(this.minZ, minZ);
this.maxX = Math.min(this.maxX, maxX);
this.maxY = Math.min(this.maxY, maxY);
this.maxZ = Math.min(this.maxZ, maxZ);
}
public boolean contains(Point2D p) {
if ((p == null) || isEmpty()) return false;
return contains(p.x, p.y, 0.0f);
}
public boolean contains(float x, float y) {
if (isEmpty()) return false;
return contains(x, y, 0.0f);
}
public boolean contains(float x, float y, float z) {
if (isEmpty()) return false;
return (x >= minX && x <= maxX && y >= minY && y <= maxY
&& z >= minZ && z <= maxZ);
}
public boolean contains(float x, float y, float z,
float width, float height, float depth) {
if (isEmpty()) return false;
return contains(x, y, z) && contains(x+width, y+height, z+depth);
}
public boolean intersects(float x, float y, float width, float height) {
return intersects(x, y, 0.0f, width, height, 0.0f);
}
public boolean intersects(float x, float y, float z,
float width, float height, float depth) {
if (isEmpty()) return false;
return (x + width >= minX &&
y + height >= minY &&
z + depth >= minZ &&
x <= maxX &&
y <= maxY &&
z <= maxZ);
}
public boolean intersects(BaseBounds other) {
if ((other == null) || other.isEmpty() || isEmpty()) {
return false;
}
return (other.getMaxX() >= minX &&
other.getMaxY() >= minY &&
other.getMaxZ() >= minZ &&
other.getMinX() <= maxX &&
other.getMinY() <= maxY &&
other.getMinZ() <= maxZ);
}
public boolean disjoint(float x, float y, float width, float height) {
return disjoint(x, y, 0f, width, height, 0f);
}
public boolean disjoint(float x, float y, float z,
float width, float height, float depth) {
if (isEmpty()) return true;
return (x + width < minX ||
y + height < minY ||
z + depth < minZ ||
x > maxX ||
y > maxY ||
z > maxZ);
}
public boolean isEmpty() {
return maxX < minX || maxY < minY || maxZ < minZ;
}
/**
* Adjusts the edges of this BoxBounds "outward" toward integral boundaries,
* such that the rounded bounding box will always full enclose the original
* bounding box.
*/
public void roundOut() {
minX = (float) Math.floor(minX);
minY = (float) Math.floor(minY);
minZ = (float) Math.floor(minZ);
maxX = (float) Math.ceil(maxX);
maxY = (float) Math.ceil(maxY);
maxZ = (float) Math.ceil(maxZ);
}
public void grow(float h, float v, float d) {
minX -= h;
maxX += h;
minY -= v;
maxY += v;
minZ -= d;
maxZ += d;
}
public BaseBounds deriveWithPadding(float h, float v, float d) {
grow(h, v, d);
return this;
}
// for convenience, this function returns a reference to itself, so we can
// change from using "bounds.makeEmpty(); return bounds;" to just
// "return bounds.makeEmpty()"
public BoxBounds makeEmpty() {
minX = minY = minZ = 0.0f;
maxX = maxY = maxZ = -1.0f;
return this;
}
protected void sortMinMax() {
if (minX > maxX) {
float tmp = maxX;
maxX = minX;
minX = tmp;
}
if (minY > maxY) {
float tmp = maxY;
maxY = minY;
minY = tmp;
}
if (minZ > maxZ) {
float tmp = maxZ;
maxZ = minZ;
minZ = tmp;
}
}
@Override
public void translate(float x, float y, float z) {
setMinX(getMinX() + x);
setMinY(getMinY() + y);
setMaxX(getMaxX() + x);
setMaxY(getMaxY() + y);
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final BoxBounds other = (BoxBounds) obj;
if (minX != other.getMinX()) return false;
if (minY != other.getMinY()) return false;
if (minZ != other.getMinZ()) return false;
if (maxX != other.getMaxX()) return false;
if (maxY != other.getMaxY()) return false;
if (maxZ != other.getMaxZ()) return false;
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + Float.floatToIntBits(minX);
hash = 79 * hash + Float.floatToIntBits(minY);
hash = 79 * hash + Float.floatToIntBits(minZ);
hash = 79 * hash + Float.floatToIntBits(maxX);
hash = 79 * hash + Float.floatToIntBits(maxY);
hash = 79 * hash + Float.floatToIntBits(maxZ);
return hash;
}
@Override
public String toString() {
return "BoxBounds { minX:" + minX + ", minY:" + minY + ", minZ:" + minZ + ", maxX:" + maxX + ", maxY:" + maxY + ", maxZ:" + maxZ + "}";
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy