#ifndef RTS_RECT_H #define RTS_RECT_H //enable CUDA_CALLABLE macro #include "../cuda/callable.h" #include "../math/vector.h" #include "../math/triangle.h" #include "../math/quaternion.h" #include #include #include namespace stim{ //template for a rectangle class in ND space template struct rect { /* ^ O | | Y C | | O---------X---------> */ private: stim::vec C; stim::vec X; stim::vec Y; CUDA_CALLABLE void scale(T factor){ X *= factor; Y *= factor; } CUDA_CALLABLE void normal(vec n){ //orient the rectangle along the specified normal n = n.norm(); //normalize, just in case vec n_current = X.cross(Y).norm(); //compute the current normal quaternion q; //create a quaternion q.CreateRotation(n_current, n); //initialize a rotation from n_current to n //apply the quaternion to the vectors and position X = q.toMatrix3() * X; Y = q.toMatrix3() * Y; } CUDA_CALLABLE void init(){ C = vec(0, 0, 0); X = vec(1, 0, 0); Y = vec(0, 1, 0); } public: CUDA_CALLABLE rect(){ init(); } //create a rectangle given a size and position CUDA_CALLABLE rect(T size, T z_pos = (T)0){ init(); //use the default setup scale(size); //scale the rectangle C[2] = z_pos; } //create a rectangle from a center point, normal, and size CUDA_CALLABLE rect(T size, vec c, vec n = vec(0, 0, 1)){ init(); //start with the default setting C = c; scale(size); //scale the rectangle normal(n); //orient } //create a rectangle from a center point, normal, and size CUDA_CALLABLE rect(vec size, vec c, vec n = vec(0, 0, 1)){ init(); //start with the default setting C = c; scale(size); //scale the rectangle normal(n); //orient } CUDA_CALLABLE rect(vec center, vec directionX, vec directionY ) { C = center; X = directionX; Y = directionY; } CUDA_CALLABLE rect(vec mag, vec center, vec directionX, vec directionY ) { C = center; X = directionX; Y = directionY; scale(mag[0], mag[1]); } CUDA_CALLABLE void scale(T factor1, T factor2){ X *= factor1; Y *= factor2; } //boolean comparison bool operator==(const rect & rhs) { if(C == rhs.C && X == rhs.X && Y == rhs.Y) return true; else return false; } /******************************************* Return the normal for the rect *******************************************/ CUDA_CALLABLE stim::vec n() { return (X.cross(Y)).norm(); } //get the world space value given the planar coordinates a, b in [0, 1] CUDA_CALLABLE stim::vec p(T a, T b) { stim::vec result; //given the two parameters a, b = [0 1], returns the position in world space vec A = C - X * (T)0.5 - Y * (T)0.5; result = A + X * a + Y * b; return result; } //parenthesis operator returns the world space given rectangular coordinates a and b in [0 1] CUDA_CALLABLE stim::vec operator()(T a, T b) { return p(a, b); } std::string str() { std::stringstream ss; vec A = C - X * (T)0.5 - Y * (T)0.5; ss<"<<"C="<"<<"D="< operator*(T rhs) { //scales the plane by a scalar value //create the new rectangle rect result = *this; result.scale(rhs); return result; } //computes the distance between the specified point and this rectangle CUDA_CALLABLE T dist(vec p) { //compute the distance between a point and this rect vec A = C - X * (T)0.5 - Y * (T)0.5; //first break the rect up into two triangles triangle T0(A, A+X, A+Y); triangle T1(A+X+Y, A+X, A+Y); T d0 = T0.dist(p); T d1 = T1.dist(p); if(d0 < d1) return d0; else return d1; } CUDA_CALLABLE T dist_max(vec p) { vec A = C - X * (T)0.5 - Y * (T)0.5; T da = (A - p).len(); T db = (A+X - p).len(); T dc = (A+Y - p).len(); T dd = (A+X+Y - p).len(); return std::max( da, std::max(db, std::max(dc, dd) ) ); } }; } //end namespace rts template std::ostream& operator<<(std::ostream& os, stim::rect R) { os<