/***********************************************************************
**
**   cupainter.cpp
**
**   This file is part of Cumulus
**   This piece of code is highly experimental!
**
************************************************************************
**
**   Copyright (c):  2002 by André Somers
**
**   This file is distributed under the terms of the General Public
**   Licence. See the file COPYING for more information.
**
**   $Id: cupainter.cpp,v 1.2 2002/11/04 20:53:25 eggert Exp $
**
***********************************************************************/

#include "cupainter.h"
#include "resource.h"

CuPainter::CuPainter(){
}

CuPainter::CuPainter(QPaintDevice * device):QPainter(device){
}

CuPainter::~CuPainter(){
}

void CuPainter::drawLine(int x1, int y1, int x2, int y2, bool safe){
  if (!safe) {
    QPainter::drawLine(x1, y1, x2, y2);
  } else {
    drawLine(QPoint(x1, y1), QPoint(x2, y2), true);
  }
}
  
void CuPainter::drawLine(const QPoint& point1, const QPoint& point2, bool safe){
  if (!safe) {
    QPainter::drawLine(point1, point2);
    return;
  } else {
    if (point1==point2) return; //no point in drawing a line without length.
    
    QRect viewport(-20,-20,280,280);//=QPainter::viewport();
    QPoint p1=point1;
    QPoint p2=point2;    

//    qDebug("");
//    qDebug("points: p1=(%d,%d), p2=(%d,%d)",p1.x(),p1.y(),p2.x(),p2.y());
    if (viewport.contains(point1)) {
//      qDebug("point 1 is inside the viewport");
      if (viewport.contains(point2)) {
        //simple case: both endpoints are inside the viewport, so just draw!
        QPainter::drawLine(point1, point2);
//        qDebug("point 2 is inside the viewport");
        return;
      } else {
        //only p1 is contained, and p2 not. We need to adjust p2
        adjustPoint(point1, p2);
//        qDebug("point 2 is not inside the viewport. Adjusted point 2 to: (%d,%d)",p2.x(),p2.y());
        //now the point second point is sure to be just outside the viewport, we can draw!
        QPainter::drawLine(point1, p2);
        return;
      }
    } else {
//      qDebug("point 1 is not inside the viewport");
      if (viewport.contains(p2)) {
        //only p2 is contained, and p1 not. We need to adjust p1
        adjustPoint(p2, p1);
//        qDebug("point 2 is inside the viewport. Adjusted point 1 to: (%d,%d)",p1.x(),p1.y());
        //now the point second point is sure to be just outside the viewport, we can draw!
        QPainter::drawLine(p1, p2);
        return;
      } else {
//        qDebug("point 2 is not inside the viewport.");
        //neither point is inside the viewport.
        //try to find a point on the line that is inside the viewport
        double dy;
        QPoint pa(-100,-100);
        QPoint pb(-100,-100);
        
        if (p2.x()==p1.x()) {
          dy=1.0;
        } else {
          dy=double(p2.y()-p1.y())/double(p2.x()-p1.x());
        }
//        qDebug("equation: dy=%f, p1=(%d,%d), p2=(%d,%d)",dy,p1.x(),p1.y(),p2.x(),p2.y());

        //we can now calculate points on the line using y=p1.y() + (x-p1.x())*dy
        //test on the x-edges:
        if (viewport.contains(viewport.left(),p1.y()+(viewport.left()-p1.x())*dy)) {
          //found intersection!
          pa=QPoint(viewport.left(),p1.y()+(viewport.left()-p1.x())*dy);
          qDebug ("found intersection 1, point: (%d,%d)",viewport.left(),int(p1.y()+(viewport.left()-p1.x())*dy));
        }

        int x=viewport.right();
//        qDebug ("intersection 2, point: (%d,%d)",x,int(p1.y()+(x-p1.x())*dy));
        if (viewport.contains(x,int(p1.y()+(x-p1.x())*dy))) {
          //found intersection!
          if (pa==QPoint(-100,-100)) {
            pa=QPoint(x,p1.y()+(x-p1.x())*dy);
          } else {
            pb=QPoint(x,p1.y()+(x-p1.x())*dy);
          }
//          qDebug ("found intersection 2, point: (%d,%d)",x,int(p1.y()+(x-p1.x())*dy));
        }

        //test on the y-edges
        if (viewport.contains((viewport.top()-p1.y())/dy+p1.x(),viewport.top())) {
          if (pa==QPoint(-100,-100)) {
            pa=QPoint((viewport.top()-p1.y())/dy+p1.x(),viewport.top());
          } else {
            pb=QPoint((viewport.top()-p1.y())/dy+p1.x(),viewport.top());
          }
//          qDebug ("found intersection 3, point: (%d,%d)",int((viewport.top()-p1.y())/dy+p1.x()),viewport.top());
        }
            
        if (viewport.contains((viewport.bottom()-p1.y())/dy+p1.x(),viewport.bottom())) {
          if (pa==QPoint(-100,-100)) {
            pa=QPoint((viewport.bottom()-p1.y())/dy+p1.x(),viewport.bottom());
          } else {
            pb=QPoint((viewport.bottom()-p1.y())/dy+p1.x(),viewport.bottom());
          }
//          qDebug ("found intersection 4, point: (%d,%d)",int((viewport.bottom()-p1.y())/dy+p1.x()),viewport.bottom());
        }
        
        //at this point, either both pa and pb are found, or neither is....
        if (pb==QPoint(-100,-100)) return; //the line is completely outside the viewport
             
        QPainter::drawLine(pa,pb);
      }
    }  
  } 
}

void CuPainter::adjustPoint(QPoint center, QPoint& adjust) {
    QRect viewport(-10,-10,250,250);//=QPainter::viewport();
    //make sure the targetpoint is not too far out of range, because that will cause errors...
    int div=ABS(adjust.x()/MAX(viewport.width(), viewport.height()));
    div=MAX(div,ABS(adjust.y()/MAX(viewport.width(), viewport.height())));

    if (div>1) {
      adjust=((adjust-center)/div)+center;
    }
  
}
