rect_old.h 6.63 KB
#ifndef RTS_RECT_H
#define RTS_RECT_H

//enable CUDA_CALLABLE macro
#include <stim/cuda/cudatools/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;
	}
	


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<T> c, vec<T> n = vec<T>(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<T> c, T s, vec<T> n = vec<T>(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<T> center, vec<T> directionX, vec<T> 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<T> center, vec<T> directionX, vec<T> 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<T> size, vec<T> center, vec<T> directionX, vec<T> 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<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;
	}

	///general init method that sets a general rectangle.
	CUDA_CALLABLE void init(){
		C = vec<T>(0, 0, 0);
		X = vec<T>(1, 0, 0);
		Y = vec<T>(0, 1, 0);
	}

	//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();

	}

	///multiplication operator 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.
	///@param p: x, y, z coordinates of the point to calculate distance to.
	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 center(vec<T> 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<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