Sphere.tests.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /* global QUnit */
  2. import { Box3 } from '../../../../src/math/Box3.js';
  3. import { Vector3 } from '../../../../src/math/Vector3.js';
  4. import { Sphere } from '../../../../src/math/Sphere.js';
  5. import { Plane } from '../../../../src/math/Plane.js';
  6. import { Matrix4 } from '../../../../src/math/Matrix4.js';
  7. import {
  8. zero3,
  9. one3,
  10. two3,
  11. eps
  12. } from '../../utils/math-constants.js';
  13. export default QUnit.module( 'Maths', () => {
  14. QUnit.module( 'Sphere', () => {
  15. // INSTANCING
  16. QUnit.test( 'Instancing', ( assert ) => {
  17. let a = new Sphere();
  18. assert.ok( a.center.equals( zero3 ), 'Passed!' );
  19. assert.ok( a.radius == - 1, 'Passed!' );
  20. a = new Sphere( one3.clone(), 1 );
  21. assert.ok( a.center.equals( one3 ), 'Passed!' );
  22. assert.ok( a.radius == 1, 'Passed!' );
  23. } );
  24. // PUBLIC
  25. QUnit.test( 'isSphere', ( assert ) => {
  26. const a = new Sphere();
  27. assert.ok( a.isSphere === true, 'Passed!' );
  28. const b = new Box3();
  29. assert.ok( ! b.isSphere, 'Passed!' );
  30. } );
  31. QUnit.test( 'set', ( assert ) => {
  32. const a = new Sphere();
  33. assert.ok( a.center.equals( zero3 ), 'Passed!' );
  34. assert.ok( a.radius == - 1, 'Passed!' );
  35. a.set( one3, 1 );
  36. assert.ok( a.center.equals( one3 ), 'Passed!' );
  37. assert.ok( a.radius == 1, 'Passed!' );
  38. } );
  39. QUnit.test( 'setFromPoints', ( assert ) => {
  40. const a = new Sphere();
  41. const expectedCenter = new Vector3( 0.9330126941204071, 0, 0 );
  42. let expectedRadius = 1.3676668773461689;
  43. const optionalCenter = new Vector3( 1, 1, 1 );
  44. const points = [
  45. new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ),
  46. new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ),
  47. new Vector3( 1, 1, 0 ), new Vector3( 0.8660253882408142, 0.5, 0 ),
  48. new Vector3( - 0, 0.5, 0.8660253882408142 ), new Vector3( 1.8660253882408142, 0.5, 0 ),
  49. new Vector3( 0, 0.5, - 0.8660253882408142 ), new Vector3( 0.8660253882408142, 0.5, - 0 ),
  50. new Vector3( 0.8660253882408142, - 0.5, 0 ), new Vector3( - 0, - 0.5, 0.8660253882408142 ),
  51. new Vector3( 1.8660253882408142, - 0.5, 0 ), new Vector3( 0, - 0.5, - 0.8660253882408142 ),
  52. new Vector3( 0.8660253882408142, - 0.5, - 0 ), new Vector3( - 0, - 1, 0 ),
  53. new Vector3( - 0, - 1, 0 ), new Vector3( 0, - 1, 0 ),
  54. new Vector3( 0, - 1, - 0 ), new Vector3( - 0, - 1, - 0 ),
  55. ];
  56. a.setFromPoints( points );
  57. assert.ok( Math.abs( a.center.x - expectedCenter.x ) <= eps, 'Default center: check center.x' );
  58. assert.ok( Math.abs( a.center.y - expectedCenter.y ) <= eps, 'Default center: check center.y' );
  59. assert.ok( Math.abs( a.center.z - expectedCenter.z ) <= eps, 'Default center: check center.z' );
  60. assert.ok( Math.abs( a.radius - expectedRadius ) <= eps, 'Default center: check radius' );
  61. expectedRadius = 2.5946195770400102;
  62. a.setFromPoints( points, optionalCenter );
  63. assert.ok( Math.abs( a.center.x - optionalCenter.x ) <= eps, 'Optional center: check center.x' );
  64. assert.ok( Math.abs( a.center.y - optionalCenter.y ) <= eps, 'Optional center: check center.y' );
  65. assert.ok( Math.abs( a.center.z - optionalCenter.z ) <= eps, 'Optional center: check center.z' );
  66. assert.ok( Math.abs( a.radius - expectedRadius ) <= eps, 'Optional center: check radius' );
  67. } );
  68. QUnit.todo( 'clone', ( assert ) => {
  69. assert.ok( false, 'everything\'s gonna be alright' );
  70. } );
  71. QUnit.test( 'copy', ( assert ) => {
  72. const a = new Sphere( one3.clone(), 1 );
  73. const b = new Sphere().copy( a );
  74. assert.ok( b.center.equals( one3 ), 'Passed!' );
  75. assert.ok( b.radius == 1, 'Passed!' );
  76. // ensure that it is a true copy
  77. a.center = zero3;
  78. a.radius = 0;
  79. assert.ok( b.center.equals( one3 ), 'Passed!' );
  80. assert.ok( b.radius == 1, 'Passed!' );
  81. } );
  82. QUnit.test( 'isEmpty', ( assert ) => {
  83. const a = new Sphere();
  84. assert.ok( a.isEmpty(), 'Passed!' );
  85. a.set( one3, 1 );
  86. assert.ok( ! a.isEmpty(), 'Passed!' );
  87. // Negative radius contains no points
  88. a.set( one3, - 1 );
  89. assert.ok( a.isEmpty(), 'Passed!' );
  90. // Zero radius contains only the center point
  91. a.set( one3, 0 );
  92. assert.ok( ! a.isEmpty(), 'Passed!' );
  93. } );
  94. QUnit.test( 'makeEmpty', ( assert ) => {
  95. const a = new Sphere( one3.clone(), 1 );
  96. assert.ok( ! a.isEmpty(), 'Passed!' );
  97. a.makeEmpty();
  98. assert.ok( a.isEmpty(), 'Passed!' );
  99. assert.ok( a.center.equals( zero3 ), 'Passed!' );
  100. } );
  101. QUnit.test( 'containsPoint', ( assert ) => {
  102. const a = new Sphere( one3.clone(), 1 );
  103. assert.ok( ! a.containsPoint( zero3 ), 'Passed!' );
  104. assert.ok( a.containsPoint( one3 ), 'Passed!' );
  105. a.set( zero3, 0 );
  106. assert.ok( a.containsPoint( a.center ), 'Passed!' );
  107. } );
  108. QUnit.test( 'distanceToPoint', ( assert ) => {
  109. const a = new Sphere( one3.clone(), 1 );
  110. assert.ok( ( a.distanceToPoint( zero3 ) - 0.7320 ) < 0.001, 'Passed!' );
  111. assert.ok( a.distanceToPoint( one3 ) === - 1, 'Passed!' );
  112. } );
  113. QUnit.test( 'intersectsSphere', ( assert ) => {
  114. const a = new Sphere( one3.clone(), 1 );
  115. const b = new Sphere( zero3.clone(), 1 );
  116. const c = new Sphere( zero3.clone(), 0.25 );
  117. assert.ok( a.intersectsSphere( b ), 'Passed!' );
  118. assert.ok( ! a.intersectsSphere( c ), 'Passed!' );
  119. } );
  120. QUnit.test( 'intersectsBox', ( assert ) => {
  121. const a = new Sphere( zero3, 1 );
  122. const b = new Sphere( new Vector3( - 5, - 5, - 5 ), 1 );
  123. const box = new Box3( zero3, one3 );
  124. assert.strictEqual( a.intersectsBox( box ), true, 'Check unit sphere' );
  125. assert.strictEqual( b.intersectsBox( box ), false, 'Check shifted sphere' );
  126. } );
  127. QUnit.test( 'intersectsPlane', ( assert ) => {
  128. const a = new Sphere( zero3.clone(), 1 );
  129. const b = new Plane( new Vector3( 0, 1, 0 ), 1 );
  130. const c = new Plane( new Vector3( 0, 1, 0 ), 1.25 );
  131. const d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 );
  132. assert.ok( a.intersectsPlane( b ), 'Passed!' );
  133. assert.ok( ! a.intersectsPlane( c ), 'Passed!' );
  134. assert.ok( ! a.intersectsPlane( d ), 'Passed!' );
  135. } );
  136. QUnit.test( 'clampPoint', ( assert ) => {
  137. const a = new Sphere( one3.clone(), 1 );
  138. const point = new Vector3();
  139. a.clampPoint( new Vector3( 1, 1, 3 ), point );
  140. assert.ok( point.equals( new Vector3( 1, 1, 2 ) ), 'Passed!' );
  141. a.clampPoint( new Vector3( 1, 1, - 3 ), point );
  142. assert.ok( point.equals( new Vector3( 1, 1, 0 ) ), 'Passed!' );
  143. } );
  144. QUnit.test( 'getBoundingBox', ( assert ) => {
  145. const a = new Sphere( one3.clone(), 1 );
  146. const aabb = new Box3();
  147. a.getBoundingBox( aabb );
  148. assert.ok( aabb.equals( new Box3( zero3, two3 ) ), 'Passed!' );
  149. a.set( zero3, 0 );
  150. a.getBoundingBox( aabb );
  151. assert.ok( aabb.equals( new Box3( zero3, zero3 ) ), 'Passed!' );
  152. // Empty sphere produces empty bounding box
  153. a.makeEmpty();
  154. a.getBoundingBox( aabb );
  155. assert.ok( aabb.isEmpty(), 'Passed!' );
  156. } );
  157. QUnit.test( 'applyMatrix4', ( assert ) => {
  158. const a = new Sphere( one3.clone(), 1 );
  159. const m = new Matrix4().makeTranslation( 1, - 2, 1 );
  160. const aabb1 = new Box3();
  161. const aabb2 = new Box3();
  162. a.clone().applyMatrix4( m ).getBoundingBox( aabb1 );
  163. a.getBoundingBox( aabb2 );
  164. assert.ok( aabb1.equals( aabb2.applyMatrix4( m ) ), 'Passed!' );
  165. } );
  166. QUnit.test( 'translate', ( assert ) => {
  167. const a = new Sphere( one3.clone(), 1 );
  168. a.translate( one3.clone().negate() );
  169. assert.ok( a.center.equals( zero3 ), 'Passed!' );
  170. } );
  171. QUnit.test( 'expandByPoint', ( assert ) => {
  172. const a = new Sphere( zero3.clone(), 1 );
  173. const p = new Vector3( 2, 0, 0 );
  174. assert.ok( a.containsPoint( p ) === false, 'a does not contain p' );
  175. a.expandByPoint( p );
  176. assert.ok( a.containsPoint( p ) === true, 'a does contain p' );
  177. assert.ok( a.center.equals( new Vector3( 0.5, 0, 0 ) ), 'Passed!' );
  178. assert.ok( a.radius === 1.5, 'Passed!' );
  179. } );
  180. QUnit.test( 'union', ( assert ) => {
  181. const a = new Sphere( zero3.clone(), 1 );
  182. const b = new Sphere( new Vector3( 2, 0, 0 ), 1 );
  183. a.union( b );
  184. assert.ok( a.center.equals( new Vector3( 1, 0, 0 ) ), 'Passed!' );
  185. assert.ok( a.radius === 2, 'Passed!' );
  186. // d contains c (demonstrates why it is necessary to process two points in union)
  187. const c = new Sphere( new Vector3(), 1 );
  188. const d = new Sphere( new Vector3( 1, 0, 0 ), 4 );
  189. c.union( d );
  190. assert.ok( c.center.equals( new Vector3( 1, 0, 0 ) ), 'Passed!' );
  191. assert.ok( c.radius === 4, 'Passed!' );
  192. // edge case: both spheres have the same center point
  193. const e = new Sphere( new Vector3(), 1 );
  194. const f = new Sphere( new Vector3(), 4 );
  195. e.union( f );
  196. assert.ok( e.center.equals( new Vector3( 0, 0, 0 ) ), 'Passed!' );
  197. assert.ok( e.radius === 4, 'Passed!' );
  198. } );
  199. QUnit.test( 'equals', ( assert ) => {
  200. const a = new Sphere();
  201. const b = new Sphere( new Vector3( 1, 0, 0 ) );
  202. const c = new Sphere( new Vector3( 1, 0, 0 ), 1.0 );
  203. assert.strictEqual( a.equals( b ), false, 'a does not equal b' );
  204. assert.strictEqual( a.equals( c ), false, 'a does not equal c' );
  205. assert.strictEqual( b.equals( c ), false, 'b does not equal c' );
  206. a.copy( b );
  207. assert.strictEqual( a.equals( b ), true, 'a equals b after copy()' );
  208. } );
  209. } );
  210. } );