/* General purpose X-Y plotting that can print/export to Postscript thanks to Trolltech's QT

Copyright (C) 2001-2002 Andrew Rogers

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "mplot.moc"
#include <qwidget.h>
#include <qpainter.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

const double pi=3.141592654;

MPlot::MPlot(QWidget * parent=0, const char * name=0, WFlags f=0):QWidget(parent,name,f)
{
    x_data=NULL;y_data=NULL;
    x_nd=10; y_nd=10; x_angle=20;
    x_margin=80; y_margin=60;
    buttPrint = new QPushButton(this);
    buttPrint->setText("Print...");
    connect( buttPrint, SIGNAL(clicked()), this, SLOT(print()));
    printer = new QPrinter();
    data_array_size=10;
    for(int i=0; i<data_array_size; i++)
    {
        data_array[i].x_data_ptr=NULL;
        data_array[i].y_data_ptr=NULL;
    }
}

void MPlot::drawFromFloat(int num, double *xdata, double *ydata, int line_num=0, QColor color=blue)
{
    size_t sz=sizeof(double);
    if(line_num>=data_array_size) return;
    x_data=data_array[line_num].x_data_ptr;
    y_data=data_array[line_num].y_data_ptr;
    data_array[line_num].color=color;
    data_array[line_num].size=num;
    x_data=(double *)realloc(x_data,num*sz);
    y_data=(double *)realloc(y_data,num*sz);
    if(x_data!=NULL)memcpy(x_data,xdata,num*sz);
    if(y_data!=NULL)memcpy(y_data,ydata,num*sz);
    data_array[line_num].x_data_ptr=x_data;
    data_array[line_num].y_data_ptr=y_data;
}

void MPlot::setAxis(int nxd=10,int nyd=10,float anglex=30,float angley=10)
{
    x_nd=nxd; y_nd=nyd; //x_angle=anglex; y_angle=angley;
}

void MPlot::setRangeFromFloat(double xmin,double ymin,double xmax,double ymax)
{
    x_min=xmin;x_max=xmax;
    y_min=ymin;y_max=ymax;
}

void MPlot::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    drawPlot(&p);
    buttPrint->setGeometry(width()-50,10,40,20);
    return;

}

void MPlot::drawPlot(QPainter *p)
{
    double dx=x_max-x_min;
    double dy=y_max-y_min;
    double xp,yp;

    for(int i=0; i<data_array_size; i++)
    {
        x_data=data_array[i].x_data_ptr;
        y_data=data_array[i].y_data_ptr;
        int num_p=data_array[i].size;
        if(x_data!=NULL&&y_data!=NULL)
        {
            p->setPen(data_array[i].color);
            xp=(x_data[0]-x_min)*(width()-2*x_margin)/dx+x_margin;
            yp=height()-(y_data[0]-y_min)*(height()-2*y_margin)/dy-y_margin;
            if(xp<x_margin) xp=x_margin;
            if(xp>width()-x_margin) xp=width()-x_margin;
            if(yp<y_margin) yp=y_margin;
            if(yp>height()-x_margin) yp=height()-y_margin;
            p->moveTo(xp,yp);
            for(int i=1;i<num_p;i++)
            {
                xp=(x_data[i]-x_min)*(width()-2*x_margin)/dx+x_margin;
                yp=height()-(y_data[i]-y_min)*(height()-2*y_margin)/dy-y_margin;
                if(xp<x_margin) xp=x_margin;
                if(xp>width()-x_margin) xp=width()-x_margin;
                if(yp<y_margin) yp=y_margin;
                if(yp>height()-x_margin) yp=height()-y_margin;
                p->lineTo(xp,yp);
            }
        }
    }
    p->setPen(black);
    p->moveTo(x_margin,y_margin); p->lineTo(x_margin,height()-y_margin); p->lineTo(width()-x_margin,height()-y_margin);

//Draw X axis ticks
    int x,y;
    for(int i=0;i<=x_nd;i++)
    {
        x=(int)(((width()-2*x_margin)*i)/x_nd+x_margin);
        y=height()-y_margin;
        p->moveTo(x,y);
        p->lineTo(x,y+8);
    }

//Draw Y axis ticks
    for(int i=0;i<=y_nd;i++)
    {

        x=x_margin;
        y=(int)(((height()-2*y_margin)*i)/y_nd+y_margin);
        p->moveTo(x,y);
        p->lineTo(x-8,y);
    }

//Draw X axis
    int ux,uy;
    char str[100];
    p->rotate(x_angle);
    QWMatrix wm=p->worldMatrix();
    wm=wm.invert();
    for(int i=0;i<=x_nd;i++)
    {
        x=(int)(((width()-2*x_margin)*i)/x_nd);
        y=height()-y_margin;
        sprintf(str,"%3.3e",(float)i*dx/x_nd+x_min);
        wm.map(x,y,&ux,&uy);
        p->drawText(ux+x_margin,uy,str);
    }

//Draw Y axis
    p->rotate(y_angle);
    wm=p->worldMatrix();
    wm=wm.invert();
    for(int i=0;i<=y_nd;i++)
    {
        x=10;
        y=(int)(((height()-2*y_margin)*i)/y_nd+y_margin+10);
        sprintf(str,"%3.3e",(float)i*dy/y_nd+y_min);
        wm.map(x,height()-y,&ux,&uy);
        p->drawText(ux,uy,str);
    }

}

void MPlot::print()
{
#ifndef QT_NO_PRINTER
    if ( printer->setup( this ) )
    {
        QPainter p( printer );
        drawPlot(&p);
    }
#endif
}

MPlot::~MPlot(void)
{
    for(int i=0; i<data_array_size; i++)
    {
        x_data=data_array[i].x_data_ptr;
        y_data=data_array[i].y_data_ptr;
        free(x_data);x_data=NULL;
        free(y_data);y_data=NULL;
        data_array[i].x_data_ptr=x_data;
        data_array[i].y_data_ptr=y_data;
    }
}


