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