rect.h 4.65 KB
``````#ifndef RTS_RECT_H
#define RTS_RECT_H

//enable CUDA_CALLABLE macro
#include <stim/cuda/callable.h>
#include <stim/math/vector.h>
#include <stim/math/triangle.h>
#include <stim/math/quaternion.h>
#include <iostream>
#include <iomanip>
#include <algorithm>

namespace stim{

//template for a rectangle class in ND space
template <class T>
struct rect
{
/*
^                   O
|
|
Y         C
|
|
O---------X--------->
*/

private:

stim::vec<T> C;
stim::vec<T> X;
stim::vec<T> Y;

CUDA_CALLABLE void scale(T factor){
X *= factor;
Y *= factor;
}

CUDA_CALLABLE void normal(vec<T> n){		//orient the rectangle along the specified normal

n = n.norm();								//normalize, just in case
vec<T> n_current = X.cross(Y).norm();	//compute the current normal
quaternion<T> 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<T>(0, 0, 0);
X = vec<T>(1, 0, 0);
Y = vec<T>(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(vec<T> c, vec<T> n = vec<T>(0, 0, 1)){
C = c;
normal(n);		//orient
}

CUDA_CALLABLE rect(vec<T> center, vec<T> directionX, vec<T> directionY )
{
C = center;
X = directionX;
Y = directionY;
}

CUDA_CALLABLE rect(T size, vec<T> center, vec<T> directionX, vec<T> directionY )
{
C = center;
X = directionX;
Y = directionY;
scale(size);
}

CUDA_CALLABLE rect(vec<T> size, vec<T> center, vec<T> directionX, vec<T> directionY )
{
C = center;
X = directionX;
Y = directionY;
scale(size[0], size[1]);
}

CUDA_CALLABLE void scale(T factor1, T factor2){
X *= factor1;
Y *= factor2;
}

//boolean comparison
bool operator==(const rect<T> & 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<T> n()
{
return (X.cross(Y)).norm();
}

//get the world space value given the planar coordinates a, b in [0, 1]
CUDA_CALLABLE stim::vec<T> p(T a, T b)
{
stim::vec<T> result;
//given the two parameters a, b = [0 1], returns the position in world space
vec<T> 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<T> operator()(T a, T b)
{
return p(a, b);
}

std::string str()
{
std::stringstream ss;
vec<T> A = C - X * (T)0.5 - Y * (T)0.5;
ss<<std::left<<"B="<<std::setfill('-')<<std::setw(20)<<A + Y<<">"<<"C="<<A + Y + X<<std::endl;
ss<<std::setfill(' ')<<std::setw(23)<<"|"<<"|"<<std::endl<<std::setw(23)<<"|"<<"|"<<std::endl;
ss<<std::left<<"A="<<std::setfill('-')<<std::setw(20)<<A<<">"<<"D="<<A + X;

return ss.str();

}

//scales the rectangle by a value rhs
CUDA_CALLABLE rect<T> operator*(T rhs)
{
//scales the plane by a scalar value

//create the new rectangle
rect<T> result = *this;
result.scale(rhs);

return result;

}

//computes the distance between the specified point and this rectangle
CUDA_CALLABLE T dist(vec<T> p)
{
//compute the distance between a point and this rect

vec<T> A = C - X * (T)0.5 - Y * (T)0.5;

//first break the rect up into two triangles
triangle<T> T0(A, A+X, A+Y);
triangle<T> 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<T> p)
{
vec<T> 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 <typename T, int N>
std::ostream& operator<<(std::ostream& os, stim::rect<T> R)
{
os<<R.str();
return os;
}

#endif
``````