/*
 * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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 + "}"; } }