#include <math.h>
// #include <iostream.h>
#include <float.h>
#include "gpklib/assert.h"
#include "nline.h"

#ifndef DBL_EPSILON
# define DBL_EPSILON	1e-14
#endif


double nline::p_hasangle(double theta) C
{
 assert(ok());
 C double st = sin(theta);
 C double ct = cos(theta);
 C double num = dir()(0)*st-dir()(1)*ct;
 return fabs(num)<DBL_MIN*2+3*DBL_EPSILON*fabs(dir()(0)*st+dir()(1)*ct)
  						? 0.0 : -0.5*num/(q()(0)*st-q()(1)*ct);
}

BOOL nline::check_hasangle(double theta) C
{
 assert(ok());
 C double st = sin(theta);
 C double ct = cos(theta);
 return fabs(dir()(0)*st-dir()(1)*ct) < DBL_MIN*2
								+ 3*DBL_EPSILON*fabs(dir()(0)*st+dir()(1)*ct)
 			|| fabs(q()(0)*st-q()(1)*ct) > DBL_MIN*2
								+ 3*DBL_EPSILON*fabs(q()(0)*st+q()(1)*ct);
}

double nline::angle(double s) C
{
 assert(ok());
 C vector2 d = dir() + 2*s*q();
 C double theta = atan2(d(1), d(0));
 return theta>M_PI/2 ? theta-M_PI : (theta<-M_PI/2 ? theta+M_PI : theta);
}

nline operator+(C nline& a, C vector2& b)
	{return nline(a.base()+b, a.dir(), a.q());}

vector2 nline::operator()(double s) C	{return (_q*s + _dir)*s + _base;}

#if 0
ostream& operator<<(ostream& s, C nline& l)
{
 if(l.ok())
 	s << "%< " << l.base() << " + s* " << l.dir() << " + s^2* "
		<< l.q() << " >%";
 else	s << "%< BAD NLINE >%";
 return s;
}
#endif

BOOL nline::ok() C
{
 return vector_space::vseQ(_base.space(), _dir.space())
			&& vector_space::vseQ(_base.space(), _q.space());
}
