package org.jzy3d.maths;
import java.util.ArrayList;
import java.util.List;
import org.jzy3d.plot3d.primitives.Point;
import org.jzy3d.plot3d.primitives.Polygon;
import org.jzy3d.plot3d.transform.space.SpaceTransformer;
/**
* A BoundingBox3d stores a couple of maximal and minimal limit on each
* dimension (x, y, and z). It provides functions for enlarging the box by
* adding coordinates, Point3d, Polygon3d or an other BoundingBox3d (that is
* equivalent to computing the union of the current BoundingBox and another
* one).
* @author Martin Pernollet
*/
public class BoundingBox3d {
/**
* Initialize a BoundingBox by calling its reset method, leaving the box in
* an inconsitent state, with minimums = Float.MAX_VALUE and maximums =
* -Float.MAX_VALUE. In other words, calling box.valid() will return false.
*/
public BoundingBox3d() {
reset();
}
public BoundingBox3d(List coords) {
reset();
for (Coord3d c : coords)
add(c);
}
public BoundingBox3d(Polygon polygon) {
reset();
for (Point c : polygon.getPoints())
add(c);
}
public BoundingBox3d(Coord3d center, float edgeLength) {
this.xmin = center.x - edgeLength / 2;
this.xmax = center.x + edgeLength / 2;
this.ymin = center.y - edgeLength / 2;
this.ymax = center.y + edgeLength / 2;
this.zmin = center.z - edgeLength / 2;
this.zmax = center.z + edgeLength / 2;
}
public BoundingBox3d(BoundingBox3d box) {
this.xmin = box.xmin;
this.xmax = box.xmax;
this.ymin = box.ymin;
this.ymax = box.ymax;
this.zmin = box.zmin;
this.zmax = box.zmax;
}
/** Initialize a BoundingBox with raw values. */
public BoundingBox3d(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax) {
this.xmin = xmin;
this.xmax = xmax;
this.ymin = ymin;
this.ymax = ymax;
this.zmin = zmin;
this.zmax = zmax;
}
public BoundingBox3d(Range xRange, Range yRange, Range zRange) {
this.xmin = xRange.getMin();
this.xmax = xRange.getMax();
this.ymin = yRange.getMin();
this.ymax = yRange.getMax();
this.zmin = zRange.getMin();
this.zmax = zRange.getMax();
}
/*********************************************************/
/**
* Initialize the bounding box with Float.MAX_VALUE as minimum value, and
* -Float.MAX_VALUE as maximum value for each dimension.
*/
public void reset() {
xmin = Float.MAX_VALUE;
xmax = -Float.MAX_VALUE;
ymin = Float.MAX_VALUE;
ymax = -Float.MAX_VALUE;
zmin = Float.MAX_VALUE;
zmax = -Float.MAX_VALUE;
}
public boolean isReset() {
return xmin == Float.MAX_VALUE && xmax == -Float.MAX_VALUE && ymin == Float.MAX_VALUE && ymax == -Float.MAX_VALUE && zmin == Float.MAX_VALUE && zmax == -Float.MAX_VALUE;
}
public boolean valid() {
return (xmin <= xmax && ymin <= ymax && zmin <= zmax);
}
/**
* Adds an x,y,z point to the bounding box, and enlarge the bounding box if
* this points lies outside of it.
*
* @param x
* @param y
* @param z
*/
public void add(float x, float y, float z) {
if (x > xmax)
xmax = x;
if (x < xmin)
xmin = x;
if (y > ymax)
ymax = y;
if (y < ymin)
ymin = y;
if (z > zmax)
zmax = z;
if (z < zmin)
zmin = z;
}
/**
* Add a Coord3d to the BoundingBox3d. A shortcut for:
* add(c.x, c.y, c.z);
*
* @param p
*/
public void add(Coord3d c) {
add(c.x, c.y, c.z);
}
public void add(List pts) {
for (Point p : pts)
add(p.xyz.x, p.xyz.y, p.xyz.z);
}
/**
* Add a Point3d to the BoundingBox3d. A shortcut for:
* add(p.x, p.y, p.z);
*
* @param p
*/
public void add(Point p) {
add(p.xyz.x, p.xyz.y, p.xyz.z);
}
/**
* Add the points of a Polygon to the BoundingBox3d.
*
* @param p
*/
public void add(Polygon p) {
for (int i = 0; i < p.size(); i++)
add(p.get(i).xyz.x, p.get(i).xyz.y, p.get(i).xyz.z);
}
/**
* Add a BoundingBox3d volume to the current one. A convenient shortcut for:
*
* add(b.xmin, b.ymin, b.zmin);
* add(b.xmax, b.ymax, b.zmax);
*
*
* @param p
*/
public void add(BoundingBox3d b) {
add(b.xmin, b.ymin, b.zmin);
add(b.xmax, b.ymax, b.zmax);
}
/*********************************************************/
/**
* Compute and return the center point of the BoundingBox3d
*
* @return the center.
*/
public Coord3d getCenter() {
return new Coord3d((xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2);
}
public Coord3d getTransformedCenter(SpaceTransformer transformers) {
return new Coord3d((transformers.getX().compute(xmin) + transformers.getX().compute(xmax)) / 2, (transformers.getY().compute(ymin) + transformers.getY().compute(ymax)) / 2, (transformers.getZ().compute(zmin) + transformers.getZ().compute(zmax)) / 2);
}
/**
* Return the radius of the Sphere containing the Bounding Box, i.e., the
* distance between the center and the point (xmin, ymin, zmin).
*
* @return the box radius.
*/
public double getRadius() {
return getCenter().distance(new Coord3d(xmin, ymin, zmin));
}
public double getTransformedRadius(SpaceTransformer transformers) {
return getTransformedCenter(transformers).distance(transformers.compute(new Coord3d(xmin, ymin, zmin)));
}
/**
* Return a copy of the current bounding box after scaling. Scaling does not
* modify the current bounding box.
*
* @return the scaled bounding box
*/
public BoundingBox3d scale(Coord3d scale) {
BoundingBox3d b = new BoundingBox3d();
b.xmax = xmax * scale.x;
b.xmin = xmin * scale.x;
b.ymax = ymax * scale.y;
b.ymin = ymin * scale.y;
b.zmax = zmax * scale.z;
b.zmin = zmin * scale.z;
return b;
}
public BoundingBox3d shift(Coord3d offset) {
BoundingBox3d b = new BoundingBox3d();
b.xmax = xmax + offset.x;
b.xmin = xmin + offset.x;
b.ymax = ymax + offset.y;
b.ymin = ymin + offset.y;
b.zmax = zmax + offset.z;
b.zmin = zmin + offset.z;
return b;
}
/** Return true if b2 is contained by this. */
public boolean contains(BoundingBox3d b2) {
return xmin <= b2.xmin && b2.xmax <= xmax && ymin <= b2.ymin && b2.ymax <= ymax && zmin <= b2.zmin && b2.zmax <= zmax;
}
public boolean contains(Coord3d c) {
if (c.x < getXmin())
return false;
else if (c.x > getXmax())
return false;
else if (c.y < getYmin())
return false;
else if (c.y > getYmax())
return false;
else if (c.z < getZmin())
return false;
else if (c.z > getZmax())
return false;
return true;
}
/** Return true if intersect b2. */
public boolean intersect(BoundingBox3d b2) {
return xmin <= b2.xmin && b2.xmin <= xmax || xmin <= b2.xmax && b2.xmax <= xmax || ymin <= b2.ymin && b2.ymin <= ymax || ymin <= b2.ymax && b2.ymax <= ymax || zmin <= b2.zmin && b2.zmin <= zmax || zmin <= b2.zmax && b2.zmax <= zmax;
}
/*********************************************************/
public BoundingBox3d margin(float margin) {
BoundingBox3d b = new BoundingBox3d();
b.xmax = xmax + margin;
b.xmin = xmin + margin;
b.ymax = ymax + margin;
b.ymin = ymin + margin;
b.zmax = zmax + margin;
b.zmin = zmin + margin;
return b;
}
public BoundingBox3d selfMargin(float margin) {
xmax += margin;
xmin -= margin;
ymax += margin;
ymin -= margin;
zmax += margin;
zmin -= margin;
return this;
}
/*********************************************************/
public Range getXRange() {
return new Range(xmin, xmax);
}
public Range getYRange() {
return new Range(ymin, ymax);
}
public Range getZRange() {
return new Range(zmin, zmax);
}
public float getXmin() {
return xmin;
}
public void setXmin(float value) {
xmin = value;
}
public float getXmax() {
return xmax;
}
public void setXmax(float value) {
xmax = value;
}
public float getYmin() {
return ymin;
}
public void setYmin(float value) {
ymin = value;
}
public float getYmax() {
return ymax;
}
public void setYmax(float value) {
ymax = value;
}
public float getZmin() {
return zmin;
}
public void setZmin(float value) {
zmin = value;
}
public float getZmax() {
return zmax;
}
public void setZmax(float value) {
zmax = value;
}
public List getVertices() {
List edges = new ArrayList(8);
edges.add(new Coord3d(xmin, ymin, zmin));
edges.add(new Coord3d(xmin, ymax, zmin));
edges.add(new Coord3d(xmax, ymax, zmin));
edges.add(new Coord3d(xmax, ymin, zmin));
edges.add(new Coord3d(xmin, ymin, zmax));
edges.add(new Coord3d(xmin, ymax, zmax));
edges.add(new Coord3d(xmax, ymax, zmax));
edges.add(new Coord3d(xmax, ymin, zmax));
return edges;
}
/*********************************************************/
public static BoundingBox3d newBoundsAtOrigin() {
return new BoundingBox3d(Coord3d.ORIGIN, 0);
}
/*********************************************************/
@Override
public String toString() {
return toString(0);
}
public String toString(int depth) {
return Utils.blanks(depth) + "(BoundingBox3d)" + xmin + "<=x<=" + xmax + " | " + ymin + "<=y<=" + ymax + " | " + zmin + "<=z<=" + zmax;
}
/*********************************************************/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Float.floatToIntBits(xmax);
result = prime * result + Float.floatToIntBits(xmin);
result = prime * result + Float.floatToIntBits(ymax);
result = prime * result + Float.floatToIntBits(ymin);
result = prime * result + Float.floatToIntBits(zmax);
result = prime * result + Float.floatToIntBits(zmin);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof BoundingBox3d))
return false;
BoundingBox3d other = (BoundingBox3d) obj;
if (Float.floatToIntBits(xmax) != Float.floatToIntBits(other.xmax))
return false;
if (Float.floatToIntBits(xmin) != Float.floatToIntBits(other.xmin))
return false;
if (Float.floatToIntBits(ymax) != Float.floatToIntBits(other.ymax))
return false;
if (Float.floatToIntBits(ymin) != Float.floatToIntBits(other.ymin))
return false;
if (Float.floatToIntBits(zmax) != Float.floatToIntBits(other.zmax))
return false;
if (Float.floatToIntBits(zmin) != Float.floatToIntBits(other.zmin))
return false;
return true;
}
@Override
public BoundingBox3d clone(){
return new BoundingBox3d(xmin, xmax, ymin, ymax, zmin, zmax);
}
/* */
private float xmin;
private float xmax;
private float ymin;
private float ymax;
private float zmin;
private float zmax;
}
Ads help maintain this website.