#ifndef RTS_RECT_H #define RTS_RECT_H //enable CUDA_CALLABLE macro #include #include #include #include #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; } public: ///base constructor. CUDA_CALLABLE rect(){ init(); } ///create a rectangle given a size and position in Z space. ///@param size: size of the rectangle in ND space. ///@param z_pos z coordinate of the rectangle. 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 ///@param c: x,y,z location of the center. ///@param n: x,y,z direction of the normal. CUDA_CALLABLE rect(vec c, vec n = vec(0, 0, 1)){ init(); //start with the default setting C = c; normal(n); //orient } ///create a rectangle from a center point, normal, and size ///@param c: x,y,z location of the center. ///@param s: size of the rectangle. ///@param n: x,y,z direction of the normal. CUDA_CALLABLE rect(vec c, T s, vec n = vec(0, 0, 1)){ init(); //start with the default setting C = c; scale(s); normal(n); //orient } ///creates a rectangle from a centerpoint and an X and Y direction vectors. ///@param center: x,y,z location of the center. ///@param directionX: u,v,w direction of the X vector. ///@param directionY: u,v,w direction of the Y vector. CUDA_CALLABLE rect(vec center, vec directionX, vec directionY ) { C = center; X = directionX; Y = directionY; } ///creates a rectangle from a size, centerpoint, X, and Y direction vectors. ///@param size of the rectangle in ND space. ///@param center: x,y,z location of the center. ///@param directionX: u,v,w direction of the X vector. ///@param directionY: u,v,w direction of the Y vector. CUDA_CALLABLE rect(T size, vec center, vec directionX, vec directionY ) { C = center; X = directionX; Y = directionY; scale(size); } ///creates a rectangle from a size, centerpoint, X, and Y direction vectors. ///@param size of the rectangle in ND space, size[0] = size in X, size[1] = size in Y. ///@param center: x,y,z location of the center. ///@param directionX: u,v,w direction of the X vector. ///@param directionY: u,v,w direction of the Y vector. CUDA_CALLABLE rect(vec size, vec center, vec directionX, vec directionY ) { C = center; X = directionX; Y = directionY; scale(size[0], size[1]); } ///scales a rectangle in ND space. ///@param factor1: size of the scale in the X-direction. ///@param factor2: size of the scale in the Y-direction. CUDA_CALLABLE void scale(T factor1, T factor2){ X *= factor1; Y *= factor2; } ///@param n; vector with the normal. ///Orients the rectangle along the normal n. 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; } ///general init method that sets a general rectangle. CUDA_CALLABLE void init(){ C = vec(0, 0, 0); X = vec(1, 0, 0); Y = vec(0, 1, 0); } //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. ///@param p: x, y, z coordinates of the point to calculate distance to. 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 center(vec p) { C = p; } ///Returns the maximum distance of the rectangle from a point p to the sides of the rectangle. ///@param p: x, y, z point. 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<