#include "ray.h"
#include <assert.h>

// constructors and desctructor 
ray::ray ( void ) {
}

ray::ray ( const ray & xxx )
{
  myline = xxx.ln();
  mystartpt = xxx.startpt();
  mydir = xxx.dir();
}

ray::ray ( const ratpoint & rp1, const ratpoint & rp2 ) {
  myline = line(rp1,rp2);
  mystartpt = rp1;
  if (myline.vert()) {
    mydir = (rp2.y() > rp1.y());
  } else {
    mydir = (rp2.x() > rp1.x());
  }
}

void ray::makeray ( const ratpoint & rp1, const ratpoint & rp2 ) {
  myline = line(rp1,rp2);
  mystartpt = rp1;
  if (myline.vert()) {
    mydir = (rp2.y() > rp1.y());
  } else {
    mydir = (rp2.x() > rp1.x());
  }
}

ray::~ray ( ) {
}

// overloading of the assignment operator =
ray & ray::operator = ( const ray & x )
{
  myline = x.ln();
  mystartpt = x.startpt();
  mydir = x.dir();

  // return a reference to THIS object so that we
  // can write x =.y() = z = ...
  return *this;
}

// overloading of the output operator
ostream & operator << ( ostream & out , const ray & x )
{
  out << ((x.mydir)? "Neg " : "Pos ") << "Ray " 
     << x.mystartpt << " " << x.myline ;
}

bool ray::hitpoint ( const ratpoint & x ) {
  // returns true if x is on the ray.
  if (!myline.hitpoint(x)) return false;
  else if (myline.vert())
    return ((x.y()==mystartpt.y()) || ((x.y()>mystartpt.y())==mydir));
  else
    return ((x.x()==mystartpt.x()) || ((x.x()>mystartpt.x())==mydir));
}

bool ray::intersect (line & x) {
  if (x.intersect(myline)) {
    return(this->hitpoint(x.intersection(myline)));
  } else {
    return(false);
  }
}

bool ray::intersect (ray & x) {
  if (x.intersect(myline)) {
    return(this->hitpoint(x.intersection(myline)));
  } else {
    return(false);
  }
}

ratpoint ray::intersection (line & x) {
  assert(this->intersect(x));
  return(x.intersection(myline));
}

ratpoint ray::intersection (ray & x) {
  assert(this->intersect(x));
  return(x.intersection(myline));
}

void ray::reverse (void) {
  mydir = (!mydir);
}
