123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- import { Vector3 } from './Vector3.js';
- /**
- * @author bhouston / http://clara.io
- * @author mrdoob / http://mrdoob.com/
- */
- function Triangle( a, b, c ) {
- this.a = ( a !== undefined ) ? a : new Vector3();
- this.b = ( b !== undefined ) ? b : new Vector3();
- this.c = ( c !== undefined ) ? c : new Vector3();
- }
- Object.assign( Triangle, {
- getNormal: function () {
- var v0 = new Vector3();
- return function getNormal( a, b, c, target ) {
- if ( target === undefined ) {
- console.warn( 'THREE.Triangle: .getNormal() target is now required' );
- target = new Vector3();
- }
- target.subVectors( c, b );
- v0.subVectors( a, b );
- target.cross( v0 );
- var targetLengthSq = target.lengthSq();
- if ( targetLengthSq > 0 ) {
- return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
- }
- return target.set( 0, 0, 0 );
- };
- }(),
- // static/instance method to calculate barycentric coordinates
- // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
- getBarycoord: function () {
- var v0 = new Vector3();
- var v1 = new Vector3();
- var v2 = new Vector3();
- return function getBarycoord( point, a, b, c, target ) {
- v0.subVectors( c, a );
- v1.subVectors( b, a );
- v2.subVectors( point, a );
- var dot00 = v0.dot( v0 );
- var dot01 = v0.dot( v1 );
- var dot02 = v0.dot( v2 );
- var dot11 = v1.dot( v1 );
- var dot12 = v1.dot( v2 );
- var denom = ( dot00 * dot11 - dot01 * dot01 );
- if ( target === undefined ) {
- console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
- target = new Vector3();
- }
- // collinear or singular triangle
- if ( denom === 0 ) {
- // arbitrary location outside of triangle?
- // not sure if this is the best idea, maybe should be returning undefined
- return target.set( - 2, - 1, - 1 );
- }
- var invDenom = 1 / denom;
- var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
- var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
- // barycentric coordinates must always sum to 1
- return target.set( 1 - u - v, v, u );
- };
- }(),
- containsPoint: function () {
- var v1 = new Vector3();
- return function containsPoint( point, a, b, c ) {
- Triangle.getBarycoord( point, a, b, c, v1 );
- return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
- };
- }()
- } );
- Object.assign( Triangle.prototype, {
- set: function ( a, b, c ) {
- this.a.copy( a );
- this.b.copy( b );
- this.c.copy( c );
- return this;
- },
- setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
- this.a.copy( points[ i0 ] );
- this.b.copy( points[ i1 ] );
- this.c.copy( points[ i2 ] );
- return this;
- },
- clone: function () {
- return new this.constructor().copy( this );
- },
- copy: function ( triangle ) {
- this.a.copy( triangle.a );
- this.b.copy( triangle.b );
- this.c.copy( triangle.c );
- return this;
- },
- getArea: function () {
- var v0 = new Vector3();
- var v1 = new Vector3();
- return function getArea() {
- v0.subVectors( this.c, this.b );
- v1.subVectors( this.a, this.b );
- return v0.cross( v1 ).length() * 0.5;
- };
- }(),
- getMidpoint: function ( target ) {
- if ( target === undefined ) {
- console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
- target = new Vector3();
- }
- return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
- },
- getNormal: function ( target ) {
- return Triangle.getNormal( this.a, this.b, this.c, target );
- },
- getPlane: function ( target ) {
- if ( target === undefined ) {
- console.warn( 'THREE.Triangle: .getPlane() target is now required' );
- target = new Vector3();
- }
- return target.setFromCoplanarPoints( this.a, this.b, this.c );
- },
- getBarycoord: function ( point, target ) {
- return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
- },
- containsPoint: function ( point ) {
- return Triangle.containsPoint( point, this.a, this.b, this.c );
- },
- intersectsBox: function ( box ) {
- return box.intersectsTriangle( this );
- },
- closestPointToPoint: function () {
- var vab = new Vector3();
- var vac = new Vector3();
- var vbc = new Vector3();
- var vap = new Vector3();
- var vbp = new Vector3();
- var vcp = new Vector3();
- return function closestPointToPoint( p, target ) {
- if ( target === undefined ) {
- console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
- target = new Vector3();
- }
- var a = this.a, b = this.b, c = this.c;
- var v, w;
- // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
- // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
- // under the accompanying license; see chapter 5.1.5 for detailed explanation.
- // basically, we're distinguishing which of the voronoi regions of the triangle
- // the point lies in with the minimum amount of redundant computation.
- vab.subVectors( b, a );
- vac.subVectors( c, a );
- vap.subVectors( p, a );
- var d1 = vab.dot( vap );
- var d2 = vac.dot( vap );
- if ( d1 <= 0 && d2 <= 0 ) {
- // vertex region of A; barycentric coords (1, 0, 0)
- return target.copy( a );
- }
- vbp.subVectors( p, b );
- var d3 = vab.dot( vbp );
- var d4 = vac.dot( vbp );
- if ( d3 >= 0 && d4 <= d3 ) {
- // vertex region of B; barycentric coords (0, 1, 0)
- return target.copy( b );
- }
- var vc = d1 * d4 - d3 * d2;
- if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
- v = d1 / ( d1 - d3 );
- // edge region of AB; barycentric coords (1-v, v, 0)
- return target.copy( a ).addScaledVector( vab, v );
- }
- vcp.subVectors( p, c );
- var d5 = vab.dot( vcp );
- var d6 = vac.dot( vcp );
- if ( d6 >= 0 && d5 <= d6 ) {
- // vertex region of C; barycentric coords (0, 0, 1)
- return target.copy( c );
- }
- var vb = d5 * d2 - d1 * d6;
- if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
- w = d2 / ( d2 - d6 );
- // edge region of AC; barycentric coords (1-w, 0, w)
- return target.copy( a ).addScaledVector( vac, w );
- }
- var va = d3 * d6 - d5 * d4;
- if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
- vbc.subVectors( c, b );
- w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
- // edge region of BC; barycentric coords (0, 1-w, w)
- return target.copy( b ).addScaledVector( vbc, w ); // edge region of BC
- }
- // face region
- var denom = 1 / ( va + vb + vc );
- // u = va * denom
- v = vb * denom;
- w = vc * denom;
- return target.copy( a ).addScaledVector( vab, v ).addScaledVector( vac, w );
- };
- }(),
- equals: function ( triangle ) {
- return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
- }
- } );
- export { Triangle };
|