1 module des.math.linear.triangle; 2 3 import des.ts; 4 import des.stdx.traits; 5 6 import des.math.linear.vector; 7 import des.math.linear.matrix; 8 import des.math.linear.ray; 9 10 /// 11 struct Triangle(T) if( isFloatingPoint!T ) 12 { 13 /// 14 alias Vector3!T vectype; 15 16 /// 17 vectype[3] pnt; 18 19 pure: 20 21 /// 22 this( in vectype P0, in vectype P1, in vectype P2 ) 23 { 24 pnt[0] = P0; 25 pnt[1] = P1; 26 pnt[2] = P2; 27 } 28 29 @property 30 { 31 /// 32 vectype perp() const { return cross( pnt[1]-pnt[0], pnt[2]-pnt[0] ); } 33 /// 34 vectype norm() const { return perp.e; } 35 /// 36 T area() const { return perp.len / 2.0; } 37 /// 38 vectype center() const { return (pnt[0] + pnt[1] + pnt[2]) / 3.0f; } 39 } 40 41 /// affine transform 42 auto tr(X)( in Matrix!(4,4,X) mtr ) const 43 { 44 return Triangle!T( (mtr * vec!(4,T,"x y z w")( pnt[0], 1 )).xyz, 45 (mtr * vec!(4,T,"x y z w")( pnt[1], 1 )).xyz, 46 (mtr * vec!(4,T,"x y z w")( pnt[2], 1 )).xyz ); 47 } 48 49 /// 50 Ray!(T)[3] toRays() const 51 { 52 alias Ray!T st; 53 return [ st.fromPoints( pnt[0], pnt[1] ), 54 st.fromPoints( pnt[1], pnt[2] ), 55 st.fromPoints( pnt[2], pnt[0] ) ]; 56 } 57 58 /+ высота проведённая из точки это отрезок, 59 соединяющий проекцию точки на плоскость и 60 саму точку (Ray) +/ 61 /// 62 auto altitude( in vectype pp ) const 63 { 64 auto n = norm; 65 auto dst = n * dot( n, pp-pnt[0] ); 66 return Ray!T( pp - dst, dst ); 67 } 68 69 /// 70 auto project(F)( in Ray!F seg ) const 71 { 72 auto n = norm; 73 auto dst1 = dot( n, seg.pos-pnt[0] ); 74 auto dst2 = dot( n, seg.end-pnt[0] ); 75 auto diff = dst1 - dst2; 76 return Ray!T( seg.png - n * dst1, 77 seg.dir + n * diff ); 78 } 79 80 /// 81 auto intersect(F)( in Ray!F seg ) const 82 { return seg.intersect( project(seg) ); } 83 } 84 85 /// 86 alias Triangle!float fTriangle; 87 /// 88 alias Triangle!double dTriangle; 89 /// 90 alias Triangle!real rTriangle; 91 92 /// 93 unittest 94 { 95 auto poly = fTriangle( vec3(0,0,0), vec3(1,0,0), vec3(0,1,0) ); 96 assertEq( poly.area, 0.5f ); 97 assertEq( poly.norm, vec3(0,0,1) ); 98 99 auto pnt = vec3( 2,2,2 ); 100 auto a = poly.altitude( pnt ); 101 assertEq( a.pos, vec3(2,2,0) ); 102 assertEq( a.dir, vec3(0,0,2) ); 103 }