#ifndef STIM_PLANE_H #define STIM_PLANE_H #include #include #include #include namespace stim { template class plane; } template CUDA_CALLABLE stim::plane operator-(stim::plane v); namespace stim { template class plane { protected: stim::vec3 P; stim::vec3 N; stim::vec3 U; ///Initializes the plane with standard coordinates. /// CUDA_CALLABLE void init() { P = stim::vec3(0, 0, 0); N = stim::vec3(0, 0, 1); U = stim::vec3(1, 0, 0); } public: CUDA_CALLABLE plane() { init(); } CUDA_CALLABLE plane(vec3 n, vec3 p = vec3(0, 0, 0)) { init(); P = p; rotate(n.norm()); } CUDA_CALLABLE plane(T z_pos) { init(); P[2] = z_pos; } //create a plane from three points (a triangle) CUDA_CALLABLE plane(vec3 a, vec3 b, vec3 c) { init(); P = c; stim::vec3 n = (c - a).cross(b - a); try { if(n.len() != 0) { rotate(n.norm()); } else { throw 42; } } catch(int i) { std::cerr << "No plane can be creates as all points a,b,c lie on a straight line" << std::endl; } } template< typename U > CUDA_CALLABLE operator plane() { plane result(N, P); return result; } CUDA_CALLABLE vec3 n() { return N; } CUDA_CALLABLE vec3 p() { return P; } CUDA_CALLABLE vec3 u() { return U; } ///flip the plane front-to-back CUDA_CALLABLE plane flip(){ plane result = *this; result.N = -result.N; return result; } //determines how a vector v intersects the plane (1 = intersects front, 0 = within plane, -1 = intersects back) CUDA_CALLABLE int face(vec3 v){ T dprod = v.dot(N); //get the dot product between v and N //conditional returns the appropriate value if(dprod < 0) return 1; else if(dprod > 0) return -1; else return 0; } //determine on which side of the plane a point lies (1 = front, 0 = on the plane, -1 = bac k) CUDA_CALLABLE int side(vec3 p){ vec3 v = p - P; //get the vector from P to the query point p return face(v); } //compute the component of v that is perpendicular to the plane CUDA_CALLABLE vec3 perpendicular(vec3 v){ return N * v.dot(N); } //compute the projection of v in the plane CUDA_CALLABLE vec3 parallel(vec3 v){ return v - perpendicular(v); } CUDA_CALLABLE void setU(vec3 v) { U = (parallel(v.norm())).norm(); } CUDA_CALLABLE void decompose(vec3 v, vec3& para, vec3& perp){ perp = N * v.dot(N); para = v - perp; } //get both the parallel and perpendicular components of a vector v w.r.t. the plane CUDA_CALLABLE void project(vec3 v, vec3 &v_par, vec3 &v_perp){ v_perp = v.dot(N); v_par = v - v_perp; } //compute the reflection of v off of the plane CUDA_CALLABLE vec3 reflect(vec3 v){ //compute the reflection using N_prime as the plane normal vec3 par = parallel(v); vec3 r = (-v) + par * 2; return r; } CUDA_CALLABLE stim::plane operator-() { stim::plane p = *this; //negate the normal vector p.N = -p.N; return p; } //output a string std::string str(){ std::stringstream ss; ss<<"P: "< n) { quaternion q; q.CreateRotation(N, n); N = q.toMatrix3() * N; U = q.toMatrix3() * U; } CUDA_CALLABLE void rotate(vec3 n, vec3 &Y) { quaternion q; q.CreateRotation(N, n); N = q.toMatrix3() * N; U = q.toMatrix3() * U; Y = q.toMatrix3() * Y; } CUDA_CALLABLE void rotate(vec3 n, vec3 &X, vec3 &Y) { quaternion q; q.CreateRotation(N, n); N = q.toMatrix3() * N; U = q.toMatrix3() * U; X = q.toMatrix3() * X; Y = q.toMatrix3() * Y; } }; } #endif