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

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

line::line ( const line & xxx )
{
  isvert = xxx.vert();
  myslope = xxx.slope();
  myxcept = xxx.xcept();
}

line::line ( const ratpoint & rp1, const ratpoint & rp2 )
{
  isvert = (rp1.x() == rp2.x());
  if (!isvert) {
    myslope = (rp1.y() - rp2.y()) / (rp1.x() - rp2.x());
    myxcept = rp1.y() - myslope * rp1.x();
  } else {
    myxcept = rp1.x();
  }
}

void line::makeline ( const ratpoint & rp1, const ratpoint & rp2 )
{
  isvert = (rp1.x() == rp2.x());
  if (!isvert) {
    myslope = (rp1.y() - rp2.y()) / (rp1.x() - rp2.x());
    myxcept = rp1.y() - myslope * rp1.x();
  } else {
    myxcept = rp1.x();
  }
}

line::~line ( )
{
}

// overloading of the assignment operator =
line & line::operator = ( const line & x )
{
  isvert = x.vert();
  myslope = x.slope();
  myxcept = x.xcept();

  // 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 line & x )
{
  if (x.isvert) {
    out << "Line (x = " << x.myxcept << ")"; 
  } else {
    out << "Line (y = " << x.myslope << " x + " << x.myxcept << ")"; 
  }
}

bool line::hitpoint ( const ratpoint & x ) {
  if (isvert) {
    return (myxcept == x.x());
  } else {
    return (x.y() == myslope * x.x() + myxcept);
  }
}

bool line::intersect (const line & x) {
  if (isvert) {
    return !(x.vert());
  } else if (x.vert()) {
    return true;
  } else {
    return !(myslope == x.slope());
  }
}

ratpoint line::intersection (const line & x) {
  rational my_x;
  rational my_y;
  assert(this->intersect(x));
  if (isvert) {
    my_x = myxcept;
    my_y = x.slope() * my_x + x.xcept();
  } else if (x.vert()) {
    my_x = x.xcept();
    my_y = myslope * my_x + myxcept;
  } else {
    my_x = (x.xcept() - myxcept) / (myslope - x.slope());
    my_y = myslope * my_x + myxcept;
  }
  return ratpoint(my_x,my_y);
}

