📄 boundingsphere.java
字号:
/* * $RCSfile: BoundingSphere.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.7 $ * $Date: 2007/04/12 17:34:04 $ * $State: Exp $ */package javax.media.j3d;import javax.vecmath.*;import java.lang.Math;import com.sun.j3d.internal.HashCodeUtil;/** * This class defines a spherical bounding region which is defined by a * center point and a radius. */public class BoundingSphere extends Bounds { /** * The center of the bounding sphere. */ Point3d center; /** * The radius of the bounding sphere. */ double radius; Point3d boxVerts[]; boolean allocBoxVerts = false; // reusable temp objects private BoundingBox tmpBox = null; private BoundingPolytope tmpPolytope = null; /** * Constructs and initializes a BoundingSphere from a center and radius. * @param center the center of the bounding sphere * @param radius the radius of the bounding sphere */ public BoundingSphere(Point3d center, double radius) { this.center = new Point3d(center); this.radius = radius; boundId = BOUNDING_SPHERE; updateBoundsStates(); } /** * Constructs and initializes a BoundingSphere with radius = 1 at 0 0 0. */ public BoundingSphere() { boundId = BOUNDING_SPHERE; center = new Point3d(); radius = 1.0; } /** * Constructs and initializes a BoundingSphere from a bounding object. * @param boundsObject a bounds object */ public BoundingSphere(Bounds boundsObject) { int i; boundId = BOUNDING_SPHERE; if (boundsObject == null) { // Negative volume. center = new Point3d(); radius = -1.0; } else if( boundsObject.boundsIsInfinite ) { center = new Point3d(); radius = Double.POSITIVE_INFINITY; } else if( boundsObject.boundId == BOUNDING_BOX){ BoundingBox box = (BoundingBox)boundsObject; center = new Point3d(); center.x = (box.upper.x+box.lower.x)/2.0; center.y = (box.upper.y+box.lower.y)/2.0; center.z = (box.upper.z+box.lower.z)/2.0; radius = 0.5*(Math.sqrt((box.upper.x-box.lower.x)* (box.upper.x-box.lower.x)+ (box.upper.y-box.lower.y)* (box.upper.y-box.lower.y)+ (box.upper.z-box.lower.z)* (box.upper.z-box.lower.z))); } else if (boundsObject.boundId == BOUNDING_SPHERE) { BoundingSphere sphere = (BoundingSphere)boundsObject; center = new Point3d(sphere.center); radius = sphere.radius; } else if(boundsObject.boundId == BOUNDING_POLYTOPE) { BoundingPolytope polytope = (BoundingPolytope)boundsObject; double t,dis,dis_sq,rad_sq,oldc_to_new_c; center = new Point3d(); center.x = polytope.centroid.x; center.y = polytope.centroid.y; center.z = polytope.centroid.z; radius = Math.sqrt( (polytope.verts[0].x - center.x)* (polytope.verts[0].x - center.x) + (polytope.verts[0].y - center.y)* (polytope.verts[0].y - center.y) + (polytope.verts[0].z - center.z)* (polytope.verts[0].z - center.z)); for(i=1;i<polytope.nVerts;i++) { rad_sq = radius * radius; dis_sq = (polytope.verts[i].x - center.x)* (polytope.verts[i].x - center.x) + (polytope.verts[i].y - center.y)* (polytope.verts[i].y - center.y) + (polytope.verts[i].z - center.z)* (polytope.verts[i].z - center.z); // change sphere so one side passes through the point // and other passes through the old sphere if( dis_sq > rad_sq) { dis = Math.sqrt( dis_sq); radius = (radius + dis)*.5; oldc_to_new_c = dis - radius; t = oldc_to_new_c/dis; center.x = center.x + (polytope.verts[i].x - center.x)*t; center.y = center.y + (polytope.verts[i].y - center.y)*t; center.z = center.z + (polytope.verts[i].z - center.z)*t; } } } else { throw new IllegalArgumentException(J3dI18N.getString("BoundingSphere0")); } updateBoundsStates(); } /** * Constructs and initializes a BoundingSphere from an array of bounding objects. * @param boundsObjects an array of bounds objects */ public BoundingSphere(Bounds[] boundsObjects) { int i=0; double dis,t,d1; boundId = BOUNDING_SPHERE; center = new Point3d(); if( boundsObjects == null || boundsObjects.length <= 0 ) { // Negative volume. radius = -1.0; updateBoundsStates(); return; } // find first non empty bounds object while( boundsObjects[i] == null && i < boundsObjects.length) { i++; } if( i >= boundsObjects.length ) { // all bounds objects were empty // Negative volume. radius = -1.0; updateBoundsStates(); return; } this.set(boundsObjects[i++]); if(boundsIsInfinite) return; for(;i<boundsObjects.length;i++) { if( boundsObjects[i] == null ); // do nothing else if( boundsObjects[i].boundsIsEmpty); // do nothing else if( boundsObjects[i].boundsIsInfinite ) { radius = Double.POSITIVE_INFINITY; break; // We're done. } else if( boundsObjects[i].boundId == BOUNDING_BOX){ BoundingBox b = (BoundingBox)boundsObjects[i]; if( !allocBoxVerts){ boxVerts = new Point3d[8]; for(int j=0;j<8;j++)boxVerts[j] = new Point3d(); allocBoxVerts = true; } boxVerts[0].set(b.lower.x, b.lower.y, b.lower.z ); boxVerts[1].set(b.lower.x, b.upper.y, b.lower.z ); boxVerts[2].set(b.upper.x, b.lower.y, b.lower.z ); boxVerts[3].set(b.upper.x, b.upper.y, b.lower.z ); boxVerts[4].set(b.lower.x, b.lower.y, b.upper.z ); boxVerts[5].set(b.lower.x, b.upper.y, b.upper.z ); boxVerts[6].set(b.upper.x, b.lower.y, b.upper.z ); boxVerts[7].set(b.upper.x, b.upper.y, b.upper.z ); this.combine(boxVerts); } else if( boundsObjects[i].boundId == BOUNDING_SPHERE ) { BoundingSphere sphere = (BoundingSphere)boundsObjects[i]; dis = Math.sqrt( (center.x - sphere.center.x)* (center.x - sphere.center.x) + (center.y - sphere.center.y)* (center.y - sphere.center.y) + (center.z - sphere.center.z)* (center.z - sphere.center.z) ); if( radius > sphere.radius) { if( (dis+sphere.radius) > radius) { d1 = .5*(radius-sphere.radius+dis); t = d1/dis; radius = d1+sphere.radius; center.x = sphere.center.x + (center.x-sphere.center.x)*t; center.y = sphere.center.y + (center.y-sphere.center.y)*t; center.z = sphere.center.z + (center.z-sphere.center.z)*t; } }else { if( (dis+radius) <= sphere.radius) { center.x = sphere.center.x; center.y = sphere.center.y; center.z = sphere.center.z; radius = sphere.radius; }else { d1 = .5*(sphere.radius-radius+dis); t = d1/dis; radius = d1+radius; center.x = center.x + (sphere.center.x-center.x)*t; center.y = center.y + (sphere.center.y-center.y)*t; center.z = center.z + (sphere.center.z-center.z)*t; } } } else if(boundsObjects[i].boundId == BOUNDING_POLYTOPE) { BoundingPolytope polytope = (BoundingPolytope)boundsObjects[i]; this.combine(polytope.verts); } else { if( boundsObjects[i] != null ) throw new IllegalArgumentException(J3dI18N.getString("BoundingSphere0")); } } updateBoundsStates(); } /** * Returns the radius of this bounding sphere as a double. * @return the radius of the bounding sphere */ public double getRadius() { return radius; } /** * Sets the radius of this bounding sphere from a double. * @param r the new radius for the bounding sphere */ public void setRadius(double r) { radius = r; updateBoundsStates(); } /** * Returns the position of this bounding sphere as a point. * @param center a Point to receive the center of the bounding sphere */ public void getCenter(Point3d center) { center.x = this.center.x; center.y = this.center.y; center.z = this.center.z; } /** * Sets the position of this bounding sphere from a point. * @param center a Point defining the new center of the bounding sphere */ public void setCenter(Point3d center) { this.center.x = center.x; this.center.y = center.y; this.center.z = center.z; checkBoundsIsNaN(); } /** * Sets the value of this BoundingSphere. * @param boundsObject another bounds object */ public void set(Bounds boundsObject){ int i; if ((boundsObject == null) || boundsObject.boundsIsEmpty) { center.x = 0.0; center.y = 0.0; center.z = 0.0; radius = -1.0; } else if( boundsObject.boundsIsInfinite ) { center.x = 0.0; center.y = 0.0; center.z = 0.0; radius = Double.POSITIVE_INFINITY; } else if( boundsObject.boundId == BOUNDING_BOX){ BoundingBox box = (BoundingBox)boundsObject; center.x = (box.upper.x + box.lower.x )/2.0; center.y = (box.upper.y + box.lower.y )/2.0; center.z = (box.upper.z + box.lower.z )/2.0; radius = 0.5*Math.sqrt((box.upper.x-box.lower.x)* (box.upper.x-box.lower.x)+ (box.upper.y-box.lower.y)* (box.upper.y-box.lower.y)+ (box.upper.z-box.lower.z)* (box.upper.z-box.lower.z)); } else if( boundsObject.boundId == BOUNDING_SPHERE ) { BoundingSphere sphere = (BoundingSphere)boundsObject; radius = sphere.radius; center.x = sphere.center.x; center.y = sphere.center.y; center.z = sphere.center.z; } else if(boundsObject.boundId == BOUNDING_POLYTOPE) { BoundingPolytope polytope = (BoundingPolytope)boundsObject; double t,dis,dis_sq,rad_sq,oldc_to_new_c; center.x = polytope.centroid.x; center.y = polytope.centroid.y; center.z = polytope.centroid.z; radius = Math.sqrt((polytope.verts[0].x - center.x)* (polytope.verts[0].x - center.x) + (polytope.verts[0].y - center.y)* (polytope.verts[0].y - center.y) + (polytope.verts[0].z - center.z)* (polytope.verts[0].z - center.z)); for(i=1;i<polytope.nVerts;i++) { rad_sq = radius * radius; dis_sq = (polytope.verts[i].x - center.x)* (polytope.verts[i].x - center.x) + (polytope.verts[i].y - center.y)* (polytope.verts[i].y - center.y) + (polytope.verts[i].z - center.z)* (polytope.verts[i].z - center.z); // change sphere so one side passes through the point // and other passes through the old sphere if( dis_sq > rad_sq) { // point is outside sphere dis = Math.sqrt( dis_sq); radius = (radius + dis)*.5; oldc_to_new_c = dis - radius; t = oldc_to_new_c/dis; center.x = center.x + (polytope.verts[i].x - center.x)*t; center.y = center.y + (polytope.verts[i].y - center.y)*t; center.z = center.z + (polytope.verts[i].z - center.z)*t; } } } else { throw new IllegalArgumentException(J3dI18N.getString("BoundingSphere2")); } updateBoundsStates(); } /** * Creates a copy of the bounding sphere. * @return a BoundingSphere */ public Object clone() { return new BoundingSphere(this.center, this.radius); } /** * Indicates whether the specified <code>bounds</code> object is * equal to this BoundingSphere object. They are equal if the * specified <code>bounds</code> object is an instance of * BoundingSphere and all of the data * members of <code>bounds</code> are equal to the corresponding * data members in this BoundingSphere. * @param bounds the object with which the comparison is made. * @return true if this BoundingSphere is equal to <code>bounds</code>; * otherwise false * * @since Java 3D 1.2 */ public boolean equals(Object bounds) { try { BoundingSphere sphere = (BoundingSphere)bounds; return (center.equals(sphere.center) && radius == sphere.radius); } catch (NullPointerException e) { return false; } catch (ClassCastException e) { return false; } } /** * Returns a hash code value for this BoundingSphere object * based on the data values in this object. Two different * BoundingSphere objects with identical data values (i.e., * BoundingSphere.equals returns true) will return the same hash * code value. Two BoundingSphere objects with different data * members may return the same hash code value, although this is * not likely. * @return a hash code value for this BoundingSphere object. * * @since Java 3D 1.2 */ public int hashCode() { long bits = 1L; bits = 31L * bits + HashCodeUtil.doubleToLongBits(radius); bits = 31L * bits + HashCodeUtil.doubleToLongBits(center.x); bits = 31L * bits + HashCodeUtil.doubleToLongBits(center.y); bits = 31L * bits + HashCodeUtil.doubleToLongBits(center.z); return (int) (bits ^ (bits >> 32)); } /** * Combines this bounding sphere with a bounding object so that the * resulting bounding sphere encloses the original bounding sphere and the * given bounds object. * @param boundsObject another bounds object */ public void combine(Bounds boundsObject) { double t,dis,d1,u,l,x,y,z,oldc_to_new_c; BoundingSphere sphere; if((boundsObject == null) || (boundsObject.boundsIsEmpty) || (boundsIsInfinite)) return; if((boundsIsEmpty) || (boundsObject.boundsIsInfinite)) { this.set(boundsObject); return; } if( boundsObject.boundId == BOUNDING_BOX){ BoundingBox b = (BoundingBox)boundsObject; // start with point furthest from sphere u = b.upper.x-center.x;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -