circle.h 3.89 KB
#ifndef STIM_CIRCLE_H
#define STIM_CIRCLE_H

#include <stim/cuda/cudatools/callable.h>
#include <stim/math/plane.h>
#include <stim/math/vector.h>
#include <stim/math/triangle.h>
#include <stim/math/constants.h>
#include <assert.h>
#include <algorithm>
#include <iostream>

namespace stim{

template <typename T>
class circle : plane<T>
{

private:
	
	stim::vec3<T> Y;

	CUDA_CALLABLE void
	init()
	{
		Y = U.cross(N).norm();
	}

public:
	using stim::plane<T>::n;
	using stim::plane<T>::P;
	using stim::plane<T>::N;
	using stim::plane<T>::U;
	using stim::plane<T>::rotate;
	using stim::plane<T>::setU;

	///base constructor
	///@param th value of the angle of the starting point from 0 to 360.
	CUDA_CALLABLE
	circle() : plane<T>()
	{
		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
	circle(T size, T z_pos = (T)0) : plane<T>()
	{
		init();
		center(stim::vec3<T>(0,0,z_pos));
		scale(size);
	}

	///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
	circle(vec3<T> c, vec3<T> n = vec3<T>(0,0,1)) : plane<T>()
	{
		center(c);
		normal(n);
		init();
	}

	///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 
	circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1)) : plane<T>()
	{
		init();
		center(c);
		rotate(n, U, Y);
		scale(s);
	}

	///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.
	///@param u: x,y,z direction for the zero vector (from where the rotation starts)
	CUDA_CALLABLE
	circle(vec3<T> c, T s, vec3<T> n = vec3<T>(0,0,1), vec3<T> u = vec3<T>(1, 0, 0)) : plane<T>()
	{
		init();
		setU(u);
		center(c);
		normal(n);
		scale(s);
	}

	///scales the circle by a certain factor
	///@param factor: the factor by which the dimensions of the shape are scaled.
	CUDA_CALLABLE
	void scale(T factor)
	{
		U *= factor;
		Y *= factor;
	}

	///sets the normal for the cirlce
	///@param n: x,y,z direction of the normal.
	CUDA_CALLABLE void
	normal(vec3<T> n)
	{
		rotate(n, Y);
	}

	///sets the center of the circle.
	///@param n: x,y,z location of the center.
	CUDA_CALLABLE void
	center(vec3<T> p){
		this->P = p;
	}

	///boolean comparison
	bool
	operator==(const circle<T> & rhs)
	{
		if(P == rhs.P && U == rhs.U && Y == rhs.Y)
			return true;
		else
			return false;
	}

	///get the world space value given the planar coordinates a, b in [0, 1]
	CUDA_CALLABLE stim::vec3<T> p(T a, T b)
	{
		stim::vec3<T> result;

		vec3<T> A = this->P - this->U * (T)0.5 - Y * (T)0.5;
		result = A + this->U * a + Y * b;
		return result;
	}

	///parenthesis operator returns the world space given rectangular coordinates a and b in [0 1]
	CUDA_CALLABLE stim::vec3<T> operator()(T a, T b)
	{
		return p(a,b);
	}

	///returns a vector with the points on the initialized circle.
	///connecting the points results in a circle.
	///@param n: integer for the number of points representing the circle.
	std::vector<stim::vec3<T> >
	getPoints(int n)
	{
		std::vector<stim::vec3<T> > result;
		stim::vec3<T> point;
		T x,y;
		float step = 360.0/(float) n;
		for(float j = 0; j <= 360.0; j += step)
		{
			y = 0.5*cos(j*stim::TAU/360.0)+0.5;
			x = 0.5*sin(j*stim::TAU/360.0)+0.5;
			result.push_back(p(x,y));
		}
		return result;
	}	
	
	///returns a vector with the points on the initialized circle.
	///connecting the points results in a circle.
	///@param n: integer for the number of points representing the circle.
	stim::vec3<T>
	p(T theta)
	{
		T x,y;
		y = 0.5*cos(theta*stim::TAU/360.0)+0.5;
		x = 0.5*sin(theta*stim::TAU/360.0)+0.5;
		return p(x,y);
	}

};
}
#endif