Source Code Cross Referenced for BoundingBox.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: BoundingBox.java,v $
0003:         *
0004:         * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.10 $
0028:         * $Date: 2008/02/28 20:17:19 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import javax.vecmath.*;
0035:        import com.sun.j3d.internal.HashCodeUtil;
0036:
0037:        /**
0038:         *  This class defines an axis aligned bounding box which is used for
0039:         *  bounding regions.
0040:         *
0041:         */
0042:
0043:        public class BoundingBox extends Bounds {
0044:
0045:            /**
0046:             * The corner of the bounding box with the numerically smallest
0047:             * values.
0048:             */
0049:            Point3d lower;
0050:
0051:            /**
0052:             * The corner of the bounding box with the numerically largest
0053:             * values.
0054:             */
0055:            Point3d upper;
0056:
0057:            private Point3d centroid = null;
0058:            private static final double EPS = 1.0E-8;
0059:
0060:            // reusable temp objects
0061:            private BoundingSphere tmpSphere = null;
0062:            private BoundingBox tmpBox = null;
0063:            private BoundingPolytope tmpPolytope = null;
0064:            private Point3d tmpP3d = null;
0065:
0066:            /**
0067:             * Constructs and initializes a BoundingBox given min,max in x,y,z.
0068:             * @param lower the "small" corner
0069:             * @param upper the "large" corner
0070:             */
0071:            public BoundingBox(Point3d lower, Point3d upper) {
0072:                boundId = BOUNDING_BOX;
0073:                this .lower = new Point3d(lower);
0074:                this .upper = new Point3d(upper);
0075:                updateBoundsStates();
0076:            }
0077:
0078:            /**
0079:             * Constructs and initializes a 2X bounding box about the
0080:             * origin. The lower corner is initialized to (-1.0d, -1.0d, -1.0d)
0081:             * and the opper corner is initialized to (1.0d, 1.0d, 1.0d).
0082:             */
0083:            public BoundingBox() {
0084:                boundId = BOUNDING_BOX;
0085:                lower = new Point3d(-1.0d, -1.0d, -1.0d);
0086:                upper = new Point3d(1.0d, 1.0d, 1.0d);
0087:                updateBoundsStates();
0088:            }
0089:
0090:            /**
0091:             * Constructs a BoundingBox from a  bounding object. 
0092:             * @param boundsObject  a bounds object 
0093:             */
0094:            public BoundingBox(Bounds boundsObject) {
0095:                int i;
0096:                boundId = BOUNDING_BOX;
0097:                if (boundsObject == null) {
0098:                    // Negative volume.
0099:                    lower = new Point3d(1.0d, 1.0d, 1.0d);
0100:                    upper = new Point3d(-1.0d, -1.0d, -1.0d);
0101:                } else if (boundsObject.boundsIsInfinite) {
0102:                    lower = new Point3d(Double.NEGATIVE_INFINITY,
0103:                            Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
0104:                    upper = new Point3d(Double.POSITIVE_INFINITY,
0105:                            Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
0106:                } else if (boundsObject.boundId == BOUNDING_BOX) {
0107:                    BoundingBox box = (BoundingBox) boundsObject;
0108:
0109:                    lower = new Point3d(box.lower.x, box.lower.y, box.lower.z);
0110:                    upper = new Point3d(box.upper.x, box.upper.y, box.upper.z);
0111:
0112:                } else if (boundsObject.boundId == BOUNDING_SPHERE) {
0113:                    BoundingSphere sphere = (BoundingSphere) boundsObject;
0114:
0115:                    lower = new Point3d(sphere.center.x - sphere.radius,
0116:                            sphere.center.y - sphere.radius, sphere.center.z
0117:                                    - sphere.radius);
0118:
0119:                    upper = new Point3d(sphere.center.x + sphere.radius,
0120:                            sphere.center.y + sphere.radius, sphere.center.z
0121:                                    + sphere.radius);
0122:
0123:                } else if (boundsObject.boundId == BOUNDING_POLYTOPE) {
0124:                    BoundingPolytope polytope = (BoundingPolytope) boundsObject;
0125:                    if (polytope.nVerts < 1) { // handle degenerate case
0126:                        lower = new Point3d(-1.0d, -1.0d, -1.0d);
0127:                        upper = new Point3d(1.0d, 1.0d, 1.0d);
0128:                    } else {
0129:                        lower = new Point3d(polytope.verts[0].x,
0130:                                polytope.verts[0].y, polytope.verts[0].z);
0131:                        upper = new Point3d(polytope.verts[0].x,
0132:                                polytope.verts[0].y, polytope.verts[0].z);
0133:
0134:                        for (i = 1; i < polytope.nVerts; i++) {
0135:                            if (polytope.verts[i].x < lower.x)
0136:                                lower.x = polytope.verts[i].x;
0137:                            if (polytope.verts[i].y < lower.y)
0138:                                lower.y = polytope.verts[i].y;
0139:                            if (polytope.verts[i].z < lower.z)
0140:                                lower.z = polytope.verts[i].z;
0141:                            if (polytope.verts[i].x > upper.x)
0142:                                upper.x = polytope.verts[i].x;
0143:                            if (polytope.verts[i].y > upper.y)
0144:                                upper.y = polytope.verts[i].y;
0145:                            if (polytope.verts[i].z > upper.z)
0146:                                upper.z = polytope.verts[i].z;
0147:                        }
0148:                    }
0149:
0150:                } else {
0151:                    throw new IllegalArgumentException(J3dI18N
0152:                            .getString("BoundingBox0"));
0153:                }
0154:
0155:                updateBoundsStates();
0156:            }
0157:
0158:            /**
0159:             * Constructs a BoundingBox from an array of bounding objects. 
0160:             * @param bounds an array of bounding objects
0161:             */
0162:            public BoundingBox(Bounds[] bounds) {
0163:                int i = 0;
0164:
0165:                upper = new Point3d();
0166:                lower = new Point3d();
0167:                boundId = BOUNDING_BOX;
0168:
0169:                if (bounds == null || bounds.length <= 0) {
0170:                    // Negative volume.
0171:                    lower = new Point3d(1.0d, 1.0d, 1.0d);
0172:                    upper = new Point3d(-1.0d, -1.0d, -1.0d);
0173:                    updateBoundsStates();
0174:                    return;
0175:                }
0176:
0177:                // find first non empty bounds object
0178:                while (bounds[i] == null && i < bounds.length) {
0179:                    i++;
0180:                }
0181:
0182:                if (i >= bounds.length) { // all bounds objects were empty
0183:                    // Negative volume.
0184:                    lower = new Point3d(1.0d, 1.0d, 1.0d);
0185:                    upper = new Point3d(-1.0d, -1.0d, -1.0d);
0186:                    updateBoundsStates();
0187:                    return;
0188:                }
0189:
0190:                this .set(bounds[i++]);
0191:                if (boundsIsInfinite)
0192:                    return;
0193:
0194:                for (; i < bounds.length; i++) {
0195:                    if (bounds[i] == null)
0196:                        ; // do nothing
0197:                    else if (bounds[i].boundsIsEmpty)
0198:                        ; // do nothing
0199:                    else if (bounds[i].boundsIsInfinite) {
0200:                        lower.x = lower.y = lower.z = Double.NEGATIVE_INFINITY;
0201:                        upper.x = upper.y = upper.z = Double.POSITIVE_INFINITY;
0202:                        break; // We're done.
0203:                    } else if (bounds[i].boundId == BOUNDING_BOX) {
0204:                        BoundingBox box = (BoundingBox) bounds[i];
0205:
0206:                        if (lower.x > box.lower.x)
0207:                            lower.x = box.lower.x;
0208:                        if (lower.y > box.lower.y)
0209:                            lower.y = box.lower.y;
0210:                        if (lower.z > box.lower.z)
0211:                            lower.z = box.lower.z;
0212:                        if (upper.x < box.upper.x)
0213:                            upper.x = box.upper.x;
0214:                        if (upper.y < box.upper.y)
0215:                            upper.y = box.upper.y;
0216:                        if (upper.z < box.upper.z)
0217:                            upper.z = box.upper.z;
0218:
0219:                    } else if (bounds[i].boundId == BOUNDING_SPHERE) {
0220:                        BoundingSphere sphere = (BoundingSphere) bounds[i];
0221:                        if (lower.x > (sphere.center.x - sphere.radius))
0222:                            lower.x = sphere.center.x - sphere.radius;
0223:                        if (lower.y > (sphere.center.y - sphere.radius))
0224:                            lower.y = sphere.center.y - sphere.radius;
0225:                        if (lower.z > (sphere.center.z - sphere.radius))
0226:                            lower.z = sphere.center.z - sphere.radius;
0227:                        if (upper.x < (sphere.center.x + sphere.radius))
0228:                            upper.x = sphere.center.x + sphere.radius;
0229:                        if (upper.y < (sphere.center.y + sphere.radius))
0230:                            upper.y = sphere.center.y + sphere.radius;
0231:                        if (upper.z < (sphere.center.z + sphere.radius))
0232:                            upper.z = sphere.center.z + sphere.radius;
0233:                    } else if (bounds[i].boundId == BOUNDING_POLYTOPE) {
0234:                        BoundingPolytope polytope = (BoundingPolytope) bounds[i];
0235:
0236:                        for (i = 0; i < polytope.nVerts; i++) { // XXXX: handle polytope with no verts
0237:                            if (polytope.verts[i].x < lower.x)
0238:                                lower.x = polytope.verts[i].x;
0239:                            if (polytope.verts[i].y < lower.y)
0240:                                lower.y = polytope.verts[i].y;
0241:                            if (polytope.verts[i].z < lower.z)
0242:                                lower.z = polytope.verts[i].z;
0243:                            if (polytope.verts[i].x > upper.x)
0244:                                upper.x = polytope.verts[i].x;
0245:                            if (polytope.verts[i].y > upper.y)
0246:                                upper.y = polytope.verts[i].y;
0247:                            if (polytope.verts[i].z > upper.z)
0248:                                upper.z = polytope.verts[i].z;
0249:                        }
0250:                    } else {
0251:                        throw new IllegalArgumentException(J3dI18N
0252:                                .getString("BoundingBox1"));
0253:                    }
0254:                }
0255:                updateBoundsStates();
0256:            }
0257:
0258:            /**
0259:             * Gets the lower corner of this bounding box.
0260:             * @param p1 a Point to receive the lower corner of the bounding box
0261:             */
0262:            public void getLower(Point3d p1) {
0263:                p1.x = lower.x;
0264:                p1.y = lower.y;
0265:                p1.z = lower.z;
0266:            }
0267:
0268:            /**
0269:             * Sets the lower corner of this bounding box.
0270:             * @param xmin minimum x value of boundining box
0271:             * @param ymin minimum y value of boundining box
0272:             * @param zmin minimum z value of boundining box
0273:             */
0274:            public void setLower(double xmin, double ymin, double zmin) {
0275:                lower.x = xmin;
0276:                lower.y = ymin;
0277:                lower.z = zmin;
0278:
0279:                updateBoundsStates();
0280:            }
0281:
0282:            /**
0283:             * Sets the lower corner of this bounding box.
0284:             * @param p1 a Point defining the new lower corner of the bounding box
0285:             */
0286:            public void setLower(Point3d p1) {
0287:
0288:                lower.x = p1.x;
0289:                lower.y = p1.y;
0290:                lower.z = p1.z;
0291:
0292:                updateBoundsStates();
0293:            }
0294:
0295:            /**
0296:             * Gets the upper corner of this bounding box.
0297:             * @param p1 a Point to receive the upper corner of the bounding box
0298:             */
0299:            public void getUpper(Point3d p1) {
0300:                p1.x = upper.x;
0301:                p1.y = upper.y;
0302:                p1.z = upper.z;
0303:            }
0304:
0305:            /**
0306:             * Sets the upper corner of this bounding box.
0307:             * @param xmax max x value of boundining box
0308:             * @param ymax max y value of boundining box
0309:             * @param zmax max z value of boundining box
0310:             */
0311:            public void setUpper(double xmax, double ymax, double zmax) {
0312:                upper.x = xmax;
0313:                upper.y = ymax;
0314:                upper.z = zmax;
0315:
0316:                updateBoundsStates();
0317:            }
0318:
0319:            /**
0320:             * Sets the upper corner of this bounding box.
0321:             * @param p1 a Point defining the new upper corner of the bounding box
0322:             */
0323:            public void setUpper(Point3d p1) {
0324:                upper.x = p1.x;
0325:                upper.y = p1.y;
0326:                upper.z = p1.z;
0327:
0328:                updateBoundsStates();
0329:            }
0330:
0331:            /**
0332:             * Sets the the value of this BoundingBox
0333:             * @param boundsObject another bounds object
0334:             */
0335:            public void set(Bounds boundsObject) {
0336:                int i;
0337:
0338:                if ((boundsObject == null) || (boundsObject.boundsIsEmpty)) {
0339:                    // Negative volume.
0340:                    lower.x = lower.y = lower.z = 1.0d;
0341:                    upper.x = upper.y = upper.z = -1.0d;
0342:
0343:                } else if (boundsObject.boundsIsInfinite) {
0344:                    lower.x = lower.y = lower.z = Double.NEGATIVE_INFINITY;
0345:                    upper.x = upper.y = upper.z = Double.POSITIVE_INFINITY;
0346:
0347:                } else if (boundsObject.boundId == BOUNDING_BOX) {
0348:                    BoundingBox box = (BoundingBox) boundsObject;
0349:
0350:                    lower.x = box.lower.x;
0351:                    lower.y = box.lower.y;
0352:                    lower.z = box.lower.z;
0353:                    upper.x = box.upper.x;
0354:                    upper.y = box.upper.y;
0355:                    upper.z = box.upper.z;
0356:
0357:                } else if (boundsObject.boundId == BOUNDING_SPHERE) {
0358:                    BoundingSphere sphere = (BoundingSphere) boundsObject;
0359:                    lower.x = sphere.center.x - sphere.radius;
0360:                    lower.y = sphere.center.y - sphere.radius;
0361:                    lower.z = sphere.center.z - sphere.radius;
0362:                    upper.x = sphere.center.x + sphere.radius;
0363:                    upper.y = sphere.center.y + sphere.radius;
0364:                    upper.z = sphere.center.z + sphere.radius;
0365:
0366:                } else if (boundsObject.boundId == BOUNDING_POLYTOPE) {
0367:                    BoundingPolytope polytope = (BoundingPolytope) boundsObject;
0368:                    lower.x = upper.x = polytope.verts[0].x;
0369:                    lower.y = upper.y = polytope.verts[0].y;
0370:                    lower.z = upper.z = polytope.verts[0].z;
0371:
0372:                    for (i = 1; i < polytope.nVerts; i++) {
0373:                        if (polytope.verts[i].x < lower.x)
0374:                            lower.x = polytope.verts[i].x;
0375:                        if (polytope.verts[i].y < lower.y)
0376:                            lower.y = polytope.verts[i].y;
0377:                        if (polytope.verts[i].z < lower.z)
0378:                            lower.z = polytope.verts[i].z;
0379:                        if (polytope.verts[i].x > upper.x)
0380:                            upper.x = polytope.verts[i].x;
0381:                        if (polytope.verts[i].y > upper.y)
0382:                            upper.y = polytope.verts[i].y;
0383:                        if (polytope.verts[i].z > upper.z)
0384:                            upper.z = polytope.verts[i].z;
0385:                    }
0386:
0387:                } else {
0388:                    throw new IllegalArgumentException(J3dI18N
0389:                            .getString("BoundingBox0"));
0390:                }
0391:
0392:                updateBoundsStates();
0393:            }
0394:
0395:            /**
0396:             * Creates a copy of this bounding box.
0397:             * @return a new bounding box 
0398:             */
0399:            public Object clone() {
0400:                return new BoundingBox(this .lower, this .upper);
0401:            }
0402:
0403:            /**
0404:             * Indicates whether the specified <code>bounds</code> object is
0405:             * equal to this BoundingBox object.  They are equal if the
0406:             * specified <code>bounds</code> object is an instance of
0407:             * BoundingBox and all of the data
0408:             * members of <code>bounds</code> are equal to the corresponding
0409:             * data members in this BoundingBox.
0410:             * @param bounds the object with which the comparison is made.
0411:             * @return true if this BoundingBox is equal to <code>bounds</code>;
0412:             * otherwise false
0413:             *
0414:             * @since Java 3D 1.2
0415:             */
0416:            public boolean equals(Object bounds) {
0417:                try {
0418:                    BoundingBox box = (BoundingBox) bounds;
0419:                    return (lower.equals(box.lower) && upper.equals(box.upper));
0420:                } catch (NullPointerException e) {
0421:                    return false;
0422:                } catch (ClassCastException e) {
0423:                    return false;
0424:                }
0425:            }
0426:
0427:            /**
0428:             * Returns a hash code value for this BoundingBox object
0429:             * based on the data values in this object.  Two different
0430:             * BoundingBox objects with identical data values (i.e.,
0431:             * BoundingBox.equals returns true) will return the same hash
0432:             * code value.  Two BoundingBox objects with different data
0433:             * members may return the same hash code value, although this is
0434:             * not likely.
0435:             * @return a hash code value for this BoundingBox object.
0436:             *
0437:             * @since Java 3D 1.2
0438:             */
0439:            public int hashCode() {
0440:                long bits = 1L;
0441:                bits = 31L * bits + HashCodeUtil.doubleToLongBits(lower.x);
0442:                bits = 31L * bits + HashCodeUtil.doubleToLongBits(lower.y);
0443:                bits = 31L * bits + HashCodeUtil.doubleToLongBits(lower.z);
0444:                bits = 31L * bits + HashCodeUtil.doubleToLongBits(upper.x);
0445:                bits = 31L * bits + HashCodeUtil.doubleToLongBits(upper.y);
0446:                bits = 31L * bits + HashCodeUtil.doubleToLongBits(upper.z);
0447:                return (int) (bits ^ (bits >> 32));
0448:            }
0449:
0450:            /** 
0451:             * Combines this bounding box with a bounding object   so that the
0452:             * resulting bounding box encloses the original bounding box and the
0453:             * specified bounds object.
0454:             * @param boundsObject another bounds object
0455:             */
0456:            public void combine(Bounds boundsObject) {
0457:
0458:                if ((boundsObject == null) || (boundsObject.boundsIsEmpty)
0459:                        || (boundsIsInfinite))
0460:                    return;
0461:
0462:                if ((boundsIsEmpty) || (boundsObject.boundsIsInfinite)) {
0463:                    this .set(boundsObject);
0464:                    return;
0465:                }
0466:
0467:                if (boundsObject.boundId == BOUNDING_BOX) {
0468:                    BoundingBox box = (BoundingBox) boundsObject;
0469:
0470:                    if (lower.x > box.lower.x)
0471:                        lower.x = box.lower.x;
0472:                    if (lower.y > box.lower.y)
0473:                        lower.y = box.lower.y;
0474:                    if (lower.z > box.lower.z)
0475:                        lower.z = box.lower.z;
0476:                    if (upper.x < box.upper.x)
0477:                        upper.x = box.upper.x;
0478:                    if (upper.y < box.upper.y)
0479:                        upper.y = box.upper.y;
0480:                    if (upper.z < box.upper.z)
0481:                        upper.z = box.upper.z;
0482:
0483:                } else if (boundsObject.boundId == BOUNDING_SPHERE) {
0484:                    BoundingSphere sphere = (BoundingSphere) boundsObject;
0485:                    if (lower.x > (sphere.center.x - sphere.radius))
0486:                        lower.x = sphere.center.x - sphere.radius;
0487:                    if (lower.y > (sphere.center.y - sphere.radius))
0488:                        lower.y = sphere.center.y - sphere.radius;
0489:                    if (lower.z > (sphere.center.z - sphere.radius))
0490:                        lower.z = sphere.center.z - sphere.radius;
0491:                    if (upper.x < (sphere.center.x + sphere.radius))
0492:                        upper.x = sphere.center.x + sphere.radius;
0493:                    if (upper.y < (sphere.center.y + sphere.radius))
0494:                        upper.y = sphere.center.y + sphere.radius;
0495:                    if (upper.z < (sphere.center.z + sphere.radius))
0496:                        upper.z = sphere.center.z + sphere.radius;
0497:
0498:                } else if (boundsObject.boundId == BOUNDING_POLYTOPE) {
0499:                    BoundingPolytope polytope = (BoundingPolytope) boundsObject;
0500:                    int i;
0501:                    for (i = 1; i < polytope.nVerts; i++) {
0502:                        if (polytope.verts[i].x < lower.x)
0503:                            lower.x = polytope.verts[i].x;
0504:                        if (polytope.verts[i].y < lower.y)
0505:                            lower.y = polytope.verts[i].y;
0506:                        if (polytope.verts[i].z < lower.z)
0507:                            lower.z = polytope.verts[i].z;
0508:                        if (polytope.verts[i].x > upper.x)
0509:                            upper.x = polytope.verts[i].x;
0510:                        if (polytope.verts[i].y > upper.y)
0511:                            upper.y = polytope.verts[i].y;
0512:                        if (polytope.verts[i].z > upper.z)
0513:                            upper.z = polytope.verts[i].z;
0514:                    }
0515:                } else {
0516:                    throw new IllegalArgumentException(J3dI18N
0517:                            .getString("BoundingBox3"));
0518:                }
0519:
0520:                updateBoundsStates();
0521:            }
0522:
0523:            /** 
0524:             * Combines this bounding box with an array of bounding objects  
0525:             * so that the resulting bounding box encloses the original bounding 
0526:             * box and the array of bounding objects.
0527:             * @param bounds an array of bounds objects
0528:             */
0529:            public void combine(Bounds[] bounds) {
0530:                int i = 0;
0531:
0532:                if ((bounds == null) || (bounds.length <= 0)
0533:                        || (boundsIsInfinite))
0534:                    return;
0535:
0536:                // find first non empty bounds object
0537:                while ((i < bounds.length)
0538:                        && ((bounds[i] == null) || bounds[i].boundsIsEmpty)) {
0539:                    i++;
0540:                }
0541:                if (i >= bounds.length)
0542:                    return; // no non empty bounds so do not modify current bounds
0543:
0544:                if (boundsIsEmpty)
0545:                    this .set(bounds[i++]);
0546:
0547:                if (boundsIsInfinite)
0548:                    return;
0549:
0550:                for (; i < bounds.length; i++) {
0551:                    if (bounds[i] == null)
0552:                        ; // do nothing
0553:                    else if (bounds[i].boundsIsEmpty)
0554:                        ; // do nothing
0555:                    else if (bounds[i].boundsIsInfinite) {
0556:                        lower.x = lower.y = lower.z = Double.NEGATIVE_INFINITY;
0557:                        upper.x = upper.y = upper.z = Double.POSITIVE_INFINITY;
0558:                        break; // We're done.
0559:                    } else if (bounds[i].boundId == BOUNDING_BOX) {
0560:                        BoundingBox box = (BoundingBox) bounds[i];
0561:
0562:                        if (lower.x > box.lower.x)
0563:                            lower.x = box.lower.x;
0564:                        if (lower.y > box.lower.y)
0565:                            lower.y = box.lower.y;
0566:                        if (lower.z > box.lower.z)
0567:                            lower.z = box.lower.z;
0568:                        if (upper.x < box.upper.x)
0569:                            upper.x = box.upper.x;
0570:                        if (upper.y < box.upper.y)
0571:                            upper.y = box.upper.y;
0572:                        if (upper.z < box.upper.z)
0573:                            upper.z = box.upper.z;
0574:                    } else if (bounds[i].boundId == BOUNDING_SPHERE) {
0575:                        BoundingSphere sphere = (BoundingSphere) bounds[i];
0576:                        if (lower.x > (sphere.center.x - sphere.radius))
0577:                            lower.x = sphere.center.x - sphere.radius;
0578:                        if (lower.y > (sphere.center.y - sphere.radius))
0579:                            lower.y = sphere.center.y - sphere.radius;
0580:                        if (lower.z > (sphere.center.z - sphere.radius))
0581:                            lower.z = sphere.center.z - sphere.radius;
0582:                        if (upper.x < (sphere.center.x + sphere.radius))
0583:                            upper.x = sphere.center.x + sphere.radius;
0584:                        if (upper.y < (sphere.center.y + sphere.radius))
0585:                            upper.y = sphere.center.y + sphere.radius;
0586:                        if (upper.z < (sphere.center.z + sphere.radius))
0587:                            upper.z = sphere.center.z + sphere.radius;
0588:                    } else if (bounds[i].boundId == BOUNDING_POLYTOPE) {
0589:                        BoundingPolytope polytope = (BoundingPolytope) bounds[i];
0590:                        for (i = 1; i < polytope.nVerts; i++) {
0591:                            if (polytope.verts[i].x < lower.x)
0592:                                lower.x = polytope.verts[i].x;
0593:                            if (polytope.verts[i].y < lower.y)
0594:                                lower.y = polytope.verts[i].y;
0595:                            if (polytope.verts[i].z < lower.z)
0596:                                lower.z = polytope.verts[i].z;
0597:                            if (polytope.verts[i].x > upper.x)
0598:                                upper.x = polytope.verts[i].x;
0599:                            if (polytope.verts[i].y > upper.y)
0600:                                upper.y = polytope.verts[i].y;
0601:                            if (polytope.verts[i].z > upper.z)
0602:                                upper.z = polytope.verts[i].z;
0603:                        }
0604:                    } else {
0605:                        throw new IllegalArgumentException(J3dI18N
0606:                                .getString("BoundingBox4"));
0607:                    }
0608:                }
0609:
0610:                updateBoundsStates();
0611:            }
0612:
0613:            /** 
0614:             * Combines this bounding box with a point so that the resulting
0615:             * bounding box encloses the original bounding box and the point.
0616:             * @param point a 3d point in space 
0617:             */
0618:            public void combine(Point3d point) {
0619:
0620:                if (boundsIsInfinite) {
0621:                    return;
0622:                }
0623:
0624:                if (boundsIsEmpty) {
0625:                    upper.x = lower.x = point.x;
0626:                    upper.y = lower.y = point.y;
0627:                    upper.z = lower.z = point.z;
0628:                } else {
0629:                    if (point.x > upper.x)
0630:                        upper.x = point.x;
0631:                    if (point.y > upper.y)
0632:                        upper.y = point.y;
0633:                    if (point.z > upper.z)
0634:                        upper.z = point.z;
0635:
0636:                    if (point.x < lower.x)
0637:                        lower.x = point.x;
0638:                    if (point.y < lower.y)
0639:                        lower.y = point.y;
0640:                    if (point.z < lower.z)
0641:                        lower.z = point.z;
0642:                }
0643:
0644:                updateBoundsStates();
0645:            }
0646:
0647:            /** 
0648:             * Combines this bounding box with an array of points so that the
0649:             * resulting bounding box encloses the original bounding box and the
0650:             * array of points.
0651:             * @param points an array of 3d points in space 
0652:             */
0653:            public void combine(Point3d[] points) {
0654:
0655:                int i;
0656:
0657:                if (boundsIsInfinite) {
0658:                    return;
0659:                }
0660:
0661:                if (boundsIsEmpty) {
0662:                    this .setUpper(points[0]);
0663:                    this .setLower(points[0]);
0664:                }
0665:
0666:                for (i = 0; i < points.length; i++) {
0667:                    if (points[i].x > upper.x)
0668:                        upper.x = points[i].x;
0669:                    if (points[i].y > upper.y)
0670:                        upper.y = points[i].y;
0671:                    if (points[i].z > upper.z)
0672:                        upper.z = points[i].z;
0673:
0674:                    if (points[i].x < lower.x)
0675:                        lower.x = points[i].x;
0676:                    if (points[i].y < lower.y)
0677:                        lower.y = points[i].y;
0678:                    if (points[i].z < lower.z)
0679:                        lower.z = points[i].z;
0680:                }
0681:
0682:                updateBoundsStates();
0683:            }
0684:
0685:            /**
0686:             * Modifies the bounding box so that it bounds the volume
0687:             * generated by transforming the given bounding object.
0688:             * @param boundsObject the bounding object to be transformed 
0689:             * @param matrix a transformation matrix
0690:             */
0691:            public void transform(Bounds boundsObject, Transform3D matrix) {
0692:
0693:                if (boundsObject == null || boundsObject.boundsIsEmpty) {
0694:                    // Negative volume.
0695:                    lower.x = lower.y = lower.z = 1.0d;
0696:                    upper.x = upper.y = upper.z = -1.0d;
0697:                    updateBoundsStates();
0698:                    return;
0699:                }
0700:
0701:                if (boundsObject.boundsIsInfinite) {
0702:                    lower.x = lower.y = lower.z = Double.NEGATIVE_INFINITY;
0703:                    upper.x = upper.y = upper.z = Double.POSITIVE_INFINITY;
0704:                    updateBoundsStates();
0705:                    return;
0706:                }
0707:
0708:                if (boundsObject.boundId == BOUNDING_BOX) {
0709:                    if (tmpBox == null) {
0710:                        tmpBox = new BoundingBox((BoundingBox) boundsObject);
0711:                    } else {
0712:                        tmpBox.set((BoundingBox) boundsObject);
0713:                    }
0714:                    tmpBox.transform(matrix);
0715:                    this .set(tmpBox);
0716:                } else if (boundsObject.boundId == BOUNDING_SPHERE) {
0717:                    if (tmpSphere == null) {
0718:                        tmpSphere = new BoundingSphere(
0719:                                (BoundingSphere) boundsObject);
0720:                    } else {
0721:                        tmpSphere.set((BoundingSphere) boundsObject);
0722:                    }
0723:                    tmpSphere.transform(matrix);
0724:                    this .set(tmpSphere);
0725:                } else if (boundsObject.boundId == BOUNDING_POLYTOPE) {
0726:                    if (tmpPolytope == null) {
0727:                        tmpPolytope = new BoundingPolytope(
0728:                                (BoundingPolytope) boundsObject);
0729:                    } else {
0730:                        tmpPolytope.set((BoundingPolytope) boundsObject);
0731:                    }
0732:                    tmpPolytope.transform(matrix);
0733:                    this .set(tmpPolytope);
0734:
0735:                } else {
0736:                    throw new IllegalArgumentException(J3dI18N
0737:                            .getString("BoundingBox5"));
0738:                }
0739:
0740:                // Release the temporary fields:
0741:                if (VirtualUniverse.mc.releaseBoundingBoxMemory) {
0742:                    tmpSphere = null;
0743:                    tmpBox = null;
0744:                    tmpPolytope = null;
0745:                }
0746:            }
0747:
0748:            /** 
0749:             * Transforms this bounding box by the given matrix.
0750:             * @param matrix a transformation matrix
0751:             */
0752:            public void transform(Transform3D matrix) {
0753:
0754:                if (boundsIsInfinite)
0755:                    return;
0756:
0757:                if (tmpP3d == null) {
0758:                    tmpP3d = new Point3d();
0759:                }
0760:
0761:                double ux, uy, uz, lx, ly, lz;
0762:                ux = upper.x;
0763:                uy = upper.y;
0764:                uz = upper.z;
0765:                lx = lower.x;
0766:                ly = lower.y;
0767:                lz = lower.z;
0768:
0769:                tmpP3d.set(ux, uy, uz);
0770:                matrix.transform(tmpP3d);
0771:                upper.x = tmpP3d.x;
0772:                upper.y = tmpP3d.y;
0773:                upper.z = tmpP3d.z;
0774:                lower.x = tmpP3d.x;
0775:                lower.y = tmpP3d.y;
0776:                lower.z = tmpP3d.z;
0777:
0778:                tmpP3d.set(lx, uy, uz);
0779:                matrix.transform(tmpP3d);
0780:                if (tmpP3d.x > upper.x)
0781:                    upper.x = tmpP3d.x;
0782:                if (tmpP3d.y > upper.y)
0783:                    upper.y = tmpP3d.y;
0784:                if (tmpP3d.z > upper.z)
0785:                    upper.z = tmpP3d.z;
0786:                if (tmpP3d.x < lower.x)
0787:                    lower.x = tmpP3d.x;
0788:                if (tmpP3d.y < lower.y)
0789:                    lower.y = tmpP3d.y;
0790:                if (tmpP3d.z < lower.z)
0791:                    lower.z = tmpP3d.z;
0792:
0793:                tmpP3d.set(lx, ly, uz);
0794:                matrix.transform(tmpP3d);
0795:                if (tmpP3d.x > upper.x)
0796:                    upper.x = tmpP3d.x;
0797:                if (tmpP3d.y > upper.y)
0798:                    upper.y = tmpP3d.y;
0799:                if (tmpP3d.z > upper.z)
0800:                    upper.z = tmpP3d.z;
0801:                if (tmpP3d.x < lower.x)
0802:                    lower.x = tmpP3d.x;
0803:                if (tmpP3d.y < lower.y)
0804:                    lower.y = tmpP3d.y;
0805:                if (tmpP3d.z < lower.z)
0806:                    lower.z = tmpP3d.z;
0807:
0808:                tmpP3d.set(ux, ly, uz);
0809:                matrix.transform(tmpP3d);
0810:                if (tmpP3d.x > upper.x)
0811:                    upper.x = tmpP3d.x;
0812:                if (tmpP3d.y > upper.y)
0813:                    upper.y = tmpP3d.y;
0814:                if (tmpP3d.z > upper.z)
0815:                    upper.z = tmpP3d.z;
0816:                if (tmpP3d.x < lower.x)
0817:                    lower.x = tmpP3d.x;
0818:                if (tmpP3d.y < lower.y)
0819:                    lower.y = tmpP3d.y;
0820:                if (tmpP3d.z < lower.z)
0821:                    lower.z = tmpP3d.z;
0822:
0823:                tmpP3d.set(lx, uy, lz);
0824:                matrix.transform(tmpP3d);
0825:                if (tmpP3d.x > upper.x)
0826:                    upper.x = tmpP3d.x;
0827:                if (tmpP3d.y > upper.y)
0828:                    upper.y = tmpP3d.y;
0829:                if (tmpP3d.z > upper.z)
0830:                    upper.z = tmpP3d.z;
0831:                if (tmpP3d.x < lower.x)
0832:                    lower.x = tmpP3d.x;
0833:                if (tmpP3d.y < lower.y)
0834:                    lower.y = tmpP3d.y;
0835:                if (tmpP3d.z < lower.z)
0836:                    lower.z = tmpP3d.z;
0837:
0838:                tmpP3d.set(ux, uy, lz);
0839:                matrix.transform(tmpP3d);
0840:                if (tmpP3d.x > upper.x)
0841:                    upper.x = tmpP3d.x;
0842:                if (tmpP3d.y > upper.y)
0843:                    upper.y = tmpP3d.y;
0844:                if (tmpP3d.z > upper.z)
0845:                    upper.z = tmpP3d.z;
0846:                if (tmpP3d.x < lower.x)
0847:                    lower.x = tmpP3d.x;
0848:                if (tmpP3d.y < lower.y)
0849:                    lower.y = tmpP3d.y;
0850:                if (tmpP3d.z < lower.z)
0851:                    lower.z = tmpP3d.z;
0852:
0853:                tmpP3d.set(lx, ly, lz);
0854:                matrix.transform(tmpP3d);
0855:                if (tmpP3d.x > upper.x)
0856:                    upper.x = tmpP3d.x;
0857:                if (tmpP3d.y > upper.y)
0858:                    upper.y = tmpP3d.y;
0859:                if (tmpP3d.z > upper.z)
0860:                    upper.z = tmpP3d.z;
0861:                if (tmpP3d.x < lower.x)
0862:                    lower.x = tmpP3d.x;
0863:                if (tmpP3d.y < lower.y)
0864:                    lower.y = tmpP3d.y;
0865:                if (tmpP3d.z < lower.z)
0866:                    lower.z = tmpP3d.z;
0867:
0868:                tmpP3d.set(ux, ly, lz);
0869:                matrix.transform(tmpP3d);
0870:                if (tmpP3d.x > upper.x)
0871:                    upper.x = tmpP3d.x;
0872:                if (tmpP3d.y > upper.y)
0873:                    upper.y = tmpP3d.y;
0874:                if (tmpP3d.z > upper.z)
0875:                    upper.z = tmpP3d.z;
0876:                if (tmpP3d.x < lower.x)
0877:                    lower.x = tmpP3d.x;
0878:                if (tmpP3d.y < lower.y)
0879:                    lower.y = tmpP3d.y;
0880:                if (tmpP3d.z < lower.z)
0881:                    lower.z = tmpP3d.z;
0882:
0883:                if (VirtualUniverse.mc.releaseBoundingBoxMemory) {
0884:                    // Free memory
0885:                    tmpP3d = null;
0886:                }
0887:
0888:            }
0889:
0890:            /** 
0891:             * Test for intersection with a ray.
0892:             * @param origin the starting point of the ray   
0893:             * @param direction the direction of the ray
0894:             * @param position3 a point defining the location of the pick w= distance to pick
0895:             * @return true or false indicating if an intersection occured 
0896:             */
0897:            boolean intersect(Point3d origin, Vector3d direction,
0898:                    Point4d position) {
0899:                double t1, t2, tmp, tnear, tfar, invDir, invMag;
0900:                double dirx, diry, dirz;
0901:
0902:                /*
0903:                  System.err.println("BoundingBox.intersect(p,d,p) called\n");
0904:                  System.err.println("bounds = " + lower + " -> " + upper);
0905:                 */
0906:
0907:                if (boundsIsEmpty) {
0908:                    return false;
0909:                }
0910:
0911:                if (boundsIsInfinite) {
0912:                    position.x = origin.x;
0913:                    position.y = origin.y;
0914:                    position.z = origin.z;
0915:                    position.w = 0.0;
0916:                    return true;
0917:                }
0918:
0919:                double dirLen = direction.x * direction.x + direction.y
0920:                        * direction.y + direction.z * direction.z;
0921:
0922:                // Handle zero length direction vector.
0923:                if (dirLen == 0.0)
0924:                    return intersect(origin, position);
0925:
0926:                invMag = 1.0 / Math.sqrt(dirLen);
0927:                dirx = direction.x * invMag;
0928:                diry = direction.y * invMag;
0929:                dirz = direction.z * invMag;
0930:
0931:                /*
0932:                  System.err.println("dir = " + dirx + ", " + diry + ", " + dirz);
0933:                  System.err.println("origin = " + origin);
0934:                 */
0935:
0936:                // initialize tnear and tfar to handle dir.? == 0 cases
0937:                tnear = -Double.MAX_VALUE;
0938:                tfar = Double.MAX_VALUE;
0939:
0940:                if (dirx == 0.0) {
0941:                    //System.err.println("dirx == 0.0");
0942:                    if (origin.x < lower.x || origin.x > upper.x) {
0943:                        //System.err.println( "parallel to x plane and outside");
0944:                        return false;
0945:                    }
0946:                } else {
0947:                    invDir = 1.0 / dirx;
0948:                    t1 = (lower.x - origin.x) * invDir;
0949:                    t2 = (upper.x - origin.x) * invDir;
0950:
0951:                    //System.err.println("x t1 = " + t1 + " t2 = " + t2);
0952:                    if (t1 > t2) {
0953:                        tnear = t2;
0954:                        tfar = t1;
0955:                    } else {
0956:                        tnear = t1;
0957:                        tfar = t2;
0958:                    }
0959:                    if (tfar < 0.0) {
0960:                        //System.err.println( "x failed: tnear="+tnear+"  tfar="+tfar);
0961:                        return false;
0962:                    }
0963:                    //System.err.println("x tnear = " + tnear + " tfar = " + tfar);
0964:                }
0965:                // y
0966:                if (diry == 0.0) {
0967:                    //System.err.println("diry == 0.0");
0968:                    if (origin.y < lower.y || origin.y > upper.y) {
0969:                        //System.err.println( "parallel to y plane and outside");
0970:                        return false;
0971:                    }
0972:                } else {
0973:                    invDir = 1.0 / diry;
0974:                    //System.err.println("invDir = " + invDir);
0975:                    t1 = (lower.y - origin.y) * invDir;
0976:                    t2 = (upper.y - origin.y) * invDir;
0977:
0978:                    if (t1 > t2) {
0979:                        tmp = t1;
0980:                        t1 = t2;
0981:                        t2 = tmp;
0982:                    }
0983:                    //System.err.println("y t1 = " + t1 + " t2 = " + t2);
0984:                    if (t1 > tnear)
0985:                        tnear = t1;
0986:                    if (t2 < tfar)
0987:                        tfar = t2;
0988:
0989:                    if ((tfar < 0.0) || (tnear > tfar)) {
0990:                        //System.err.println( "y failed: tnear="+tnear+"  tfar="+tfar);
0991:                        return false;
0992:                    }
0993:                    //System.err.println("y tnear = " + tnear + " tfar = " + tfar);
0994:                }
0995:
0996:                // z
0997:                if (dirz == 0.0) {
0998:                    //System.err.println("dirz == 0.0");
0999:                    if (origin.z < lower.z || origin.z > upper.z) {
1000:                        //System.err.println( "parallel to z plane and outside");
1001:                        return false;
1002:                    }
1003:                } else {
1004:                    invDir = 1.0 / dirz;
1005:                    t1 = (lower.z - origin.z) * invDir;
1006:                    t2 = (upper.z - origin.z) * invDir;
1007:
1008:                    if (t1 > t2) {
1009:                        tmp = t1;
1010:                        t1 = t2;
1011:                        t2 = tmp;
1012:                    }
1013:                    //System.err.println("z t1 = " + t1 + " t2 = " + t2);
1014:                    if (t1 > tnear)
1015:                        tnear = t1;
1016:                    if (t2 < tfar)
1017:                        tfar = t2;
1018:
1019:                    if ((tfar < 0.0) || (tnear > tfar)) {
1020:                        //System.err.println( "z failed: tnear="+tnear+"  tfar="+tfar);
1021:                        return false;
1022:                    }
1023:                    //System.err.println("z tnear = " + tnear + " tfar = " + tfar);
1024:                }
1025:
1026:                if ((tnear < 0.0) && (tfar >= 0.0)) {
1027:                    // origin is inside the BBox.
1028:                    position.x = origin.x + dirx * tfar;
1029:                    position.y = origin.y + diry * tfar;
1030:                    position.z = origin.z + dirz * tfar;
1031:                    position.w = tfar;
1032:                } else {
1033:                    position.x = origin.x + dirx * tnear;
1034:                    position.y = origin.y + diry * tnear;
1035:                    position.z = origin.z + dirz * tnear;
1036:                    position.w = tnear;
1037:                }
1038:
1039:                return true;
1040:
1041:            }
1042:
1043:            /** 
1044:             * Test for intersection with a point.
1045:             * @param point the pick point   
1046:             * @param position a point defining the location  of the pick w= distance to pick
1047:             * @return true or false indicating if an intersection occured 
1048:             */
1049:            boolean intersect(Point3d point, Point4d position) {
1050:
1051:                if (boundsIsEmpty) {
1052:                    return false;
1053:                }
1054:
1055:                if (boundsIsInfinite) {
1056:                    position.x = point.x;
1057:                    position.y = point.y;
1058:                    position.z = point.z;
1059:                    position.w = 0.0;
1060:                    return true;
1061:                }
1062:
1063:                if (point.x <= upper.x && point.x >= lower.x
1064:                        && point.y <= upper.y && point.y >= lower.y
1065:                        && point.z <= upper.z && point.z >= lower.z) {
1066:                    position.x = point.x;
1067:                    position.y = point.y;
1068:                    position.z = point.z;
1069:                    position.w = 0.0;
1070:                    return true;
1071:                } else
1072:                    return false;
1073:
1074:            }
1075:
1076:            /**
1077:             * Test for intersection with a segment.
1078:             * @param start a point defining  the start of the line segment 
1079:             * @param end a point defining the end of the line segment 
1080:             * @param position a point defining the location  of the pick w= distance to pick
1081:             * @return true or false indicating if an intersection occured
1082:             */
1083:            boolean intersect(Point3d start, Point3d end, Point4d position) {
1084:                double t1, t2, tmp, tnear, tfar, invDir, invMag;
1085:                double dirx, diry, dirz;
1086:
1087:                if (boundsIsEmpty) {
1088:                    return false;
1089:                }
1090:
1091:                if (boundsIsInfinite) {
1092:                    position.x = start.x;
1093:                    position.y = start.y;
1094:                    position.z = start.z;
1095:                    position.w = 0.0;
1096:                    return true;
1097:                }
1098:
1099:                dirx = end.x - start.x;
1100:                diry = end.y - start.y;
1101:                dirz = end.z - start.z;
1102:
1103:                double dirLen = dirx * dirx + diry * diry + dirz * dirz;
1104:
1105:                // Optimization : Handle zero length direction vector.
1106:                if (dirLen == 0.0)
1107:                    return intersect(start, position);
1108:
1109:                dirLen = Math.sqrt(dirLen);
1110:                // System.err.println("dirLen is " + dirLen);
1111:                invMag = 1.0 / dirLen;
1112:                dirx = dirx * invMag;
1113:                diry = diry * invMag;
1114:                dirz = dirz * invMag;
1115:
1116:                /*
1117:                System.err.println("dir = " + dir);
1118:                System.err.println("start = " + start);
1119:                System.err.println("lower = " + lower);
1120:                System.err.println("upper = " + upper);
1121:                 */
1122:
1123:                // initialize tnear and tfar to handle dir.? == 0 cases
1124:                tnear = -Double.MAX_VALUE;
1125:                tfar = Double.MAX_VALUE;
1126:
1127:                if (dirx == 0.0) {
1128:                    //System.err.println("dirx == 0.0");
1129:                    if (start.x < lower.x || start.x > upper.x) {
1130:                        //System.err.println( "parallel to x plane and outside");
1131:                        return false;
1132:                    }
1133:                } else {
1134:                    invDir = 1.0 / dirx;
1135:                    t1 = (lower.x - start.x) * invDir;
1136:                    t2 = (upper.x - start.x) * invDir;
1137:
1138:                    //System.err.println("x t1 = " + t1 + " t2 = " + t2);
1139:                    if (t1 > t2) {
1140:                        tnear = t2;
1141:                        tfar = t1;
1142:                    } else {
1143:                        tnear = t1;
1144:                        tfar = t2;
1145:                    }
1146:                    if (tfar < 0.0) {
1147:                        //System.err.println( "x failed: tnear="+tnear+"  tfar="+tfar);
1148:                        return false;
1149:                    }
1150:                    //System.err.println("x tnear = " + tnear + " tfar = " + tfar);
1151:                }
1152:                // y
1153:                if (diry == 0.0) {
1154:                    //System.err.println("diry == 0.0");
1155:                    if (start.y < lower.y || start.y > upper.y) {
1156:                        //System.err.println( "parallel to y plane and outside");
1157:                        return false;
1158:                    }
1159:                } else {
1160:                    invDir = 1.0 / diry;
1161:                    //System.err.println("invDir = " + invDir);
1162:                    t1 = (lower.y - start.y) * invDir;
1163:                    t2 = (upper.y - start.y) * invDir;
1164:
1165:                    if (t1 > t2) {
1166:                        tmp = t1;
1167:                        t1 = t2;
1168:                        t2 = tmp;
1169:                    }
1170:                    //System.err.println("y t1 = " + t1 + " t2 = " + t2);
1171:                    if (t1 > tnear)
1172:                        tnear = t1;
1173:                    if (t2 < tfar)
1174:                        tfar = t2;
1175:
1176:                    if ((tfar < 0.0) || (tnear > tfar)) {
1177:                        //System.err.println( "y failed: tnear="+tnear+"  tfar="+tfar);
1178:                        return false;
1179:                    }
1180:                    //System.err.println("y tnear = " + tnear + " tfar = " + tfar);
1181:                }
1182:
1183:                // z
1184:                if (dirz == 0.0) {
1185:                    //System.err.println("dirz == 0.0");
1186:                    if (start.z < lower.z || start.z > upper.z) {
1187:                        //System.err.println( "parallel to z plane and outside");
1188:                        return false;
1189:                    }
1190:                } else {
1191:                    invDir = 1.0 / dirz;
1192:                    t1 = (lower.z - start.z) * invDir;
1193:                    t2 = (upper.z - start.z) * invDir;
1194:
1195:                    if (t1 > t2) {
1196:                        tmp = t1;
1197:                        t1 = t2;
1198:                        t2 = tmp;
1199:                    }
1200:                    //System.err.println("z t1 = " + t1 + " t2 = " + t2);
1201:                    if (t1 > tnear)
1202:                        tnear = t1;
1203:                    if (t2 < tfar)
1204:                        tfar = t2;
1205:
1206:                    if ((tfar < 0.0) || (tnear > tfar)) {
1207:                        //System.err.println( "z failed: tnear="+tnear+"  tfar="+tfar);
1208:                        return false;
1209:                    }
1210:                    //System.err.println("z tnear = " + tnear + " tfar = " + tfar);
1211:                }
1212:
1213:                if ((tnear < 0.0) && (tfar >= 0.0)) {
1214:                    // origin is inside the BBox.
1215:                    position.x = start.x + dirx * tfar;
1216:                    position.y = start.y + diry * tfar;
1217:                    position.z = start.z + dirz * tfar;
1218:                    position.w = tfar;
1219:                } else {
1220:                    if (tnear > dirLen) {
1221:                        // Segment is behind BBox.
1222:                        /*
1223:                          System.err.println("PickSegment : intersected postion : " + position
1224:                          + " tnear " + tnear + " tfar " + tfar );
1225:                         */
1226:                        return false;
1227:                    }
1228:                    position.x = start.x + dirx * tnear;
1229:                    position.y = start.y + diry * tnear;
1230:                    position.z = start.z + dirz * tnear;
1231:
1232:                    position.w = tnear;
1233:                }
1234:
1235:                /*  
1236:                    System.err.println("tnear = " + tnear + " tfar = " + tfar + " w " +
1237:                    position.w);
1238:                    System.err.println("lower = " + lower);
1239:                    System.err.println("upper = " + upper + "\n");
1240:                 */
1241:                return true;
1242:
1243:            }
1244:
1245:            /** 
1246:             * Test for intersection with a ray.
1247:             * @param origin the starting point of the ray   
1248:             * @param direction the direction of the ray
1249:             * @return true or false indicating if an intersection occured 
1250:             */
1251:            public boolean intersect(Point3d origin, Vector3d direction) {
1252:
1253:                if (boundsIsEmpty) {
1254:                    return false;
1255:                }
1256:
1257:                if (boundsIsInfinite) {
1258:                    return true;
1259:                }
1260:
1261:                Point3d p = new Point3d();
1262:                return intersect(origin, direction, p);
1263:            }
1264:
1265:            /**
1266:             * A protected intersect method that returns the point of intersection.
1267:             * Used by Picking methods to sort or return closest picked item.
1268:             */
1269:            boolean intersect(Point3d origin, Vector3d direction,
1270:                    Point3d intersect) {
1271:                double theta = 0.0;
1272:
1273:                if (boundsIsEmpty) {
1274:                    return false;
1275:                }
1276:
1277:                if (boundsIsInfinite) {
1278:                    intersect.x = origin.x;
1279:                    intersect.y = origin.y;
1280:                    intersect.z = origin.z;
1281:                    return true;
1282:                }
1283:
1284:                if (direction.x > 0.0)
1285:                    theta = Math.max(theta, (lower.x - origin.x) / direction.x);
1286:                if (direction.x < 0.0)
1287:                    theta = Math.max(theta, (upper.x - origin.x) / direction.x);
1288:                if (direction.y > 0.0)
1289:                    theta = Math.max(theta, (lower.y - origin.y) / direction.y);
1290:                if (direction.y < 0.0)
1291:                    theta = Math.max(theta, (upper.y - origin.y) / direction.y);
1292:                if (direction.z > 0.0)
1293:                    theta = Math.max(theta, (lower.z - origin.z) / direction.z);
1294:                if (direction.z < 0.0)
1295:                    theta = Math.max(theta, (upper.z - origin.z) / direction.z);
1296:
1297:                intersect.x = origin.x + theta * direction.x;
1298:                intersect.y = origin.y + theta * direction.y;
1299:                intersect.z = origin.z + theta * direction.z;
1300:
1301:                if (intersect.x < (lower.x - EPS))
1302:                    return false;
1303:                if (intersect.x > (upper.x + EPS))
1304:                    return false;
1305:                if (intersect.y < (lower.y - EPS))
1306:                    return false;
1307:                if (intersect.y > (upper.y + EPS))
1308:                    return false;
1309:                if (intersect.z < (lower.z - EPS))
1310:                    return false;
1311:                if (intersect.z > (upper.z + EPS))
1312:                    return false;
1313:
1314:                return true;
1315:
1316:            }
1317:
1318:            /** 
1319:             * Test for intersection with a point.
1320:             * @param point a point defining a position in 3-space 
1321:             * @return true or false indicating if an intersection occured 
1322:             */
1323:            public boolean intersect(Point3d point) {
1324:
1325:                if (boundsIsEmpty) {
1326:                    return false;
1327:                }
1328:                if (boundsIsInfinite) {
1329:                    return true;
1330:                }
1331:
1332:                if (point.x <= upper.x && point.x >= lower.x
1333:                        && point.y <= upper.y && point.y >= lower.y
1334:                        && point.z <= upper.z && point.z >= lower.z)
1335:                    return true;
1336:                else
1337:                    return false;
1338:            }
1339:
1340:            /**
1341:             * Tests whether the bounding box is empty.  A bounding box is
1342:             * empty if it is null (either by construction or as the result of
1343:             * a null intersection) or if its volume is negative.  A bounding box
1344:             * with a volume of zero is <i>not</i> empty.
1345:             * @return true if the bounding box is empty; otherwise, it returns false
1346:             */
1347:            public boolean isEmpty() {
1348:
1349:                return boundsIsEmpty;
1350:            }
1351:
1352:            /** 
1353:             * Test for intersection with another bounds object.
1354:             * @param boundsObject another bounds object 
1355:             * @return true or false indicating if an intersection occured 
1356:             */
1357:            boolean intersect(Bounds boundsObject, Point4d position) {
1358:                return intersect(boundsObject);
1359:            }
1360:
1361:            /** 
1362:             * Test for intersection with another bounds object. 
1363:             * @param boundsObject another bounds object 
1364:             * @return true or false indicating if an intersection occured 
1365:             */
1366:            public boolean intersect(Bounds boundsObject) {
1367:
1368:                if (boundsObject == null) {
1369:                    return false;
1370:                }
1371:
1372:                if (boundsIsEmpty || boundsObject.boundsIsEmpty) {
1373:                    return false;
1374:                }
1375:
1376:                if (boundsIsInfinite || boundsObject.boundsIsInfinite) {
1377:                    return true;
1378:                }
1379:
1380:                if (boundsObject.boundId == BOUNDING_BOX) {
1381:                    BoundingBox box = (BoundingBox) boundsObject;
1382:                    // both boxes are axis aligned
1383:                    if (upper.x > box.lower.x && box.upper.x > lower.x
1384:                            && upper.y > box.lower.y && box.upper.y > lower.y
1385:                            && upper.z > box.lower.z && box.upper.z > lower.z)
1386:                        return true;
1387:                    else
1388:                        return false;
1389:                } else if (boundsObject.boundId == BOUNDING_SPHERE) {
1390:                    BoundingSphere sphere = (BoundingSphere) boundsObject;
1391:                    double rad_sq = sphere.radius * sphere.radius;
1392:                    double dis = 0.0;
1393:
1394:                    if (sphere.center.x < lower.x)
1395:                        dis = (sphere.center.x - lower.x)
1396:                                * (sphere.center.x - lower.x);
1397:                    else if (sphere.center.x > upper.x)
1398:                        dis = (sphere.center.x - upper.x)
1399:                                * (sphere.center.x - upper.x);
1400:
1401:                    if (sphere.center.y < lower.y)
1402:                        dis += (sphere.center.y - lower.y)
1403:                                * (sphere.center.y - lower.y);
1404:                    else if (sphere.center.y > upper.y)
1405:                        dis += (sphere.center.y - upper.y)
1406:                                * (sphere.center.y - upper.y);
1407:
1408:                    if (sphere.center.z < lower.z)
1409:                        dis += (sphere.center.z - lower.z)
1410:                                * (sphere.center.z - lower.z);
1411:                    else if (sphere.center.z > upper.z)
1412:                        dis += (sphere.center.z - upper.z)
1413:                                * (sphere.center.z - upper.z);
1414:
1415:                    if (dis <= rad_sq)
1416:                        return true;
1417:                    else
1418:                        return false;
1419:                } else if (boundsObject.boundId == BOUNDING_POLYTOPE) {
1420:                    // intersect an axis aligned box with a polytope
1421:                    return intersect_ptope_abox(
1422:                            (BoundingPolytope) boundsObject, this );
1423:                } else {
1424:                    throw new IllegalArgumentException(J3dI18N
1425:                            .getString("BoundingBox6"));
1426:                }
1427:
1428:            }
1429:
1430:            /** 
1431:             * Test for intersection with an array of bounds objects.
1432:             * @param boundsObjects an array of bounding objects 
1433:             * @return true or false indicating if an intersection occured 
1434:             */
1435:            public boolean intersect(Bounds[] boundsObjects) {
1436:
1437:                double distsq, radsq;
1438:                int i;
1439:
1440:                if (boundsObjects == null || boundsObjects.length <= 0) {
1441:                    return false;
1442:                }
1443:
1444:                if (boundsIsEmpty) {
1445:                    return false;
1446:                }
1447:
1448:                for (i = 0; i < boundsObjects.length; i++) {
1449:                    if (boundsObjects[i] == null
1450:                            || boundsObjects[i].boundsIsEmpty)
1451:                        ;
1452:                    else if (boundsIsInfinite
1453:                            || boundsObjects[i].boundsIsInfinite) {
1454:                        return true; // We're done here.
1455:                    } else if (boundsObjects[i].boundId == BOUNDING_BOX) {
1456:                        BoundingBox box = (BoundingBox) boundsObjects[i];
1457:                        // both boxes are axis aligned
1458:                        if (upper.x > box.lower.x && box.upper.x > lower.x
1459:                                && upper.y > box.lower.y
1460:                                && box.upper.y > lower.y
1461:                                && upper.z > box.lower.z
1462:                                && box.upper.z > lower.z)
1463:                            return true;
1464:                    } else if (boundsObjects[i].boundId == BOUNDING_SPHERE) {
1465:                        BoundingSphere sphere = (BoundingSphere) boundsObjects[i];
1466:                        double rad_sq = sphere.radius * sphere.radius;
1467:                        double dis = 0.0;
1468:
1469:                        if (sphere.center.x < lower.x)
1470:                            dis = (sphere.center.x - lower.x)
1471:                                    * (sphere.center.x - lower.x);
1472:                        else if (sphere.center.x > upper.x)
1473:                            dis = (sphere.center.x - upper.x)
1474:                                    * (sphere.center.x - upper.x);
1475:
1476:                        if (sphere.center.y < lower.y)
1477:                            dis += (sphere.center.y - lower.y)
1478:                                    * (sphere.center.y - lower.y);
1479:                        else if (sphere.center.y > upper.y)
1480:                            dis += (sphere.center.y - upper.y)
1481:                                    * (sphere.center.y - upper.y);
1482:
1483:                        if (sphere.center.z < lower.z)
1484:                            dis += (sphere.center.z - lower.z)
1485:                                    * (sphere.center.z - lower.z);
1486:                        else if (sphere.center.z > upper.z)
1487:                            dis += (sphere.center.z - upper.z)
1488:                                    * (sphere.center.z - upper.z);
1489:
1490:                        if (dis <= rad_sq)
1491:                            return true;
1492:
1493:                    } else if (boundsObjects[i].boundId == BOUNDING_POLYTOPE) {
1494:                        if (intersect_ptope_abox(
1495:                                (BoundingPolytope) boundsObjects[i], this ))
1496:                            return true;
1497:                    } else {
1498:                        //	       System.err.println("intersect ?? ");
1499:                    }
1500:                }
1501:
1502:                return false;
1503:            }
1504:
1505:            /** 
1506:             * Test for intersection with another bounding box.
1507:             * @param boundsObject another bounding object 
1508:             * @param newBoundBox the new bounding box which is the intersection of
1509:             *        the boundsObject and this BoundingBox
1510:             * @return true or false indicating if an intersection occured 
1511:             */
1512:            public boolean intersect(Bounds boundsObject,
1513:                    BoundingBox newBoundBox) {
1514:
1515:                if ((boundsObject == null) || boundsIsEmpty
1516:                        || boundsObject.boundsIsEmpty) {
1517:                    // Negative volume.
1518:                    newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1519:                    newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1520:                    return false;
1521:                }
1522:
1523:                if (boundsIsInfinite && (!boundsObject.boundsIsInfinite)) {
1524:                    newBoundBox.set(boundsObject);
1525:                    return true;
1526:                } else if ((!boundsIsInfinite) && boundsObject.boundsIsInfinite) {
1527:                    newBoundBox.set(this );
1528:                    return true;
1529:                } else if (boundsIsInfinite && boundsObject.boundsIsInfinite) {
1530:                    newBoundBox.set(this );
1531:                    return true;
1532:                } else if (boundsObject.boundId == BOUNDING_BOX) {
1533:                    BoundingBox box = (BoundingBox) boundsObject;
1534:                    // both boxes are axis aligned
1535:                    if (upper.x > box.lower.x && box.upper.x > lower.x
1536:                            && upper.y > box.lower.y && box.upper.y > lower.y
1537:                            && upper.z > box.lower.z && box.upper.z > lower.z) {
1538:
1539:                        if (upper.x > box.upper.x)
1540:                            newBoundBox.upper.x = box.upper.x;
1541:                        else
1542:                            newBoundBox.upper.x = upper.x;
1543:
1544:                        if (upper.y > box.upper.y)
1545:                            newBoundBox.upper.y = box.upper.y;
1546:                        else
1547:                            newBoundBox.upper.y = upper.y;
1548:
1549:                        if (upper.z > box.upper.z)
1550:                            newBoundBox.upper.z = box.upper.z;
1551:                        else
1552:                            newBoundBox.upper.z = upper.z;
1553:
1554:                        if (lower.x < box.lower.x)
1555:                            newBoundBox.lower.x = box.lower.x;
1556:                        else
1557:                            newBoundBox.lower.x = lower.x;
1558:
1559:                        if (lower.y < box.lower.y)
1560:                            newBoundBox.lower.y = box.lower.y;
1561:                        else
1562:                            newBoundBox.lower.y = lower.y;
1563:
1564:                        if (lower.z < box.lower.z)
1565:                            newBoundBox.lower.z = box.lower.z;
1566:                        else
1567:                            newBoundBox.lower.z = lower.z;
1568:
1569:                        newBoundBox.updateBoundsStates();
1570:                        return true;
1571:                    } else {
1572:                        // Negative volume.
1573:                        newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1574:                        newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1575:                        return false;
1576:                    }
1577:                } else if (boundsObject.boundId == BOUNDING_SPHERE) {
1578:                    BoundingSphere sphere = (BoundingSphere) boundsObject;
1579:                    if (this .intersect(sphere)) {
1580:                        BoundingBox sbox = new BoundingBox(sphere);
1581:                        this .intersect(sbox, newBoundBox);
1582:                        return true;
1583:                    } else {
1584:                        // Negative volume.
1585:                        newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1586:                        newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1587:                        return false;
1588:                    }
1589:
1590:                    //      System.err.println("intersect Sphere ");
1591:                } else if (boundsObject.boundId == BOUNDING_POLYTOPE) {
1592:                    BoundingPolytope polytope = (BoundingPolytope) boundsObject;
1593:                    if (this .intersect(polytope)) {
1594:                        BoundingBox pbox = new BoundingBox(polytope); // convert polytope to box
1595:                        this .intersect(pbox, newBoundBox);
1596:                        return true;
1597:                    } else {
1598:                        // Negative volume.
1599:                        newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1600:                        newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1601:                        return false;
1602:                    }
1603:                } else {
1604:                    throw new IllegalArgumentException(J3dI18N
1605:                            .getString("BoundingBox7"));
1606:                }
1607:            }
1608:
1609:            /** 
1610:             * Test for intersection with an array of  bounds objects.
1611:             * @param boundsObjects an array of  bounds objects 
1612:             * @param newBoundBox the new bounding box which is the intersection of
1613:             *	      the boundsObject and this BoundingBox
1614:             * @return true or false indicating if an intersection occured 
1615:             */
1616:            public boolean intersect(Bounds[] boundsObjects,
1617:                    BoundingBox newBoundBox) {
1618:
1619:                if (boundsObjects == null || boundsObjects.length <= 0
1620:                        || boundsIsEmpty) {
1621:                    // Negative volume.
1622:                    newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1623:                    newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1624:                    return false;
1625:                }
1626:
1627:                int i = 0;
1628:                // find first non null bounds object
1629:                while (boundsObjects[i] == null && i < boundsObjects.length) {
1630:                    i++;
1631:                }
1632:
1633:                if (i >= boundsObjects.length) { // all bounds objects were empty
1634:                    // Negative volume.
1635:                    newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1636:                    newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1637:                    return false;
1638:                }
1639:
1640:                boolean status = false;
1641:                BoundingBox tbox = new BoundingBox();
1642:
1643:                for (; i < boundsObjects.length; i++) {
1644:                    if (boundsObjects[i] == null
1645:                            || boundsObjects[i].boundsIsEmpty)
1646:                        ;
1647:                    else if (boundsObjects[i].boundId == BOUNDING_BOX) {
1648:                        BoundingBox box = (BoundingBox) boundsObjects[i];
1649:                        // both boxes are axis aligned
1650:                        if (upper.x > box.lower.x && box.upper.x > lower.x
1651:                                && upper.y > box.lower.y
1652:                                && box.upper.y > lower.y
1653:                                && upper.z > box.lower.z
1654:                                && box.upper.z > lower.z) {
1655:
1656:                            if (upper.x > box.upper.x)
1657:                                newBoundBox.upper.x = box.upper.x;
1658:                            else
1659:                                newBoundBox.upper.x = upper.x;
1660:
1661:                            if (upper.y > box.upper.y)
1662:                                newBoundBox.upper.y = box.upper.y;
1663:                            else
1664:                                newBoundBox.upper.y = upper.y;
1665:
1666:                            if (upper.z > box.upper.z)
1667:                                newBoundBox.upper.z = box.upper.z;
1668:                            else
1669:                                newBoundBox.upper.z = upper.z;
1670:
1671:                            if (lower.x < box.lower.x)
1672:                                newBoundBox.lower.x = box.lower.x;
1673:                            else
1674:                                newBoundBox.lower.x = lower.x;
1675:
1676:                            if (lower.y < box.lower.y)
1677:                                newBoundBox.lower.y = box.lower.y;
1678:                            else
1679:                                newBoundBox.lower.y = lower.y;
1680:
1681:                            if (lower.z < box.lower.z)
1682:                                newBoundBox.lower.z = box.lower.z;
1683:                            else
1684:                                newBoundBox.lower.z = lower.z;
1685:                            status = true;
1686:                            newBoundBox.updateBoundsStates();
1687:                        }
1688:                    } else if (boundsObjects[i].boundId == BOUNDING_SPHERE) {
1689:                        BoundingSphere sphere = (BoundingSphere) boundsObjects[i];
1690:                        if (this .intersect(sphere)) {
1691:                            BoundingBox sbox = new BoundingBox(sphere); // convert sphere to box 
1692:                            this .intersect(sbox, tbox); // insersect two boxes
1693:                            if (status) {
1694:                                newBoundBox.combine(tbox);
1695:                            } else {
1696:                                newBoundBox.set(tbox);
1697:                                status = true;
1698:                            }
1699:                        }
1700:
1701:                    } else if (boundsObjects[i].boundId == BOUNDING_POLYTOPE) {
1702:                        BoundingPolytope polytope = (BoundingPolytope) boundsObjects[i];
1703:                        if (this .intersect(polytope)) {
1704:                            BoundingBox pbox = new BoundingBox(polytope); // convert polytope to box 
1705:                            this .intersect(pbox, tbox); // insersect two boxes
1706:                            if (status) {
1707:                                newBoundBox.combine(tbox);
1708:                            } else {
1709:                                newBoundBox.set(tbox);
1710:                                status = true;
1711:                            }
1712:                        }
1713:                    } else {
1714:                        throw new IllegalArgumentException(J3dI18N
1715:                                .getString("BoundingBox6"));
1716:                    }
1717:
1718:                    if (newBoundBox.boundsIsInfinite)
1719:                        break; // We're done. 
1720:                }
1721:                if (status == false) {
1722:                    // Negative volume.
1723:                    newBoundBox.setLower(1.0d, 1.0d, 1.0d);
1724:                    newBoundBox.setUpper(-1.0d, -1.0d, -1.0d);
1725:                }
1726:                return status;
1727:            }
1728:
1729:            /** 
1730:             * Finds closest bounding object that intersects this bounding box.
1731:             * @param boundsObjects an array of bounds objects 
1732:             * @return closest bounding object 
1733:             */
1734:            public Bounds closestIntersection(Bounds[] boundsObjects) {
1735:
1736:                if (boundsObjects == null || boundsObjects.length <= 0) {
1737:                    return null;
1738:                }
1739:
1740:                if (boundsIsEmpty) {
1741:                    return null;
1742:                }
1743:
1744:                getCenter();
1745:
1746:                double dis, far_dis, pdist, x, y, z, rad_sq;
1747:                double cenX = 0.0, cenY = 0.0, cenZ = 0.0;
1748:                boolean contains = false;
1749:                boolean inside;
1750:                boolean intersect = false;
1751:                double smallest_distance = Double.MAX_VALUE;
1752:                int i, j, index = 0;
1753:
1754:                for (i = 0; i < boundsObjects.length; i++) {
1755:                    if (boundsObjects[i] == null)
1756:                        ;
1757:
1758:                    else if (this .intersect(boundsObjects[i])) {
1759:                        intersect = true;
1760:                        if (boundsObjects[i].boundId == BOUNDING_BOX) {
1761:                            BoundingBox box = (BoundingBox) boundsObjects[i];
1762:                            cenX = (box.upper.x + box.lower.x) / 2.0;
1763:                            cenY = (box.upper.y + box.lower.y) / 2.0;
1764:                            cenZ = (box.upper.z + box.lower.z) / 2.0;
1765:                            dis = Math.sqrt((centroid.x - cenX)
1766:                                    * (centroid.x - cenX) + (centroid.y - cenY)
1767:                                    * (centroid.y - cenY) + (centroid.z - cenZ)
1768:                                    * (centroid.z - cenZ));
1769:                            inside = false;
1770:
1771:                            if (lower.x <= box.lower.x
1772:                                    && lower.y <= box.lower.y
1773:                                    && lower.z <= box.lower.z
1774:                                    && upper.x >= box.upper.x
1775:                                    && upper.y >= box.upper.y
1776:                                    && upper.z >= box.upper.z) { // box is contained 
1777:                                inside = true;
1778:                            }
1779:                            if (inside) {
1780:                                if (!contains) { // initialize smallest_distance for the first containment
1781:                                    index = i;
1782:                                    smallest_distance = dis;
1783:                                    contains = true;
1784:                                } else {
1785:                                    if (dis < smallest_distance) {
1786:                                        index = i;
1787:                                        smallest_distance = dis;
1788:                                    }
1789:                                }
1790:                            } else if (!contains) {
1791:                                if (dis < smallest_distance) {
1792:                                    index = i;
1793:                                    smallest_distance = dis;
1794:                                }
1795:                            }
1796:
1797:                        } else if (boundsObjects[i].boundId == BOUNDING_SPHERE) {
1798:                            BoundingSphere sphere = (BoundingSphere) boundsObjects[i];
1799:                            dis = Math.sqrt((centroid.x - sphere.center.x)
1800:                                    * (centroid.x - sphere.center.x)
1801:                                    + (centroid.y - sphere.center.y)
1802:                                    * (centroid.y - sphere.center.y)
1803:                                    + (centroid.z - sphere.center.z)
1804:                                    * (centroid.z - sphere.center.z));
1805:
1806:                            inside = false;
1807:
1808:                            // sphere sphere.center is inside box
1809:                            if (sphere.center.x <= upper.x
1810:                                    && sphere.center.x >= lower.x
1811:                                    && sphere.center.y <= upper.y
1812:                                    && sphere.center.y >= lower.y
1813:                                    && sphere.center.z <= upper.z
1814:                                    && sphere.center.z >= lower.z) {
1815:                                // check if sphere intersects any side 
1816:                                if (sphere.center.x - lower.x >= sphere.radius
1817:                                        && upper.x - sphere.center.x >= sphere.radius
1818:                                        && sphere.center.y - lower.y >= sphere.radius
1819:                                        && upper.y - sphere.center.y >= sphere.radius
1820:                                        && sphere.center.z - lower.z >= sphere.radius
1821:                                        && upper.z - sphere.center.z >= sphere.radius) {
1822:                                    // contains the sphere
1823:                                    inside = true;
1824:                                }
1825:                            }
1826:                            if (inside) {
1827:                                // initialize smallest_distance for the first containment
1828:                                if (!contains) {
1829:                                    index = i;
1830:                                    smallest_distance = dis;
1831:                                    contains = true;
1832:                                } else {
1833:                                    if (dis < smallest_distance) {
1834:                                        index = i;
1835:                                        smallest_distance = dis;
1836:                                    }
1837:                                }
1838:                            } else if (!contains) {
1839:                                if (dis < smallest_distance) {
1840:                                    index = i;
1841:                                    smallest_distance = dis;
1842:                                }
1843:                            }
1844:                        } else if (boundsObjects[i].boundId == BOUNDING_POLYTOPE) {
1845:                            BoundingPolytope polytope = (BoundingPolytope) boundsObjects[i];
1846:                            dis = Math.sqrt((centroid.x - polytope.centroid.x)
1847:                                    * (centroid.x - polytope.centroid.x)
1848:                                    + (centroid.y - polytope.centroid.y)
1849:                                    * (centroid.y - polytope.centroid.y)
1850:                                    + (centroid.z - polytope.centroid.z)
1851:                                    * (centroid.z - polytope.centroid.z));
1852:                            inside = true;
1853:                            for (j = 0; j < polytope.nVerts; j++) {
1854:                                if (polytope.verts[j].x < lower.x
1855:                                        || polytope.verts[j].y < lower.y
1856:                                        || polytope.verts[j].z < lower.z
1857:                                        || polytope.verts[j].x > upper.x
1858:                                        || polytope.verts[j].y > upper.y
1859:                                        || polytope.verts[j].z > upper.z) { // box contains polytope
1860:                                    inside = false;
1861:
1862:                                }
1863:
1864:                            }
1865:                            if (inside) {
1866:                                if (!contains) { // initialize smallest_distance for the first containment
1867:                                    index = i;
1868:                                    smallest_distance = dis;
1869:                                    contains = true;
1870:                                } else {
1871:                                    if (dis < smallest_distance) {
1872:                                        index = i;
1873:                                        smallest_distance = dis;
1874:                                    }
1875:                                }
1876:                            } else if (!contains) {
1877:                                if (dis < smallest_distance) {
1878:                                    index = i;
1879:                                    smallest_distance = dis;
1880:                                }
1881:                            }
1882:
1883:                        } else {
1884:                            throw new IllegalArgumentException(J3dI18N
1885:                                    .getString("BoundingBox9"));
1886:                        }
1887:                    }
1888:                }
1889:
1890:                if (intersect)
1891:                    return boundsObjects[index];
1892:                else
1893:                    return null;
1894:            }
1895:
1896:            /** 
1897:             * Tests for intersection of box and frustum.
1898:             * @param frustum  
1899:             * @return true if they intersect 
1900:             */
1901:            boolean intersect(CachedFrustum frustum) {
1902:
1903:                if (boundsIsEmpty)
1904:                    return false;
1905:
1906:                if (boundsIsInfinite)
1907:                    return true;
1908:
1909:                // System.err.println("intersect frustum with box="+this.toString()); 
1910:                // System.err.println("frustum "+frustum.toString()); 
1911:                // check if box and bounding box  of frustum intersect 
1912:                if ((upper.x < frustum.lower.x) || (lower.x > frustum.upper.x)
1913:                        || (upper.y < frustum.lower.y)
1914:                        || (lower.y > frustum.upper.y)
1915:                        || (upper.z < frustum.lower.z)
1916:                        || (lower.z > frustum.upper.z)) {
1917:
1918:                    // System.err.println("*** box and bounding box of frustum do not intersect");
1919:                    return false;
1920:                }
1921:
1922:                // check if all box points out any frustum plane  
1923:                int i = 5;
1924:                while (i >= 0) {
1925:                    Vector4d vc = frustum.clipPlanes[i--];
1926:                    if (((upper.x * vc.x + upper.y * vc.y + upper.z * vc.z + vc.w) < 0.0)
1927:                            && ((upper.x * vc.x + lower.y * vc.y + upper.z
1928:                                    * vc.z + vc.w) < 0.0)
1929:                            && ((upper.x * vc.x + lower.y * vc.y + lower.z
1930:                                    * vc.z + vc.w) < 0.0)
1931:                            && ((upper.x * vc.x + upper.y * vc.y + lower.z
1932:                                    * vc.z + vc.w) < 0.0)
1933:                            && ((lower.x * vc.x + upper.y * vc.y + upper.z
1934:                                    * vc.z + vc.w) < 0.0)
1935:                            && ((lower.x * vc.x + lower.y * vc.y + upper.z
1936:                                    * vc.z + vc.w) < 0.0)
1937:                            && ((lower.x * vc.x + lower.y * vc.y + lower.z
1938:                                    * vc.z + vc.w) < 0.0)
1939:                            && ((lower.x * vc.x + upper.y * vc.y + lower.z
1940:                                    * vc.z + vc.w) < 0.0)) {
1941:                        // all corners outside this frustum plane
1942:                        // System.err.println("*** all corners outside this frustum plane");
1943:                        return false;
1944:                    }
1945:                }
1946:
1947:                return true;
1948:            }
1949:
1950:            /** 
1951:             * Returns a string representation of this class.
1952:             */
1953:            public String toString() {
1954:                return new String("Bounding box: Lower=" + lower.x + " "
1955:                        + lower.y + " " + lower.z + " Upper=" + upper.x + " "
1956:                        + upper.y + " " + upper.z);
1957:            }
1958:
1959:            private void updateBoundsStates() {
1960:                if ((lower.x == Double.NEGATIVE_INFINITY)
1961:                        && (lower.y == Double.NEGATIVE_INFINITY)
1962:                        && (lower.z == Double.NEGATIVE_INFINITY)
1963:                        && (upper.x == Double.POSITIVE_INFINITY)
1964:                        && (upper.y == Double.POSITIVE_INFINITY)
1965:                        && (upper.z == Double.POSITIVE_INFINITY)) {
1966:                    boundsIsEmpty = false;
1967:                    boundsIsInfinite = true;
1968:                    return;
1969:                }
1970:
1971:                if (checkBoundsIsNaN()) {
1972:                    boundsIsEmpty = true;
1973:                    boundsIsInfinite = false;
1974:                    return;
1975:                } else {
1976:                    boundsIsInfinite = false;
1977:                    if (lower.x > upper.x || lower.y > upper.y
1978:                            || lower.z > upper.z) {
1979:                        boundsIsEmpty = true;
1980:                    } else {
1981:                        boundsIsEmpty = false;
1982:                    }
1983:                }
1984:            }
1985:
1986:            // For a infinite bounds. What is the centroid ?    
1987:            Point3d getCenter() {
1988:                if (centroid == null) {
1989:                    centroid = new Point3d();
1990:                }
1991:
1992:                centroid.x = (upper.x + lower.x) * 0.5;
1993:                centroid.y = (upper.y + lower.y) * 0.5;
1994:                centroid.z = (upper.z + lower.z) * 0.5;
1995:
1996:                return centroid;
1997:            }
1998:
1999:            void translate(BoundingBox bbox, Vector3d value) {
2000:                if (bbox == null || bbox.boundsIsEmpty) {
2001:                    // Negative volume.
2002:                    setLower(1.0d, 1.0d, 1.0d);
2003:                    setUpper(-1.0d, -1.0d, -1.0d);
2004:                    return;
2005:                }
2006:                if (bbox.boundsIsInfinite) {
2007:                    this .set(bbox);
2008:                    return;
2009:                }
2010:
2011:                lower.x = bbox.lower.x + value.x;
2012:                lower.y = bbox.lower.y + value.y;
2013:                lower.z = bbox.lower.z + value.z;
2014:                upper.x = bbox.upper.x + value.x;
2015:                upper.y = bbox.upper.y + value.y;
2016:                upper.z = bbox.upper.z + value.z;
2017:            }
2018:
2019:            /**
2020:             * if the passed the "region" is same type as this object
2021:             * then do a copy, otherwise clone the Bounds  and
2022:             * return
2023:             */
2024:            Bounds copy(Bounds r) {
2025:                if (r != null && this .boundId == r.boundId) {
2026:                    BoundingBox region = (BoundingBox) r;
2027:                    region.lower.x = lower.x;
2028:                    region.lower.y = lower.y;
2029:                    region.lower.z = lower.z;
2030:                    region.upper.x = upper.x;
2031:                    region.upper.y = upper.y;
2032:                    region.upper.z = upper.z;
2033:                    region.boundsIsEmpty = boundsIsEmpty;
2034:                    region.boundsIsInfinite = boundsIsInfinite;
2035:                    return region;
2036:                } else {
2037:                    return (Bounds) this .clone();
2038:                }
2039:            }
2040:
2041:            // Check is any of the bounds is a NaN, if yes, then
2042:            // set it an empty bounds
2043:            boolean checkBoundsIsNaN() {
2044:                if (Double.isNaN(lower.x + lower.y + lower.z + upper.x
2045:                        + upper.y + upper.z)) {
2046:                    return true;
2047:                }
2048:
2049:                return false;
2050:            }
2051:
2052:            int getPickType() {
2053:                return PickShape.PICKBOUNDINGBOX;
2054:            }
2055:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.