/** * Returns a new empty bounding sphere. * @return a new empty bounding sphere. */ public static BoundingSphere empty() { return new BoundingSphere(); }
/** * Determines whether this sphere contains the specified point. * @param p the point. * @return true, if this sphere contains the point; false, otherwise. */ public boolean contains(Point3 p) { return contains(p.x,p.y,p.z); }
/** * Gets the bounding sphere for this constraint. * @return the bounding sphere. */ public BoundingSphere getBoundingSphere() { BoundingSphere bs = new BoundingSphere(); bs.expandBy(getBoundingBox()); return bs; }
/** * Returns a new infinite bounding sphere. * @return a new infinite bounding sphere. */ public static BoundingSphere infinite() { BoundingSphere bs = new BoundingSphere(); bs.setInfinite(); return bs; }
/** * Determines whether this sphere contains a point with specified coordinates. * @param x the point x coordinate. * @param y the point y coordinate. * @param z the point z coordinate. * @return true, if this sphere contains the point; false, otherwise. */ public boolean contains(double x, double y, double z) { if (isEmpty()) return false; if (isInfinite()) return true; double dx = _x-x; double dy = _y-y; double dz = _z-z; double rs = _r*_r; return dx*dx+dy*dy+dz*dz<=rs; }
/** * Expands this box to include the specified bounding sphere. * @param bs the bounding sphere. */ public void expandBy(BoundingSphere bs) { if (!bs.isInfinite()) { if (!bs.isEmpty()) { double r = bs.getRadius(); Point3 c = bs.getCenter(); double x = c.x; double y = c.y; double z = c.z; if (_xmin>x-r) _xmin = x-r; if (_ymin>y-r) _ymin = y-r; if (_zmin>z-r) _zmin = z-r; if (_xmax<x+r) _xmax = x+r; if (_ymax<y+r) _ymax = y+r; if (_zmax<z+r) _zmax = z+r; } } else { setInfinite(); } }
public void testSphereExpand() { int ntrial = 100; for (int itrial=0; itrial<ntrial; ++itrial) { BoundingSphere bs = new BoundingSphere(); assertTrue(bs.isEmpty()); int nexpand = 100; for (int iexpand=0; iexpand<nexpand; ++iexpand) { Point3 p = randomPoint3(); Point3 q = randomPoint3(); BoundingBox bb = new BoundingBox(p,q); if (randomDouble()>0.5) { bs.expandBy(bb); } else { bs.expandRadiusBy(bb); } assertTrue(!bs.isEmpty()); int npoint=100; for (int ipoint=0; ipoint<npoint; ++ipoint) { Point3 r = randomPoint3(); if (bb.contains(r)) assertTrue(bs.contains(r)); } } } }
/** * Computes the bounding sphere for this group, including its children. * @param finite true, to force bounding sphere to be finite. * @return the computed bounding sphere. */ protected BoundingSphere computeBoundingSphere(boolean finite) { if (countChildren()==1) { return _childList.get(0).getBoundingSphere(finite); } else { BoundingBox bb = new BoundingBox(); for (Node child : _childList) bb.expandBy(child.getBoundingSphere(finite)); if (bb.isEmpty()) return BoundingSphere.empty(); if (bb.isInfinite()) // should not happen if finite == true return BoundingSphere.infinite(); BoundingSphere bs = new BoundingSphere(bb.getCenter(),0.0); for (Node child : _childList) bs.expandRadiusBy(child.getBoundingSphere(finite)); return bs; } }
public void testSphere() { BoundingSphere bs = new BoundingSphere(); bs.expandBy(0,0,0); bs.expandBy(1,1,1); double a = 10.0*DBL_EPSILON; double b = 1.0-a; assertTrue(bs.contains(new Point3(a,a,a))); assertTrue(bs.contains(new Point3(a,a,b))); assertTrue(bs.contains(new Point3(a,b,a))); assertTrue(bs.contains(new Point3(a,b,b))); assertTrue(bs.contains(new Point3(b,a,a))); assertTrue(bs.contains(new Point3(b,a,b))); assertTrue(bs.contains(new Point3(b,b,a))); assertTrue(bs.contains(new Point3(b,b,b))); a = -10.0*DBL_EPSILON; b = 1.0-a; assertTrue(!bs.contains(new Point3(a,a,a))); assertTrue(!bs.contains(new Point3(a,a,b))); assertTrue(!bs.contains(new Point3(a,b,a))); assertTrue(!bs.contains(new Point3(a,b,b))); assertTrue(!bs.contains(new Point3(b,a,a))); assertTrue(!bs.contains(new Point3(b,a,b))); assertTrue(!bs.contains(new Point3(b,b,a))); assertTrue(!bs.contains(new Point3(b,b,b))); }
/** * Expands this sphere to include the specified bounding sphere. * Changes only the radius, if necessary, not the center of this sphere. * @param bs the bounding sphere. */ public void expandRadiusBy(BoundingSphere bs) { if (!isInfinite()) { if (!bs.isInfinite()) { if (!bs.isEmpty()) { if (!isEmpty()) { double dx = bs._x-_x; double dy = bs._y-_y; double dz = bs._z-_z; double d = sqrt(dx*dx+dy*dy+dz*dz); double r = d+bs._r; if (r>_r) _r = r; } else { _r = bs._r; _x = bs._x; _y = bs._y; _z = bs._z; } } } else { setInfinite(); } } }
if (!isInfinite()) { if (!bb.isInfinite()) { if (!bb.isEmpty()) { double ymax = pmax.y; double zmax = pmax.z; if (!isEmpty()) { for (int i=0; i<8; ++i) { double x = ((i&1)==0)?xmin:xmax; double y = ((i&2)==0)?ymin:ymax; double z = ((i&4)==0)?zmin:zmax; expandRadiusBy(x,y,z); setInfinite();
public void testBoxExpand() { int ntrial = 100; for (int itrial=0; itrial<ntrial; ++itrial) { BoundingBox bb = new BoundingBox(); assertTrue(bb.isEmpty()); int nexpand = 100; for (int iexpand=0; iexpand<nexpand; ++iexpand) { Point3 c = randomPoint3(); double r = randomDouble(); BoundingSphere bs = new BoundingSphere(c,r); bb.expandBy(bs); assertTrue(!bb.isEmpty()); int npoint=100; for (int ipoint=0; ipoint<npoint; ++ipoint) { Point3 p = randomPoint3(); if (bs.contains(p)) assertTrue(bb.contains(p)); } } } }
/** * Gets the sphere radius. * @return the radius. */ public double getRadius() { Check.state(!isEmpty(),"bounding sphere is not empty"); return _r; }
/** * Expands this sphere to include the specified point. * Adjusts the sphere center to minimize any increase in radius. * @param p the point. */ public void expandBy(Point3 p) { expandBy(p.x,p.y,p.z); }
/** * Computes the bounding sphere for this node, including its children. * This method is called by {@link #getBoundingSphere(boolean)} when this * node's bounding sphere is dirty. * <p> * If a finite bounding sphere is specified, then any infinite bounding * sphere is replaced by an empty bounding sphere, so that the returned * sphere is always finite. * <p> * Classes that extend this abstract base class should override this * implementation, which simply returns an empty or infinite bounding * sphere, depending on whether or not a finite sphere is requested. * @param finite true, to force bounding sphere to be finite. * @return the computed bounding sphere. */ protected BoundingSphere computeBoundingSphere(boolean finite) { return (finite)?BoundingSphere.empty():BoundingSphere.infinite(); }
/** * Expands this sphere to include the specified point. * Changes only the radius, if necessary, not the center of this sphere. * @param p the point. */ public void expandRadiusBy(Point3 p) { expandRadiusBy(p.x,p.y,p.z); }
/** * Computes the transform matrix for this handle in the specified context. * The context is view-dependent, as is the computed transform matrix. * This matrix includes the view-dependent scaling required for the * handle to have the correct size in pixels. * @param tc the transform context. * @return the transform matrix for this handle. */ private Matrix44 computeTransform(TransformContext tc) { View view = tc.getView(); Tuple3 as = view.getAxesScale(); Matrix44 localToPixel = tc.getLocalToPixel().times(_transform); Matrix44 pixelToLocal = localToPixel.inverse(); Point3 p = new Point3(0.0,0.0,0.0); Point3 q = localToPixel.times(p); q.x += getSize(); q = pixelToLocal.times(q); double dx = (q.x-p.x)*as.x; double dy = (q.y-p.y)*as.y; double dz = (q.z-p.z)*as.z; double d = Math.sqrt(dx*dx+dy*dy+dz*dz); double r = _boundingSphereChildren.getRadius(); double s = d/r; double sx = s/as.x; double sy = s/as.y; double sz = s/as.z; return _transform.times(Matrix44.scale(sx,sy,sz)); } }
/** * Determines whether the view frustrum intersects the bounding sphere * of the specified node. * @param node the node with a bounding sphere. * @return true, if the view frustum intersects the bounding sphere; * false, otherwise. */ public boolean frustumIntersectsSphereOf(Node node) { if (_active!=0) { // if at least one frustum plane is active, ... BoundingSphere bs = node.getBoundingSphere(false); if (bs.isEmpty()) return false; if (bs.isInfinite()) return true; Point3 c = bs.getCenter(); double r = bs.getRadius(); double s = -r; for (int i=0,plane=1; i<6; ++i,plane<<=1) { // for all six planes if ((_active&plane)!=0) { // if plane is active double d = _planes[i].distanceTo(c); // distance from center if (d<s) { // if sphere is entirely outside (below plane) return false; // no intersection } else if (d>r) { // else if sphere is entirely above plane _active ^= plane; // need not test this plane again } } } } return true; }