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

#define D	if(0)

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

double line::angle() C
{
 assert(ok());
 C double theta = atan2(_dir(1), _dir(0));
 return theta>M_PI/2 ? theta-M_PI : (theta<-M_PI/2 ? theta+M_PI : theta);
}

line::line(C vector2& point, double angle_)
 : _base(point), _dir(vector2::unitvec(angle_))
{}

double line::p_nearest_to_origin() C
{
 assert(ok());
 C double denom = dot(dir(), dir());
 return -dot(base(), dir())/denom;
}

line::line(double aa, double bb, double cc)
 : _base(vector2(aa*cc/(aa*aa+bb*bb), bb*cc/(aa*aa+bb*bb))), _dir(-bb, aa)
{ }

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

ostream& operator<<(ostream& s, C line& l)
{
 if(l.ok())
 	s << "%< " << l.base() << " + s* " << l.dir() << " >%";
 else	s << "%< BAD LINE >%";
 return s;
}

line::line()	: _base(), _dir() {}

line::line(C vector2& point1, C vector2& point2)
 : _base(point1), _dir(point2-point1)	{}

double line::x_intercept() C
{
 assert(ok());
 return _base(0)-_dir(0)*_base(1)/_dir(1);
}

double line::y_intercept() C
{
 assert(ok());
 return _base(1)-_dir(1)*_base(0)/_dir(0);
}
