Triangle.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import { Vector3 } from './Vector3.js';
  2. import { Line3 } from './Line3.js';
  3. import { Plane } from './Plane.js';
  4. /**
  5. * @author bhouston / http://clara.io
  6. * @author mrdoob / http://mrdoob.com/
  7. */
  8. function Triangle( a, b, c ) {
  9. this.a = ( a !== undefined ) ? a : new Vector3();
  10. this.b = ( b !== undefined ) ? b : new Vector3();
  11. this.c = ( c !== undefined ) ? c : new Vector3();
  12. }
  13. Object.assign( Triangle, {
  14. normal: function () {
  15. var v0 = new Vector3();
  16. return function normal( a, b, c, target ) {
  17. if ( target === undefined ) {
  18. console.warn( 'THREE.Triangle: .normal() target is now required' );
  19. target = new Vector3();
  20. }
  21. target.subVectors( c, b );
  22. v0.subVectors( a, b );
  23. target.cross( v0 );
  24. var targetLengthSq = target.lengthSq();
  25. if ( targetLengthSq > 0 ) {
  26. return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
  27. }
  28. return target.set( 0, 0, 0 );
  29. };
  30. }(),
  31. // static/instance method to calculate barycentric coordinates
  32. // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
  33. barycoordFromPoint: function () {
  34. var v0 = new Vector3();
  35. var v1 = new Vector3();
  36. var v2 = new Vector3();
  37. return function barycoordFromPoint( point, a, b, c, target ) {
  38. v0.subVectors( c, a );
  39. v1.subVectors( b, a );
  40. v2.subVectors( point, a );
  41. var dot00 = v0.dot( v0 );
  42. var dot01 = v0.dot( v1 );
  43. var dot02 = v0.dot( v2 );
  44. var dot11 = v1.dot( v1 );
  45. var dot12 = v1.dot( v2 );
  46. var denom = ( dot00 * dot11 - dot01 * dot01 );
  47. if ( target === undefined ) {
  48. console.warn( 'THREE.Triangle: .barycoordFromPoint() target is now required' );
  49. target = new Vector3();
  50. }
  51. // collinear or singular triangle
  52. if ( denom === 0 ) {
  53. // arbitrary location outside of triangle?
  54. // not sure if this is the best idea, maybe should be returning undefined
  55. return target.set( - 2, - 1, - 1 );
  56. }
  57. var invDenom = 1 / denom;
  58. var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
  59. var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
  60. // barycentric coordinates must always sum to 1
  61. return target.set( 1 - u - v, v, u );
  62. };
  63. }(),
  64. containsPoint: function () {
  65. var v1 = new Vector3();
  66. return function containsPoint( point, a, b, c ) {
  67. Triangle.barycoordFromPoint( point, a, b, c, v1 );
  68. return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
  69. };
  70. }()
  71. } );
  72. Object.assign( Triangle.prototype, {
  73. set: function ( a, b, c ) {
  74. this.a.copy( a );
  75. this.b.copy( b );
  76. this.c.copy( c );
  77. return this;
  78. },
  79. setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
  80. this.a.copy( points[ i0 ] );
  81. this.b.copy( points[ i1 ] );
  82. this.c.copy( points[ i2 ] );
  83. return this;
  84. },
  85. clone: function () {
  86. return new this.constructor().copy( this );
  87. },
  88. copy: function ( triangle ) {
  89. this.a.copy( triangle.a );
  90. this.b.copy( triangle.b );
  91. this.c.copy( triangle.c );
  92. return this;
  93. },
  94. area: function () {
  95. var v0 = new Vector3();
  96. var v1 = new Vector3();
  97. return function area() {
  98. v0.subVectors( this.c, this.b );
  99. v1.subVectors( this.a, this.b );
  100. return v0.cross( v1 ).length() * 0.5;
  101. };
  102. }(),
  103. midpoint: function ( target ) {
  104. if ( target === undefined ) {
  105. console.warn( 'THREE.Triangle: .midpoint() target is now required' );
  106. target = new Vector3();
  107. }
  108. return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
  109. },
  110. normal: function ( target ) {
  111. return Triangle.normal( this.a, this.b, this.c, target );
  112. },
  113. plane: function ( target ) {
  114. if ( target === undefined ) {
  115. console.warn( 'THREE.Triangle: .plane() target is now required' );
  116. target = new Vector3();
  117. }
  118. return target.setFromCoplanarPoints( this.a, this.b, this.c );
  119. },
  120. barycoordFromPoint: function ( point, target ) {
  121. return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, target );
  122. },
  123. containsPoint: function ( point ) {
  124. return Triangle.containsPoint( point, this.a, this.b, this.c );
  125. },
  126. intersectsBox: function ( box ) {
  127. return box.intersectsTriangle( this );
  128. },
  129. closestPointToPoint: function () {
  130. var plane = new Plane();
  131. var edgeList = [ new Line3(), new Line3(), new Line3() ];
  132. var projectedPoint = new Vector3();
  133. var closestPoint = new Vector3();
  134. return function closestPointToPoint( point, target ) {
  135. if ( target === undefined ) {
  136. console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
  137. target = new Vector3();
  138. }
  139. var minDistance = Infinity;
  140. // project the point onto the plane of the triangle
  141. plane.setFromCoplanarPoints( this.a, this.b, this.c );
  142. plane.projectPoint( point, projectedPoint );
  143. // check if the projection lies within the triangle
  144. if ( this.containsPoint( projectedPoint ) === true ) {
  145. // if so, this is the closest point
  146. target.copy( projectedPoint );
  147. } else {
  148. // if not, the point falls outside the triangle. the target is the closest point to the triangle's edges or vertices
  149. edgeList[ 0 ].set( this.a, this.b );
  150. edgeList[ 1 ].set( this.b, this.c );
  151. edgeList[ 2 ].set( this.c, this.a );
  152. for ( var i = 0; i < edgeList.length; i ++ ) {
  153. edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
  154. var distance = projectedPoint.distanceToSquared( closestPoint );
  155. if ( distance < minDistance ) {
  156. minDistance = distance;
  157. target.copy( closestPoint );
  158. }
  159. }
  160. }
  161. return target;
  162. };
  163. }(),
  164. equals: function ( triangle ) {
  165. return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
  166. }
  167. } );
  168. export { Triangle };
粤ICP备19079148号