|
1 | 1 |
|
2 | 2 | var widgets = require("@jupyter-widgets/base");
|
| 3 | +var THREE = require('three'); |
3 | 4 |
|
4 | 5 |
|
| 6 | +/** |
| 7 | + * Compute the box bounding all objects in a scene graph. |
| 8 | + * |
| 9 | + * Returns a unity box if no relevant objects were found. |
| 10 | + */ |
| 11 | +var computeBoundingBox = function() { |
| 12 | + var objectBoundingBox = new THREE.Box3(); |
| 13 | + |
| 14 | + return function computeBoundingBox(scene) { |
| 15 | + var boundingBox = new THREE.Box3(); |
| 16 | + scene.traverseVisible(function (object) { |
| 17 | + if (object.geometry) { |
| 18 | + object.geometry.computeBoundingBox(); |
| 19 | + objectBoundingBox.copy(object.geometry.boundingBox); |
| 20 | + objectBoundingBox.applyMatrix4(object.matrixWorld); |
| 21 | + boundingBox.union(objectBoundingBox); |
| 22 | + } |
| 23 | + }); |
| 24 | + if (boundingBox.isEmpty()) { |
| 25 | + boundingBox.min.set(-1, -1, -1); |
| 26 | + boundingBox.max.set(1, 1, 1); |
| 27 | + } |
| 28 | + return boundingBox; |
| 29 | + } |
| 30 | +}(); |
| 31 | + |
| 32 | + |
| 33 | +/** |
| 34 | + * Compute the sphere bounding all objects in a scene graph. |
| 35 | + * |
| 36 | + * Note: This is based on the bounding spheres of the individual objects |
| 37 | + * in the scene, and not the set of all points in the scene, and will |
| 38 | + * therefore not be optimal. |
| 39 | + * |
| 40 | + * Returns a unity sphere if no relevant objects were found. |
| 41 | + */ |
| 42 | +var computeBoundingSphere = function() { |
| 43 | + var objectBoundingSphere = new THREE.Sphere(); |
| 44 | + var vAB = new THREE.Vector3(); |
| 45 | + var d, rmin, rmax, rA, rB; |
| 46 | + return function computeBoundingSphere(scene) { |
| 47 | + // Current bounding sphere: |
| 48 | + var boundingSphere = null; |
| 49 | + scene.traverseVisible(function (object) { |
| 50 | + if (object.geometry) { |
| 51 | + object.geometry.computeBoundingSphere(); |
| 52 | + if (boundingSphere === null) { |
| 53 | + // First sphere found, store it |
| 54 | + boundingSphere = object.geometry.boundingSphere.clone(); |
| 55 | + boundingSphere.applyMatrix4(object.matrixWorld); |
| 56 | + return; // continue traverse |
| 57 | + } |
| 58 | + objectBoundingSphere.copy(object.geometry.boundingSphere); |
| 59 | + objectBoundingSphere.applyMatrix4(object.matrixWorld); |
| 60 | + |
| 61 | + rA = boundingSphere.radius; |
| 62 | + rB = objectBoundingSphere.radius; |
| 63 | + rmin = Math.min(rA, rB); |
| 64 | + rmax = Math.max(rA, rB); |
| 65 | + |
| 66 | + vAB.subVectors(objectBoundingSphere.center, boundingSphere.center); |
| 67 | + d = vAB.length(); |
| 68 | + if (d + rmin < rmax) { |
| 69 | + // Smallest sphere contained within largest |
| 70 | + if (rB > rA) { |
| 71 | + boundingSphere.copy(objectBoundingSphere); |
| 72 | + } |
| 73 | + return; // continue traverse |
| 74 | + } |
| 75 | + |
| 76 | + // Calculate new bounding-sphere: |
| 77 | + boundingSphere.radius = 0.5 * (rA + rB + d); |
| 78 | + boundingSphere.center.addScaledVector(vAB, 0.5 + rB); |
| 79 | + } |
| 80 | + }); |
| 81 | + if (boundingSphere === null) { |
| 82 | + return new THREE.Sphere(new THREE.Vector3(), 1); |
| 83 | + } |
| 84 | + return boundingSphere; |
| 85 | + } |
| 86 | +}(); |
5 | 87 |
|
6 | 88 | /**
|
7 | 89 | * Work around for notebook issue #2730.
|
@@ -81,4 +163,6 @@ var createModel = function(constructor, widget_manager, obj) {
|
81 | 163 |
|
82 | 164 | module.exports = {
|
83 | 165 | createModel: createModel,
|
| 166 | + computeBoundingSphere: computeBoundingSphere, |
| 167 | + computeBoundingBox: computeBoundingBox, |
84 | 168 | }
|
0 commit comments