浏览代码

Added new empty concept to sphere with a negative radius. Modified containment / intersection functions to honor isEmpty and return false in this case

samfoster 5 年之前
父节点
当前提交
7548e1c4a1
共有 7 个文件被更改,包括 93 次插入18 次删除
  1. 8 4
      docs/api/en/math/Sphere.html
  2. 2 2
      docs/api/zh/math/Sphere.html
  3. 11 0
      src/Three.Legacy.js
  4. 6 0
      src/math/Box3.js
  5. 6 1
      src/math/Sphere.d.ts
  6. 23 4
      src/math/Sphere.js
  7. 37 7
      test/unit/src/math/Sphere.tests.js

+ 8 - 4
docs/api/en/math/Sphere.html

@@ -11,12 +11,13 @@
 		<h1>[name]</h1>
 
 		<p class="desc">A sphere defined by a center and radius.</p>
+		<p></p>
 
 		<h2>Constructor</h2>
 		<h3>[name]( [param:Vector3 center], [param:Float radius] )</h3>
 		<p>
 		[page:Vector3 center] - center of the sphere. Default is a [page:Vector3] at (0, 0, 0). <br />
-		[page:Float radius] - radius of the sphere. Default is 0.<br /><br />
+		[page:Float radius] - radius of the sphere. Default is -1.<br /><br />
 
 		Creates a new [name].
 
@@ -73,11 +74,14 @@
 		the distance will be negative.
 		</p>
 
-		<h3>[method:Boolean empty]()</h3>
-		<p>Checks to see if the sphere is empty (the radius set to 0).</p>
+		<h3>[method:Boolean isEmpty]()</h3>
+		<p>
+		Checks to see if the sphere is empty (the radius set to a negative number).</br>
+		Spheres with a radius of 0 contain only their center point and are not considererd to be empty.
+		</p>
 
 		<h3>[method:Sphere makeEmpty]()</h3>
-		<p>Makes the sphere empty by setting [page:.center center] to (0, 0, 0) and [page:.radius radius] to 0.</p>
+		<p>Makes the sphere empty by setting [page:.center center] to (0, 0, 0) and [page:.radius radius] to -1.</p>
 
 		<h3>[method:Boolean equals]( [param:Sphere sphere] )</h3>
 		<p>

+ 2 - 2
docs/api/zh/math/Sphere.html

@@ -70,8 +70,8 @@
 		若这个点,则距离将为负值。
 		</p>
 
-		<h3>[method:Boolean empty]()</h3>
-		<p>检查球是否为空(其半径设为了0).</p>
+		<h3>[method:Boolean isEmpty]()</h3>
+		<p>检查球是否为空(the radius set to a negative number).</p>
 
 		<h3>[method:Sphere makeEmpty]()</h3>
 		<p>Makes the sphere empty by setting [page:.center center] to (0, 0, 0) and [page:.radius radius] to 0.</p>

+ 11 - 0
src/Three.Legacy.js

@@ -542,6 +542,17 @@ Object.assign( Box3.prototype, {
 	}
 } );
 
+Object.assign( Sphere.prototype, {
+
+	empty: function() {
+
+		console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
+		return this.isEmpty();
+
+	},
+
+} );
+
 Frustum.prototype.setFromMatrix = function ( m ) {
 
 	console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );

+ 6 - 0
src/math/Box3.js

@@ -325,6 +325,12 @@ Object.assign( Box3.prototype, {
 
 	intersectsSphere: function ( sphere ) {
 
+		if( sphere.isEmpty() ) {
+
+			return false;
+
+		}
+
 		// Find the point on the AABB closest to the sphere center.
 		this.clampPoint( sphere.center, _vector );
 

+ 6 - 1
src/math/Sphere.d.ts

@@ -14,7 +14,7 @@ export class Sphere {
 	setFromPoints( points: Vector3[], optionalCenter?: Vector3 ): Sphere;
 	clone(): this;
 	copy( sphere: Sphere ): this;
-	empty(): boolean;
+	isEmpty(): boolean;
 	makeEmpty(): this;
 	containsPoint( point: Vector3 ): boolean;
 	distanceToPoint( point: Vector3 ): number;
@@ -27,4 +27,9 @@ export class Sphere {
 	translate( offset: Vector3 ): Sphere;
 	equals( sphere: Sphere ): boolean;
 
+	/**
+	 * @deprecated Use {@link Sphere#isEmpty .isEmpty()} instead.
+	 */
+	empty(): any;
+
 }

+ 23 - 4
src/math/Sphere.js

@@ -11,7 +11,7 @@ var _box = new Box3();
 function Sphere( center, radius ) {
 
 	this.center = ( center !== undefined ) ? center : new Vector3();
-	this.radius = ( radius !== undefined ) ? radius : 0;
+	this.radius = ( radius !== undefined ) ? radius : -1;
 
 }
 
@@ -69,16 +69,16 @@ Object.assign( Sphere.prototype, {
 
 	},
 
-	empty: function () {
+	isEmpty: function () {
 
-		return ( this.radius <= 0 );
+		return ( this.radius < 0 );
 
 	},
 
 	makeEmpty: function () {
 
 		this.center.set( 0, 0, 0 );
-		this.radius = 0;
+		this.radius = -1;
 
 		return this;
 
@@ -86,6 +86,12 @@ Object.assign( Sphere.prototype, {
 
 	containsPoint: function ( point ) {
 
+		if( this.isEmpty() ) {
+
+			return false;
+
+		}
+
 		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
 
 	},
@@ -98,6 +104,12 @@ Object.assign( Sphere.prototype, {
 
 	intersectsSphere: function ( sphere ) {
 
+		if( this.isEmpty() ) {
+
+			return false;
+
+		}
+
 		var radiusSum = this.radius + sphere.radius;
 
 		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
@@ -149,6 +161,13 @@ Object.assign( Sphere.prototype, {
 
 		}
 
+		if( this.isEmpty() ) {
+
+			target.makeEmpty();
+			return target;
+
+		}
+
 		target.set( this.center, this.center );
 		target.expandByScalar( this.radius );
 

+ 37 - 7
test/unit/src/math/Sphere.tests.js

@@ -108,13 +108,21 @@ export default QUnit.module( 'Maths', () => {
 
 		} );
 
-		QUnit.test( "empty", ( assert ) => {
+		QUnit.test( "isEmpty", ( assert ) => {
 
 			var a = new Sphere();
-			assert.ok( a.empty(), "Passed!" );
+			assert.ok( a.isEmpty(), "Passed!" );
 
 			a.set( one3, 1 );
-			assert.ok( ! a.empty(), "Passed!" );
+			assert.ok( ! a.isEmpty(), "Passed!" );
+
+			// Negative radius contains no points
+			a.set( one3, -1 );
+			assert.ok( a.isEmpty(), "Passed!" );
+
+			// Zero radius contains only the center point
+			a.set( one3, 0 );
+			assert.ok( ! a.isEmpty(), "Passed!" );
 
 		} );
 
@@ -122,8 +130,10 @@ export default QUnit.module( 'Maths', () => {
 
 			var a = new Sphere( one3.clone(), 1 );
 
+			assert.ok( ! a.isEmpty(), "Passed!" );
+
 			a.makeEmpty();
-			assert.ok( a.empty(), "Passed!" );
+			assert.ok( a.isEmpty(), "Passed!" );
 			assert.ok( a.center.equals( zero3 ), "Passed!" );
 
 		} );
@@ -135,6 +145,12 @@ export default QUnit.module( 'Maths', () => {
 			assert.ok( ! a.containsPoint( zero3 ), "Passed!" );
 			assert.ok( a.containsPoint( one3 ), "Passed!" );
 
+			a.set( zero3, 0 );
+			assert.ok( a.containsPoint( a.center ), "Passed!" );
+
+			a.makeEmpty();
+			assert.ok( !a.containsPoint( a.center ), "Passed" );
+
 		} );
 
 		QUnit.test( "distanceToPoint", ( assert ) => {
@@ -155,17 +171,23 @@ export default QUnit.module( 'Maths', () => {
 			assert.ok( a.intersectsSphere( b ), "Passed!" );
 			assert.ok( ! a.intersectsSphere( c ), "Passed!" );
 
+			a.makeEmpty();
+			assert.ok( !a.intersectsSphere( a ), "Passed!" );
+
 		} );
 
 		QUnit.test( "intersectsBox", ( assert ) => {
 
-			var a = new Sphere();
-			var b = new Sphere( new Vector3( - 5, - 5, - 5 ) );
+			var a = new Sphere( zero3, 1 );
+			var b = new Sphere( new Vector3( - 5, - 5, - 5 ), 1 );
 			var box = new Box3( zero3, one3 );
 
-			assert.strictEqual( a.intersectsBox( box ), true, "Check default sphere" );
+			assert.strictEqual( a.intersectsBox( box ), true, "Check unit sphere" );
 			assert.strictEqual( b.intersectsBox( box ), false, "Check shifted sphere" );
 
+			a.makeEmpty();
+			assert.strictEqual( a.intersectsBox( box ), false , "Check empty sphere");
+
 		} );
 
 		QUnit.test( "intersectsPlane", ( assert ) => {
@@ -179,6 +201,9 @@ export default QUnit.module( 'Maths', () => {
 			assert.ok( ! a.intersectsPlane( c ), "Passed!" );
 			assert.ok( ! a.intersectsPlane( d ), "Passed!" );
 
+			a.makeEmpty();
+			assert.ok( ! a.intersectsPlane( b ), "Passed!" );
+
 		} );
 
 		QUnit.test( "clampPoint", ( assert ) => {
@@ -205,6 +230,11 @@ export default QUnit.module( 'Maths', () => {
 			a.getBoundingBox( aabb );
 			assert.ok( aabb.equals( new Box3( zero3, zero3 ) ), "Passed!" );
 
+			// Empty sphere produces empty bounding box
+			a.makeEmpty();
+			a.getBoundingBox( aabb );
+			assert.ok( aabb.isEmpty(), "Passed!" );
+
 		} );
 
 		QUnit.test( "applyMatrix4", ( assert ) => {