#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 rts{ //template for a rectangle class in ND space template struct rect { /* ^ O | | Y C | | O---------X---------> */ private: rts::vec C; rts::vec X; rts::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(); } CUDA_CALLABLE rect(T size, T z_pos = (T)0){ init(); //use the default setup scale(size); //scale the rectangle C[2] = z_pos; } 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 } /*CUDA_CALLABLE rect(vec a, vec b, vec c) { A = a; Y = b - a; X = c - a - Y; }*/ /******************************************************************* Constructor - create a rect from a position, normal, and rotation *******************************************************************/ /*CUDA_CALLABLE rect(rts::vec c, rts::vec normal, T width, T height, T theta) { //compute the X direction - start along world-space X Y = rts::vec(0, 1, 0); if(Y == normal) Y = rts::vec(0, 0, 1); X = Y.cross(normal).norm(); std::cout< q; q.CreateRotation(theta, normal); X = q.toMatrix3() * X; Y = normal.cross(X); //normalize everything X = X.norm(); Y = Y.norm(); //scale to match the rect width and height X = X * width; Y = Y * height; //set the corner of the plane A = c - X * 0.5f - Y * 0.5f; std::cout< & rhs) { if(C == rhs.C && X == rhs.X && Y == rhs.Y) return true; else return false; } /******************************************* Return the normal for the rect *******************************************/ CUDA_CALLABLE rts::vec n() { return (X.cross(Y)).norm(); } CUDA_CALLABLE rts::vec p(T a, T b) { rts::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; } CUDA_CALLABLE rts::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; } 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, rts::rect R) { os<