plotwidget.cc

Go to the documentation of this file.
00001 #include "postscriptplot.h"
00002 #include "controlpanel.h"
00003 
00004 #include "data.h"
00005 #include "plotwidget.h"
00006 #include "spline.h"
00007 
00008 #include <QPaintEvent>
00009 #include <QPainterPath>
00010 #include <QKeyEvent>
00011 #include <QPolygon>
00012 #include <QMessageBox>
00013 #include <QMouseEvent>
00014 #include <QPrinter>
00015 #include <QPrintDialog>
00016 #include <QProcess>
00017 #include <QTime>
00018 #include <QTimer>
00019 #include <QSettings>
00020 #include <QColorDialog>
00021 
00022 
00023 #include <fstream>
00024 #include <cmath>
00025 
00026 
00027 
00028 PlotWidget::PlotWidget(QWidget * parent, const char * name, Qt::WFlags flags) : QWidget(parent,flags) , paint(0), LogX(false), LogY(false), AntiAlias(true), BadDraw(false), MidMouseDown(false), Pin(QString::fromStdString(ControlPanel::cmbeasyDir("/pix/pin4c.png"))), RepaintReason(NoSpecialReason), DrawBestFitModel(false), Co(2,2000,1e-5,1e-4), xoffset(40), yoffset(20), SplineId(0) , Web(0), Blocks(0), Rectangles(0), data(0) , IsPrinting(false) {
00029   setObjectName( name );
00030   colors.resize(100);
00031 
00032   colors[0] = new QColor(0,0,0);
00033   colors[1] = new QColor(180,0,0);
00034   colors[2] = new QColor(0,0,180);
00035   colors[3] = new QColor(0,180,0);
00036   
00037   for (unsigned int i=4;i < colors.size(); i++) colors[i]=new QColor(0,0,0);
00038   
00039   dataColors.resize(4);
00040   dataColors[0] = new QColor(100,0,200);
00041   dataColors[1] = new QColor(20,180,0);
00042   dataColors[2] = new QColor(180,20,0);
00043   QFont f( "Helvetica", 10);
00044   setFont( f );
00045   setMouseTracking(true);
00046 
00047   QFont g( "Helvetica", 12);
00048 
00049   QPalette palette;
00050   palette.setColor( backgroundRole(), Qt::white );
00051   setPalette( palette );
00052 
00053   setFocusPolicy(Qt::ClickFocus);
00054 
00055   LastDraw = new QTime();
00056   LastDraw->start();
00057   EnsureBlockDrawing = new QTimer();
00058   connect(EnsureBlockDrawing,SIGNAL(timeout()),this,SLOT(repaint()));
00059 
00060 }
00061 
00062 void PlotWidget::paintEvent(QPaintEvent *e) {
00063   // cout << "Paintevent for : " << this << "RepaintReason: " << RepaintReason << endl;
00064 
00065     checkPainter();
00066   // paint->fillRect(0,0,width(),Height(),QBrush(Qt::white));
00067   paint->setPen( Qt::black);
00068   //cout << "PaintEvent: " << e->rect().left() << " ::  " << e->rect().right() << endl;
00069   if (BadDraw) {
00070     paint->setPen( Qt::red);
00071     paint->drawText(width()/2-100, Height()/2,"Bad Data. Repaint impossible");
00072   } else {
00073     try {
00074       startDrawing(e->rect());
00075     } catch  (Bad_Error x) {
00076       QMessageBox::critical(this,"Bad Error", x.s.c_str(),  QMessageBox::Ok,QMessageBox::NoButton);
00077       cerr << "BAD: ERROR" << endl;
00078       cerr << x.s << endl;
00079       BadDraw = true;
00080     }
00081   }
00082 
00083   switch (RepaintReason) {
00084     case LeftButtonPressed:
00085           RepaintReason = NoSpecialReason;
00086           paintOnLeftButtonPress();
00087           break;
00088     case LeftButtonMoved:
00089           RepaintReason = NoSpecialReason;
00090           paintOnLeftMouseMove();
00091           break;
00092     case MidButtonMoved:
00093           RepaintReason = NoSpecialReason;
00094           paintOnMidMouseMove();
00095           break;
00096     case MouseMoved:
00097           RepaintReason = NoSpecialReason;
00098           paintOnMouseMove();
00099           break;
00100     case NoSpecialReason:
00101     default:
00102          break;
00103   }
00104 
00105   delete paint; paint=0;
00106 }
00107 
00108 void PlotWidget::printQt() {
00109   //printPostscript();
00110   return;
00111 
00112   QPrinter *prt = new QPrinter();
00113   QSettings s;
00114   //prt->setOutputToFile(s.value("/cmbeasy/plot/printqt/tofile",false).toBool());
00115   prt->setOutputFileName(s.value("/cmbeasy/plot/printqt/name","print.ps").toString());
00116   prt->setOrientation((QPrinter::Orientation)s.value("/cmbeasy/plot/printqt/orientation",QPrinter::Landscape).toInt());
00117 
00118   QPrintDialog dialog(prt);
00119   if (dialog.exec()) {
00120     s.setValue("/cmbeasy/plot/printqt/tofile",prt->outputFileName().isEmpty());
00121     s.setValue("/cmbeasy/plot/printqt/name",prt->outputFileName());
00122     s.setValue("/cmbeasy/plot/printqt/orientation",prt->orientation());
00123     bool aa = AntiAlias;
00124     AntiAlias = false;
00125     PrintingHeight = prt->height();
00126     PrintingWidth = prt->width();
00127 
00128     if (paint) { delete paint; paint=0;}
00129     paint = new QPainter(prt);
00130     if (paint == 0) cout << ":::::::::::::::::::::::::::: PAINT is 0 " << endl;
00131   
00132     //    cout << "PRINTING HEIGHT " << PrintingHeight <<  "  :: " << PrintingWidth << endl;
00133     paint->setPen( Qt::black);
00134     IsPrinting = true;
00135     startDrawing(QRect(0,0,Width(),Height())); 
00136     IsPrinting = false;
00137     delete paint; paint=0;
00138     AntiAlias = aa;
00139   } 
00140   delete prt;
00141 }
00142 
00143 void PlotWidget::printPostscript(PostscriptPlot& post, ThingsToPlot& things, const QString fileName)
00144 {
00145   bool fileNameGiven = !fileName.isEmpty();
00146   QString outputFile;
00147   if (fileNameGiven)
00148    outputFile = fileName;
00149   else
00150    outputFile = "/tmp/o.ps";
00151 
00152   ofstream out;
00153 
00154   static QPrinter *prt = new QPrinter();
00155   QSettings s;
00156   prt->setOutputFileName(s.value("/cmbeasy/plot/printqt/name",QString()).toString());
00157   prt->setOrientation((QPrinter::Orientation)s.value("/cmbeasy/plot/printqt/orientation",QPrinter::Landscape).toInt());
00158 
00159   QPrintDialog dialog(prt);
00160   if (fileNameGiven || dialog.exec()) {
00161     s.setValue("/cmbeasy/plot/printqt/tofile",prt->outputFileName().isEmpty()); // shouldn't be needed anymore
00162     s.setValue("/cmbeasy/plot/printqt/name",prt->outputFileName());
00163     s.setValue("/cmbeasy/plot/printqt/orientation",prt->orientation());
00164 
00165     if (!fileNameGiven && !prt->outputFileName().isEmpty()) out.open(prt->outputFileName().toLatin1().data());
00166     else out.open(outputFile.toAscii());
00167 
00168     // a4 paper:   x = 595.3    y = 841.9 
00169     double scaleX=595.3,scaleY=841.9;
00170     double t;
00171     switch (prt->pageSize()) {
00172     case QPrinter::A4: break;
00173     case QPrinter::A5: t=scaleX; scaleX=scaleY /2; scaleY=t; break;
00174     case QPrinter::A3: t=scaleX; scaleX=scaleY; scaleY=2*t; break;
00175     case QPrinter::Letter: scaleX*=216.0/210.0; scaleY *= 279.0/297.0; break;
00176       //case QPrinter::Custom: scaleX *= post.Width/210; scaleY *= post.Height/297.0;break;
00177     default: 
00178       scaleX *= post.Width/210; scaleY *= post.Height/297.0;
00179     }
00180     
00181     post.Width = scaleX;
00182     post.Height = scaleY;
00183 
00184 
00185     // ==============================================
00186     // == Initialize Confidence Regions
00187     // ==============================================
00188   
00189     if (! RegionGroups.empty()) {
00190       for (map<int,ConfidenceRegionGroup>::iterator g = RegionGroups.begin(); g != RegionGroups.end(); g++) {
00191         // first the z-dots, if any
00192         if (! g->second.cp.v.empty() ) { 
00193           ColorPoints cp(g->second.cp);
00194           int size = cp.v.size();
00195           for (int i = 0; i < size; i++) {
00196             pair<double,double> tr = translate(cp.v[i][0],cp.v[i][1]);  // die Punkte nach 0..1 uebersetzen
00197             cp.v[i][0] = tr.first;  
00198             cp.v[i][1] = tr.second;
00199           }
00200           things.CPs.push_back(cp);
00201           // Also, we need to push back labels for Min and Max values for the color scale
00202           TickLabel MinLabel(cp.LeftLower.y);
00203           MinLabel.grace =  post.createGraceLabel(cp.Min,LowLevelPlot::decimal,2);
00204           MinLabel.size =  post.TickLabelSize*0.01*0.05;
00205           MinLabel.offset = -cp.LeftLower.x + 0.01;
00206           things.YTickLabels.push_back(MinLabel);
00207 
00208           TickLabel MaxLabel(cp.LeftLower.y + cp.Height);
00209           MaxLabel.grace =  post.createGraceLabel(cp.Max,LowLevelPlot::decimal,2);
00210           MaxLabel.size =  post.TickLabelSize*0.01*0.05;
00211           MaxLabel.offset = -cp.LeftLower.x + 0.01;
00212           things.YTickLabels.push_back(MaxLabel);
00213 
00214         }
00215         // now the regions
00216         list<ConfidenceRegion> &Regions = g->second.Regions;    
00217         for (list<ConfidenceRegion>::iterator i = Regions.begin(); i != Regions.end(); i++) {
00218           ConfidenceRegion r =*i; // make a copy
00219           for (list<CoordPoint>::iterator k = r.region.begin(); k != r.region.end(); k++) {
00220             *k = translateCoordPoint(*k);
00221           }
00222           things.Regions.push_back(r); 
00223         }
00224       }
00225     }
00226 
00227     // ==============================================
00228     // == Initialize Special Points (like marker for best fit model)
00229     // ==============================================
00230     if ( !things.SpecialPoints.empty() ) {
00231       list<SpecialPoint>::iterator it = things.SpecialPoints.begin();
00232       list<SpecialPoint>::iterator end = things.SpecialPoints.end();
00233       for ( ; it != end; ++it ) {
00234         it->position = translateCoordPoint( it->position);
00235       }
00236     }
00237 
00238 
00239 
00240     // ==============================================
00241     // == Initialize Blocks
00242     // ==============================================
00243   
00244     if (Blocks) {
00245       for (list<Block>::reverse_iterator i = Blocks->rbegin(); i != Blocks->rend(); i++) {
00246         Block b = *i; // make a copy
00247         b.lines.clear();
00248         b.Width /= (Co.X - Co.x);
00249         for (map<float, list<CoordPoint> >::iterator j = i->lines.begin(); j != i->lines.end(); j++) {
00250           float x = translate(j->first,j->first).first;
00251           for (list<CoordPoint>::iterator k = j->second.begin(); k != j->second.end(); k++) {
00252             float y1 = translate(k->x,k->x).second;
00253             float y2 = translate(k->y,k->y).second;
00254             b.lines[x].push_back(CoordPoint(y1,y2));
00255           }
00256         }
00257         things.Blocks.push_back(b); 
00258       }
00259     }
00260     
00261    
00262     // ==============================================
00263     // == Initialize Rectangles
00264     // ==============================================
00265   
00266     if (Rectangles) {
00267       for (list<Rectangle>::iterator i = Rectangles->begin(); i != Rectangles->end(); i++) {
00268           pair<double,double> left_up  = translate(i->C.x,i->C.Y);
00269           pair<double,double> left_down  = translate(i->C.x,i->C.y);
00270           pair<double,double> right_down  = translate(i->C.X,i->C.y);
00271           
00272           double x = left_up.first;
00273           double Y = left_up.second;
00274           double X = right_down.first;
00275           double y =  right_down.second ;
00276           
00277           Rectangle r(x,X,y,Y); 
00278           r.FillColor = i->FillColor;
00279           things.Rectangles.push_back(r);
00280           
00281       }
00282     }
00283 
00284     // ============================================
00285     // ==== Make Line segments out of  the Splines
00286     // ============================================
00287     int count = 0;
00288     for (map<int,Spline*>::iterator i=splines.begin(); i != splines.end();i++,count++) {
00289       Curve curve;
00290       double x = Co.x;
00291       pair<double,double> rel,lastrel;
00292       x = max(x, i->second->start());
00293       if (i->second->isWithinBounds(x)) {
00294         rel = translate(x,i->second->fastY(x));
00295         lastrel = rel;
00296         curve.Points.push_back(CoordPoint(rel.first,rel.second));
00297       } 
00298       curve.dash = count;
00299       while (x <= Co.X) {
00300         if (i->second->isWithinBounds(x)) {
00301           rel = translate(x,i->second->fastY(x));
00302           float distance = pow(fabs(rel.first - lastrel.first),2) + pow(fabs(rel.second - lastrel.second),2);     
00303           distance = sqrt(distance);
00304           if (distance > 0.003 || x > Co.X - (Co.X - Co.x)*3e-3 ) {
00305             lastrel = rel; 
00306             curve.Points.push_back(CoordPoint(rel.first,rel.second));
00307           }       
00308           //      curve.Points.push_back(CoordPoint(rel.first,rel.second));  // we sample densly, below we thin this out
00309         }
00310         x += (Co.X - Co.x)*2e-5;
00311       }
00312       /*cout << "BEFORE THIN: " << curve.Points.size() << endl; cout << "LAST POINT: " << curve.Points.rbegin()->x << " : " <<  curve.Points.rbegin()->y << endl; */
00313 
00314 
00315       // curve.thinOut(5e-4);
00316      
00317 
00318  /*      cout << "AFTER THIN: " << curve.Points.size() << endl;
00319               cout << "LAST POINT: " << curve.Points.rbegin()->x << " : " <<  curve.Points.rbegin()->y << endl; */
00320 
00321       curve.color = FromColor(*colors[idCount(i->first)]);  // get the color of this curve and convert from qt-color to my color
00322       things.Curves.push_back(curve);
00323     }
00324 
00325     // ============================================
00326     // === Construct data points
00327     // ============================================
00328 
00329     if (data) {
00330       count =0;
00331       for (list<Data*>::iterator i = data->begin(); i != data->end(); i++,count++) { 
00332         Data *d = *i;
00333         for (list<DataEntry>::iterator j = d->points.begin(); j != d->points.end(); j++) { 
00334           DataEntry e = *j;
00335           // calculate center of data point in 0..1 coordinates 
00336           // and get length of error - bar lines in 0..1 coordinates
00337           //double x1 = e.x, y1 = e.y;
00338           double x2 = e.xRight(), y2 = e.yMiddle();
00339           double x3 = e.xLeft(), y3 = e.yMiddle();
00340           double x4 = e.xMiddle(), y4 = e.yUpper();
00341           double x5 = e.xMiddle(), y5 = e.yLower();
00342           //pair<double,double> center = translate(x1,y1);
00343           pair<double,double> right_horizontal = translate(x2,y2);
00344           pair<double,double> left_horizontal = translate(x3,y3);
00345           pair<double,double> up_vertical = translate(x4,y4);
00346           pair<double,double> down_vertical  = translate(x5,y5);
00347           
00348           Curve vertical(up_vertical,down_vertical);
00349           Curve horizontal(left_horizontal,right_horizontal);
00350 
00351           vertical.color = FromColor(*dataColors[count]);
00352           horizontal.color = FromColor(*dataColors[count]);
00353           things.Curves.push_back(vertical);
00354           things.Curves.push_back(horizontal);
00355 
00356           double TipWidth = 4; // Width of the little bar at the tip of the errorbars
00357           pair<double,double> uptip1(up_vertical);
00358           pair<double,double> uptip2(up_vertical);
00359           uptip1.first -= TipWidth/scaleY;
00360           uptip2.first += TipWidth/scaleY;
00361           Curve uptip(uptip1,uptip2);
00362           uptip.color = horizontal.color;
00363           things.Curves.push_back(uptip);
00364           
00365           pair<double,double> downtip1(down_vertical);
00366           pair<double,double> downtip2(down_vertical);
00367           downtip1.first -= TipWidth/scaleY;
00368           downtip2.first += TipWidth/scaleY;
00369           Curve downtip(downtip1,downtip2);
00370           downtip.color = horizontal.color;
00371           things.Curves.push_back(downtip);
00372 
00373           
00374           pair<double,double> lefttip1(left_horizontal);
00375           pair<double,double> lefttip2(left_horizontal);
00376           lefttip1.second -= TipWidth/scaleX;
00377           lefttip2.second += TipWidth/scaleX;
00378           Curve lefttip(lefttip1,lefttip2);
00379           lefttip.color = horizontal.color;
00380           things.Curves.push_back(lefttip);
00381           
00382           pair<double,double> righttip1(right_horizontal);
00383           pair<double,double> righttip2(right_horizontal);
00384           righttip1.second -= TipWidth/scaleX;
00385           righttip2.second += TipWidth/scaleX;
00386           Curve righttip(righttip1,righttip2);
00387           righttip.color = horizontal.color;
00388           things.Curves.push_back(righttip);
00389                   
00390           /*
00391           cout << left_horizontal.first << " " << down_vertical.second << endl;  // lower left
00392           cout << left_horizontal.first << " " <<left_horizontal.second << endl; // left mid
00393           cout << right_horizontal.first << " " << right_horizontal.second << endl; // right mid
00394           cout << up_vertical.first << " " << up_vertical.second << endl;  // upper mid
00395           cout << down_vertical.first << " " << down_vertical.second << endl;  // lower mid 
00396           */
00397           
00398           
00399           
00400 
00401         }
00402       }
00403     }
00404 
00405 
00406     // =============================================
00407     // the tickmarks  --- first x-Axis
00408     // =============================================
00409     /*
00410     list<double> tick;
00411 
00412     if (logX()) logAxisTicks(Co.x,Co.X,tick,false);   
00413     else   axisTicks(Co.x,Co.X,tick);
00414 
00415     for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00416       double x = *i;
00417       double pos = translate(x,Co.y).first;
00418       things.XTickMarks.push_back(TickMark(pos));
00419       //TickLabel label = post.createLabel(x,pos,post.XTickLabelStyle);
00420       things.XTickLabels.push_back(label);
00421     }
00422     */
00423     for (map<float,string>::iterator i = post.XTickMarkList.begin(); i != post.XTickMarkList.end(); i++) {
00424       things.XTickMarks.push_back(TickMark(i->first));
00425       TickLabel label(i->first);
00426       label.grace = i->second;
00427       label.size = post.TickLabelSize*0.01*0.05;
00428       things.XTickLabels.push_back(label);
00429     }
00430 
00431  
00432 
00433     // =============================================
00434     // the tickmarks  --- now y-Axis
00435     // =============================================
00436     
00437     /*
00438     tick.clear();
00439 
00440     if (logY()) logAxisTicks(Co.y,Co.Y,tick,false);   
00441     else   axisTicks(Co.y,Co.Y,tick);
00442 
00443     for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00444       double y = *i;
00445       double pos = translate(Co.x,y).second;
00446       things.YTickMarks.push_back(TickMark(pos));
00447       TickLabel label = post.createLabel(y,pos,post.YTickLabelStyle);
00448       things.YTickLabels.push_back(label);
00449     } */ 
00450 
00451     for (map<float,string>::iterator i = post.YTickMarkList.begin(); i != post.YTickMarkList.end(); i++) {
00452       things.YTickMarks.push_back(TickMark(i->first));
00453       TickLabel label(i->first);
00454       label.grace = i->second;
00455       label.size = post.TickLabelSize*0.01*0.05;
00456       things.YTickLabels.push_back(label);
00457     }
00458    
00459     post.Things = things;
00460     post.plot(out);  // Go!
00461   }
00462 
00463   // =================== DONE CREATING THE PS-FILE =================
00464 
00465   if (fileNameGiven || !prt->outputFileName().isEmpty()) return;
00466 
00467   PrinterName = prt->printerName();
00468   launchLPR();
00469 }
00470 
00471 void PlotWidget::startDrawing(QRect rect) {
00472 
00473   // cout << "Stratdrawing in "  << this << endl;
00474 
00475   bool stop=false;
00476   
00477   if (Co.x >= Co.X) stop = true;
00478   if (logX() && ( Co.x <= 0 || Co.X <=0)) stop = true;
00479   if (logY() && ( Co.y <= 0 || Co.Y <=0)) stop = true; 
00480   if (Web) {
00481     if (Co.x < Web->x(0)) stop = true;
00482     if (Co.y < Web->y(0)) stop = true;
00483     if (Co.X > Web->x(Web->igrid)) stop = true;
00484     if (Co.Y > Web->y(Web->jgrid)) stop = true;
00485   }  
00486   
00487   if (stop) { 
00488     drawAxis();
00489     paint->setPen( Qt::red);
00490     paint->drawText((Width()*2)/5,(Height()*2)/5,"x-range invalid (you may consider autoscale)");  
00491   } else {
00492     
00493     bool goon = true;
00494     if (Blocks) { drawBlocks(); goon=false;}
00495     if (!RegionGroups.empty()) { drawRegions(); goon=false;}
00496     
00497     if (goon) {
00498       paint->setClipRect(xoffset,0,Width()-xoffset,Height()-yoffset);
00499       drawData();
00500       if (Rectangles) drawRectangles(rect);
00501       // cout << "SPLINES" << endl;
00502       drawSplines(rect);
00503       // cout << "done splines" << endl;
00504     }
00505     paint->setClipRect(0,0,Width(),Height());
00506     drawAxis();
00507   }
00508   // cout << " finished drawing in "  << this << endl;
00509 }
00510 
00511 
00512 void PlotWidget::drawAxis() {
00513   QColor grau(200,200,200);
00514   paint->setPen(grau);
00515   drawRect(0.0,1.0,1.0,1.0);
00516   
00517   list<double> tick;
00518   
00519   QFont f(font());
00520   QFont big( "Helvetica", 12);
00521   QFont small("Helvetica",8);
00522 
00523   LowLevelPlot help;
00524 
00525   // cout << "Drawaxis" << endl;
00526   double ticklength = 2.0/Height();
00527   double labeloffset = 2.0/Height();
00528 
00529   if (logX()) {
00530     logAxisTicks(Co.x,Co.X,tick,false);   
00531     for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00532       double x =*i; 
00533       double pos = translate(x,Co.y).first;
00534       TickLabel label = help.createLabel(x,pos,LowLevelPlot::exponent,1);
00535 
00536       drawLine(pos,-ticklength,pos,ticklength); 
00537       paint->setPen(Qt::black);
00538       int expwidth = fontMetrics().width(label.exponent.c_str());
00539       int basewidth =  fontMetrics().width("10");
00540       int middle = (expwidth + basewidth)/2;
00541       drawTextBase(pos,0,label.exponent.c_str(), -middle+basewidth+2,14);
00542       paint->setFont(big); 
00543       drawTextBase(pos,0,"10", -middle,19); 
00544       paint->setFont(f); 
00545       paint->setPen(grau);
00546     }
00547   } else {
00548     axisTicks(Co.x,Co.X,tick);
00549     for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00550       double x =*i; 
00551       double pos = translate(x,Co.y).first;
00552       TickLabel label = help.createLabel(x,pos,LowLevelPlot::decimal,3);
00553       //      cout << "label: " << x << "  " << label.decimal << endl;
00554       drawLine(pos,0.98,pos,1.02);
00555       paint->setPen(Qt::black);
00556       drawTextBase(pos,0,label.decimal.c_str(), -paint->fontMetrics().width(label.decimal.c_str())/2,14);
00557       paint->setPen(grau);
00558     }
00559   }
00560 
00561 
00562   tick.clear();
00563   ticklength = 2.0/Width();
00564   labeloffset = 2.0/Width();
00565   if (logY()) {
00566     logAxisTicks(Co.y,Co.Y,tick,true);
00567     for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00568       double y = *i; 
00569       double pos = translate(Co.x,y).second;
00570       TickLabel label = help.createLabel(y,pos,LowLevelPlot::exponent,1);
00571       drawLine(-ticklength,pos,ticklength,pos);
00572       paint->setPen(Qt::black);
00573       drawTextBase(-labeloffset,pos,label.exponent.c_str(), -fontMetrics().width(label.exponent.c_str()),14);
00574       paint->setFont(big); 
00575       drawTextBase(-labeloffset,pos,"10", -paint->fontMetrics().width(label.exponent.c_str())-  paint->fontMetrics().width("10"),19); 
00576       paint->setFont(f); 
00577       paint->setPen(grau);
00578     }
00579   } else {
00580     axisTicks(Co.y,Co.Y,tick);
00581     for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00582       double y = *i; 
00583       double pos = translate(Co.x,y).second;
00584       TickLabel label = help.createLabel(y,pos,LowLevelPlot::decimal,2);
00585       drawLine(-ticklength,pos,ticklength,pos); 
00586       paint->setPen(Qt::black);
00587       drawTextBase(-labeloffset,pos,label.decimal.c_str(), -paint->fontMetrics().width(label.decimal.c_str()),14);
00588       paint->setPen(grau);
00589     }
00590   }
00591   // cout << "~drawaxis" << endl;
00592 }
00593 
00594 
00595 void PlotWidget::autoTick(LowLevelPlot& plot) {
00596   // =============================================
00597   // the tickmarks  --- first x-Axis
00598   // =============================================
00599   list<double> tick;
00600   cout << "autoticking" << endl;
00601   if (logX()) logAxisTicks(Co.x,Co.X,tick,false);   
00602   else   axisTicks(Co.x,Co.X,tick);
00603   
00604   for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00605     double x = *i;
00606     double pos = translate(x,Co.y).first;
00607     LowLevelPlot::LabelStyle style = plot.XTickLabelStyle;
00608     if (logX()) style = LowLevelPlot::exponent;
00609     plot.XTickMarkList[pos] = plot.createGraceLabel(x,style,plot.Significant_x);
00610     cout << "x label for: " << x << "  " <<   plot.XTickMarkList[pos] << endl;
00611   }
00612 
00613 
00614   // =============================================
00615   // the tickmarks  --- now y-Axis
00616   // =============================================
00617     
00618   tick.clear();
00619     
00620   if (logY()) logAxisTicks(Co.y,Co.Y,tick,false);   
00621   else   axisTicks(Co.y,Co.Y,tick);
00622     
00623   for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00624     double y = *i;
00625     double pos = translate(Co.x,y).second;
00626     LowLevelPlot::LabelStyle style = plot.YTickLabelStyle;
00627     if (logY()) style = LowLevelPlot::exponent;
00628     plot.YTickMarkList[pos] = plot.createGraceLabel(y, style,plot.Significant_y); 
00629   }
00630 }
00631 
00632 void PlotWidget::semiAutoTick(LowLevelPlot& plot) {
00633   // =============================================
00634   // the tickmarks  --- first x-Axis
00635   // =============================================
00636 
00637  
00638   int cnt =0;
00639   for (float x = plot.StartTick_x; x <= Co.X*1.00001; x +=  plot.StepTick_x) {
00640     double pos = translate(x,Co.y).first;
00641     if (cnt++ > 20) throw Bad_Error("SemiAuto:: Too many x-axis ticks");
00642     plot.XTickMarkList[pos] = plot.createGraceLabel(x,plot.XTickLabelStyle,plot.Significant_x);
00643   }
00644 
00645 
00646   // =============================================
00647   // the tickmarks  --- now y-Axis
00648   // =============================================
00649    
00650   cnt=0;
00651   for (float y =  plot.StartTick_y; y <= Co.Y*1.00001; y +=  plot.StepTick_y) {
00652     if (cnt++ > 20) throw Bad_Error("SemiAuto:: Too many y-axis ticks");
00653     double pos = translate(Co.x,y).second;
00654     plot.YTickMarkList[pos] = plot.createGraceLabel(y, plot.YTickLabelStyle,plot.Significant_y); 
00655   }
00656 }
00657 
00658 void PlotWidget::logAxisTicks(double min,double max, list<double> &tick,bool yaxis) {
00659 
00660   if (min && max) {
00661     double lgMin = ceil(log(min)/log(10.0));
00662     double lgMax = floor(log(max)/log(10.0));
00663     
00664     if (lgMax - lgMin > 20) {
00665 //X       cout << "logAxisTicks:  lgMin: " << lgMin << "  lgMax: " << lgMax << endl;
00666       throw Bad_Error("PlotWidget::logAxisTicks(): Too many ticks");
00667     }
00668 
00669     for (double lg = lgMin; lg <= lgMax; lg++) {
00670       tick.push_back(pow(10,lg));
00671     }
00672   }
00673 }
00674 
00675 double  PlotWidget::axisTicks(double min, double max, list<double> &tick) {
00676   LowLevelPlot low;
00677   double range = max - min;
00678 //X   cout << "axisticks: min: " << min <<  "  " << max << endl;
00679   if (range == 0) return 1;
00680 
00681   double sgn=1.0;
00682   if (min < 0) sgn = -1.0;
00683   int order = (int)floor(log10(range))-1;
00684   //  if (order >= 0) order = floor(order); else order = ceil(order);
00685   
00686   double start=0, startexp=0,startfactor=0;
00687   if (min != 0) {
00688     start = fabs(min);
00689     startexp = low.splitExponent(start);
00690     startfactor = low.splitPrefactor(start);
00691   }
00692 
00693   //cout << "start: " << start << " startexp: " << startexp << "  startfact: " << startfactor << endl;
00694   //  cout << "order: " << order << endl;
00695   
00696   double pre[] = {1,2,2.5,5};
00697   
00698   for (int od = order; od <= order+2; od ++) {
00699     for (int i = 0; i < 4; i++) {
00700       double skip = pre[i];
00701       double unit = skip*pow(10.0,od);
00702       //      cout << "skip: " << skip << " unit: "<<unit << endl;
00703       double x = (rint(min / unit)-1)*unit;  // start one unit before the start
00704       tick.clear();
00705       do {
00706         if (fabs(x/unit) < 1e-5) x = 0;
00707         //      cout << "strt: " << x << endl;
00708         if (x >= min && x <= max) tick.push_back(x);
00709         x += unit;
00710       } while (x <= max && tick.size() < 12);
00711       if (tick.size() < 12) break;
00712     }
00713     if (tick.size() < 12) break;
00714   }
00715   
00716   for (list<double>::iterator i = tick.begin(); i != tick.end(); i++) {
00717     //    cout << "final: " << *i << endl;
00718   }
00719 
00720   return 1.0;
00721 
00722 
00723 
00724   
00725 
00726 
00727 
00728 
00729   double factor=0;
00730   if (range > 0) {
00731     double order = (int)floor(log(range)/log(10.0));
00732     if (fabs(order) > 3) {factor = order; order =0;}
00733     
00734     double unit = pow(10,factor+order);
00735     double pack = range/unit;
00736 
00737     //cout << "at first: unit " << unit << endl;
00738     //cout << "at first: pack " << pack << endl;
00739     while (pack < 5 && pack*2 <12) { unit*=0.5; pack*=2;}
00740 
00741     int k = (int) rint(min / unit);
00742   
00743     
00744     // cout << "range: " << range << endl;
00745 //     cout << "order:" << order << endl;
00746 //     cout << "faktor: " << factor << endl;
00747 //     cout << "pack: " << pack << endl;
00748 //     cout << "unit: " << unit << endl;
00749 //     cout << "k: " << k << endl;
00750     int cnt=0;
00751     while (k * unit < max) {
00752       if (k*unit > min) {
00753         if (cnt++ > 20) throw Bad_Error("PlotWidget::axisTicks(): Too many ticks");
00754         tick.push_back(k*unit * pow(10,-factor));
00755       }
00756       k++;
00757     }
00758   }  
00759   return factor;
00760 }
00761 
00762 void PlotWidget::drawData() {
00763   if (data) {
00764     // cout << "PAINTING DATA" << endl;
00765     //if (paint ==0) paint = new QPainter(this);
00766     int count =0;
00767     for (list<Data*>::iterator i= data->begin(); i != data->end(); i++,count++) drawDataSet(*i,count);
00768   
00769     //if (paint) delete paint; paint=0;
00770   }
00771 }
00772 
00773 void PlotWidget::drawDataSet(Data* d, int count ) {
00774   //  cout << "drawDataSet" << endl;
00775   paint->setPen(*dataColors[count]);
00776   //  cout << "PAINTING set " << endl;
00777   for (list<DataEntry>::iterator i = d->points.begin(); i != d->points.end(); i++) drawSingleDataEntry(*i);
00778   //  cout << "done" << endl;
00779 }
00780 
00781 void PlotWidget::drawSingleDataEntry(const DataEntry &point) {
00782   //cout << "try to paint point: " << point.x << "  " << point.y   << endl;
00783 
00784   if (point.x()  < Co.x && point.x() > Co.X)  return;
00785 
00786   drawDataLine(point.xMiddle(),point.yLower(), point.xMiddle(), point.yUpper());
00787   drawDataLine(point.xRight(),point.yMiddle(),point.xLeft(),point.yMiddle());
00788   drawFixedYDataLine(point.xMiddle(), point.yUpper(), -3, +3);
00789   drawFixedYDataLine(point.xMiddle(), point.yLower(), -3, +3);
00790   drawFixedXDataLine(point.xRight(), point.yMiddle(),-3,+3);
00791   drawFixedXDataLine(point.xLeft(), point.yMiddle(),-3,+3);
00792 }
00793 
00794 
00795 QString PlotWidget::toStr(double x,int post) {
00796   QString tmp;
00797   tmp.setNum(x);
00798   int k = tmp.indexOf('.');
00799   int e = tmp.indexOf('e');
00800 
00801   if (k == -1 && e == -1) return tmp;   // not . not e
00802   if (e == -1) return tmp.left(k+1+post);  //  .  but no e
00803   
00804   // both
00805   
00806   return tmp.left(k+1+post) + tmp.right(tmp.length()-e);
00807 }
00808 
00809 
00810 
00811 
00812 int  PlotWidget::setSpline(const Spline &s) {
00813   Spline *neu = new Spline(s.size(), "plotwidget"); 
00814   neu->getData(s);
00815   neu->arm();
00816   splines[++SplineId] = neu;
00817   (*validIds)[SplineId] = true;
00818   return SplineId;
00819 }
00820 
00821 Spline* PlotWidget::getSpline(int idx) {
00822   Spline *s = 0;
00823   if (splines.find(idx) != splines.end()) s = splines[idx];
00824   return s;
00825 }
00826 
00827 void PlotWidget::ridOf(int id, bool doRepaint) {
00828   if (splines.find(id) != splines.end()) splines.erase(splines.find(id));  //erase the spline
00829   if (validIds->find(id) != validIds->end())  validIds->erase(validIds->find(id));  // erase the id 
00830   if (doRepaint) repaint();
00831 }
00832 
00833 void PlotWidget::checkPainter() {
00834   if (paint) return;
00835   paint = new QPainter(this);
00836 }
00837 
00838 
00839 void PlotWidget::drawSpline(int id, const QColor &c,  Qt::PenStyle  style) {
00840   QRect rect(0,0,Width(),Height());
00841   drawSpline(id,c,style,rect);
00842 }
00843 
00844 void PlotWidget::drawSpline(int id, const QColor &c,  Qt::PenStyle  style, QRect &rect) {
00845   //cout << "drawSpline: " << id << endl;
00846   //if (paint ==0) paint = new QPainter(this);
00847   
00848   //cout  << "Plotwidget: " << this << "   drawSpline: " << splines[id] << endl;
00849 
00850   checkPainter();
00851   paint->setPen(c);
00852   paint->setClipRect(xoffset,0,Width(),Height()-yoffset);
00853   //p().setPen(style);
00854   clearDrawPath();
00855  
00856   Spline &s = *splines[id];
00857   
00858   int left = max(xoffset, rect.left()-3);
00859   int right=min(Width(),rect.right()+3);
00860   int top = max(0,rect.top()-3);
00861   int bottom = min(Height(),rect.bottom()+3);
00862   double ymax = reverse_y(top);
00863   double ymin = reverse_y(bottom);
00864   double store_x,store_y;
00865   bool stored=false; // if there is a point that could not be drawn (i.e. y out of bound)
00866   bool drawn=false; // if at least one point is in the path, true
00867   //cout << "draw spline in " << left << "  " << right << endl;
00868   double y;
00869   for (int pixel=left; pixel <= right; pixel++) { 
00870     double x = reverse_x(pixel);
00871     //    cout << " reverse x of " << pixel << "  =  " << x << endl;
00872     if ( x <=  s.stop()  && x >= s.start())  { 
00873       y = s(x);
00874       //      cout << "x: " << x << " y: "  << y << endl;
00875       if (y <= ymax && y>=ymin) {
00876         if (stored) {  // one point left to the boundary
00877           drawDataPoint(store_x,store_y,true); 
00878           stored=false;
00879         }
00880         drawDataPoint( x,  y, true );
00881         drawn=true;
00882       } else {
00883         store_x = x; store_y=s(x); stored=true;
00884         if (drawn) { // so this is one point right to the boundary
00885           drawn = false;
00886           drawDataPoint(x,s(x),true); 
00887         }
00888       }
00889     } 
00890   }
00891   drawPath();
00892   //if (paint) delete paint; paint=0;
00893 } 
00894 
00895 
00896 void PlotWidget::drawRectangles(QRect rect) {
00897   checkPainter();
00898   paint->setClipRect(xoffset,0,Width(),Height()-yoffset);
00899   for (list<Rectangle>::iterator i = Rectangles->begin(); i != Rectangles->end(); i++) {
00900     
00901     pair<double,double> left_up  = translate(i->C.x,i->C.Y);
00902     pair<double,double> left_down  = translate(i->C.x,i->C.y);
00903     pair<double,double> right_down  = translate(i->C.X,i->C.y);
00904     
00905     double x = left_up.first;
00906     double Y = left_up.second;
00907     double w = right_down.first - x;
00908     double h =  Y - right_down.second ;
00909 
00910     int ix = tx(x);
00911     int iY = ty(Y);
00912     int iw = sx(w);
00913     int ih = sy(h);
00914     
00915     QBrush black(QColor(0,0,0));
00916     QBrush brush(ToColor(i->FillColor));
00917 
00918     fillRect(ix-1,iY-1,iw+1,ih+1,black);
00919     fillRect(ix,iY,iw,ih,brush);
00920 
00921   }  
00922 }
00923 
00924 void PlotWidget::drawSplines() {
00925   drawSplines(QRect(0,0,Width(),Height()));
00926 }
00927 
00928 void PlotWidget::drawSplines(QRect rect) {
00929   int count = 0;
00930   for (map<int,Spline*>::iterator i=splines.begin(); i != splines.end();i++,count++) 
00931     drawSpline(i->first, *colors[idCount(i->first)] , Qt::SolidLine,rect);
00932 }  
00933 
00940 void PlotWidget::drawDataPoint(double x,double y, bool store) {
00941   double X,Y;
00942   if (logX()) X = (log(x)-log(Co.x))/(log(Co.X) - log(Co.x)); else X = (x-Co.x)/(Co.X - Co.x);
00943   if (logY()) Y = (log(y)-log(Co.y))/(log(Co.Y) - log(Co.y)); else Y = (y-Co.y)/(Co.Y-Co.y);
00944  
00945   if (store) DrawPath.push_back(QPoint(tx(X),ty(Y))); else 
00946     paint->drawPoint(tx(X),ty(Y));
00947 }
00948 
00949 
00953 pair<double,double> PlotWidget::translate(double x,double y) {
00954   double X,Y;
00955   //cout << "Y, Co.y : " << Y << "  " << Co.y << "  max " << max(Y,Co.y) << "  ";
00956   //y = max(y,Co.y);
00957 
00958   if (logX()) X = (log(x)-log(Co.x))/(log(Co.X) - log(Co.x)); else X = (x-Co.x)/(Co.X - Co.x);
00959   if (logY()) Y = (log(y)-log(Co.y))/(log(Co.Y) - log(Co.y)); else Y = (y-Co.y)/(Co.Y-Co.y);
00960   return pair<double,double>(X,Y);
00961 }
00962 
00963 CoordPoint PlotWidget::translateCoordPoint(CoordPoint& p) {
00964   pair<double,double> paar = translate(p.x,p.y);
00965   return CoordPoint(paar.first,paar.second);
00966 }
00967 
00968 
00969 
00970 
00971 void PlotWidget::drawDataLine(double x1,double y1, double x2,double y2) {
00972   // cout << y1 << "  " << Co.y << "  ";
00973   pair<double,double> a = translate(x1,y1);
00974   pair<double,double> b = translate(x2,y2);
00975 
00976   int X1= Rint(tx(a.first)), Y1 = Rint(ty(a.second));
00977   int X2= Rint(tx(b.first)), Y2 = Rint(ty(b.second));
00978    
00979   if (max(X2,X1) <= xoffset) return;
00980   if (min(Y1,Y2) >= Height() - yoffset) return; 
00981 
00982   X1 = max(X1,xoffset);
00983   X2 = max(X2,xoffset);
00984   if (min(Y1,Y2) >= Height() - yoffset) return; 
00985   paint->drawLine(X1,Y1,X2,Y2);
00986 }
00987 
00988 void PlotWidget::drawFixedXDataLine(double x,double y,int top,int bottom) { 
00989   pair<double,double> a = translate(x,y);
00990   int X1 = Rint(tx(a.first)), Y1 = Rint(ty(a.second)) + top;
00991   int Y2 = Y1 - top + bottom;
00992   
00993   if (X1 <= xoffset) return;
00994   if (min(Y1,Y2) >= Height() - yoffset) return; 
00995   Y2 = min(Y2,Height()-yoffset);
00996   Y1 = min(Y1,Height()-yoffset);
00997   
00998   paint->drawLine(X1,Y1, X1,Y2);
00999 }
01000 
01001 void PlotWidget::drawFixedYDataLine(double x,double y,int left,int right) { 
01002   pair<double,double> a = translate(x,y);
01003   int X1= Rint(tx(a.first)) + left, Y1 = Rint(ty(a.second));
01004   int X2= X1 - left + right;
01005   if (X1 <= xoffset) return;
01006   if (Y1 >= Height() - yoffset) return; 
01007   paint->drawLine(X1,Y1,X2,Y1);
01008 }
01009 
01010 int PlotWidget::tx(double x) { return (int)rint(xoffset +  (Width()-xoffset)*x); }
01011 int PlotWidget::ty(double y) { return (int)rint( (Height()-yoffset)*(1.0-y) ); }
01012 
01013 
01014 
01015 void PlotWidget::altDrawPath() {
01016   if (DrawPath.size() < 2 ) return;
01017   
01018   QPolygon a(100000);
01019   QPen save = paint->pen();
01020   int step = 1,point = -1;
01021   double distance;
01022   QPoint last;
01023   for (list<QPoint >::iterator j=DrawPath.begin(); j != DrawPath.end();j++,step++ ) {
01024     if (step == 1) distance =1e5;    
01025     if (step != 1) distance = pow((double)last.x()- j->x(),2) + pow((double)last.y() - j->y(),2);
01026     if (distance > 9) {
01027       a.setPoint(++point,*j);
01028       last  = *j;
01029     }
01030   }
01031   // cout << "*********************************" << endl;
01032   //cout << step << "  and point  " << point << endl;
01033   a.resize(point);
01034   paint->setPen(save);
01035   if (IsPrinting) {
01036     paint->drawPolyline(a);
01037   } else paint->drawPoints(a);
01038 }
01039 
01044 void PlotWidget::drawPath() {
01045   if (IsPrinting) {
01046     altDrawPath(); return;
01047   }
01048   if (DrawPath.size() < 2 ) return;
01049 
01050  
01051   QPolygon neu(DrawPath.size());
01052   unsigned int k =0;
01053   for  ( list<QPoint >::iterator i = DrawPath.begin();  i != DrawPath.end(); i++,k++) {
01054     neu.setPoint(k,*i);
01055   }
01056   paint->drawPolyline(neu);
01057   return;
01058   
01059   QPolygon a(100000);
01060   QPolygon alias(100000), dark(100000);
01061   
01062   list<QPoint >::iterator i = DrawPath.begin(); 
01063 
01064   QPen save = paint->pen();
01065   //int step = -1;
01066   int point = -1;
01067   int ap = -1,dc =-1;
01068 
01069   a.setPoint(++point,*i);
01070   
01071   list<QPoint >::iterator j;
01072   for(;;) {
01073     j = i;
01074     if (++j == DrawPath.end()) break;
01075     int x1 = i->x(); 
01076     int y1= i->y();
01077 
01078     int x2 = j->x();
01079     int y2 = j->y();
01080 
01081    
01082     int dx = x2 - x1, dy = y2-y1;
01083 
01084     int total =0;
01085     if (abs(dx) > abs(dy))  {  // rather horizontal
01086       int count_y = 0;
01087       //cout << "horizontal " << endl;
01088       if (dy) count_y = (int)rint(0.5 * (float)abs(dx)/(float)abs(dy));
01089       while (total <= abs(dx)) {
01090         if (a.point(point).x() != x1 ||  a.point(point).y() != y1) {
01091           a.setPoint(++point,x1,y1);
01092           
01093           alias.setPoint(++ap, x1,y1+1);
01094           alias.setPoint(++ap, x1,y1-1);
01095         }
01096         int yold = y1;
01097         count_y += abs(dy);
01098         if (count_y > abs(dx)) {
01099           count_y -= abs(dx); 
01100           if (dy > 0) y1++; else y1--;
01101         }
01102         dark.setPoint(++dc, x1,y1);
01103         if (dx > 0) x1++; else x1--;
01104         dark.setPoint(++dc, x1,yold);
01105         total++;
01106       }
01107     } else {
01108       int count_x = 0;
01109       if (dx) count_x = (int)rint(0.5 * (float)abs(dy) / (float)abs(dx));
01110       while (total <= abs(dy)) {
01111         if (a.point(point).x() != x1 ||  a.point(point).y() != y1) {
01112           a.setPoint(++point,x1,y1);
01113          
01114           alias.setPoint(++ap, x1+1,y1);
01115           alias.setPoint(++ap, x1-1,y1);
01116         }
01117 
01118         count_x += abs(dx);
01119         int xold = x1;
01120         if (count_x > abs(dy)) {
01121           count_x -= abs(dy); 
01122           if (dx > 0) x1++; else  x1--;     
01123         }
01124         dark.setPoint(++dc, x1,y1);
01125         if (dy > 0) y1++; else y1--;
01126         dark.setPoint(++dc, xold,y1);
01127         total++;
01128       }
01129     }
01130     i++;
01131   }
01132   //cout << "insgesamt: " << point << endl;
01133   a.resize(point);
01134 
01135   if (antiAlias()) {
01136 
01137     alias.resize(ap);
01138     dark.resize(dc);
01139    
01140     paint->setPen(blend(0.4));
01141     paint->drawPoints(alias);
01142     
01143     paint->setPen(blend(1.4));
01144     paint->drawPoints(dark);
01145   }
01146 
01147   paint->setPen(save);
01148   if (IsPrinting)  {
01149     uint j=0;
01150     QPolygon b(a.size());
01151       //      cout << a.point(i).x() << "  " << a.point(i).y();
01152 
01153    for ( int i = 0; i < a.size(); i++ ) {
01154       //      cout << a.point(i).x() << "  " << a.point(i).y();
01155       if (  ( i&1 ) == 1 ) {
01156         //cout << "   in b ";
01157         b.setPoint( j++,a.point( i ).x(),a.point( i ).y() );
01158       }
01159       //cout << endl;
01160     } 
01161     b.resize(j);    
01162     paint->drawPolyline(b);
01163   } else paint->drawPoints(a);
01164   //  for( list<QPoint >::iterator i = DrawPath.begin();  i != DrawPath.end(); i++) {
01165   //p().setPen(QColor(255,255,255));
01166   //p().drawPoint(*i);
01167   //}
01168 }
01169 
01170 QColor PlotWidget::blend(float ratio) {
01171   const QColor &b = palette().background().color();
01172   const QColor &c = paint->pen().color();
01173   float norm = 1.0 + ratio;
01174   float red = b.red() + ratio* c.red();
01175   float green = b.green() + ratio * c.green();
01176   float blue = b.blue() + ratio * c.blue();
01177   return QColor((int)rint(red/norm), (int)rint(green/norm), (int)rint(blue/norm));
01178 }
01179 
01186 void PlotWidget::autoScale(bool doX, bool notify)
01187 {
01188   if (Web) {
01189     if (doX) {
01190       Co.x = Web->x(0);
01191       Co.X = Web->x(Web->igrid);
01192     }
01193     Co.y = Web->y(0);
01194     Co.Y = Web->y(Web->jgrid);
01195   }
01196 
01197 
01198   if (! Blocks && !Web)  {
01199     Co.Y = -1e100;
01200     Co.y=1e100;
01201     if (doX) {
01202       Co.X = -1e100;
01203       Co.x=1e100;
01204     }
01205 
01206     for (map<int,Spline*>::iterator i=splines.begin(); i != splines.end();i++) {
01207       Spline &s = * i->second;
01208       //s->printStatus();
01209       for (int j = 0; j < s.size(); j++) {
01210         if (doX) {
01211           if (s.x(j) > Co.X) Co.X = s.x(j);
01212           if (s.x(j) < Co.x) Co.x = s.x(j);      
01213         }
01214         if (s.x(j) >= Co.x && s.x(j) <= Co.X) {  // for honoring x range in doX false case
01215           if (s.y(j) > Co.Y) Co.Y = s.y(j);
01216           if (s.y(j) < Co.y) Co.y = s.y(j); 
01217         }
01218       }
01219 
01220 
01221       for (double x = s.start(); x <= s.stop(); x += s.range(10000)) {
01222         if (x >= Co.x && x  <= Co.X) {  // for honoring x range in doX false case
01223           double w = s(x);
01224           if (w > Co.Y) Co.Y = w;
01225           if (w < Co.y) Co.y = w;
01226         }
01227       } 
01228     }
01229 //     cout << "AUTOSCALE : Co.Y : " << Co.Y << endl;
01230 //     cout << "AUTOSCALE: Co.y : " << Co.y << endl;
01231     if (data) {
01232       for (list<Data*>::iterator i= data->begin(); i != data->end(); i++) {
01233         for (list<DataEntry>::iterator j =(*i)->points.begin(); j != (*i)->points.end(); j++) {
01234           if (doX) {
01235             if (j->xRight() > Co.X) Co.X = j->xRight();
01236             if (j->xLeft()  < Co.x) Co.x = j->xLeft();
01237           }
01238           if (j->x()  >= Co.x && j->x() <= Co.X) {  // for honoring x range in doX false case
01239             if (j->yUpper() > Co.Y) Co.Y = j->yUpper();
01240             if (j->yLower() < Co.y && j->yLower() > 0) Co.y = j->yLower();
01241           }
01242         }
01243       }
01244     }
01245 
01246     Co.Y += (Co.Y  - Co.y)*0.05;
01247   }
01248   //  cout << "PLOTWIDGET: " << this << "  has min_y: " << Co.y << "  Max_y: " << Co.Y << endl;
01249   if (notify) emit(scaleChanged());
01250 }
01251 
01252 
01253 void PlotWidget::keyPressEvent(QKeyEvent *e) {
01254   double shift_x = 0.1*(Co.X - Co.x);
01255   double shift_y = 0.1*(Co.Y - Co.y);
01256   //cout << "key press even " << endl;
01257   if (e->key() == Qt::Key_Left) {Co.x -= shift_x; Co.X -=shift_x;}
01258   if (e->key() == Qt::Key_Right) {Co.x += shift_x; Co.X += shift_x;}
01259   if (e->key() == Qt::Key_Down) {Co.y -= shift_y; Co.Y -=shift_y;}
01260   if (e->key() == Qt::Key_Up) {Co.y += shift_y; Co.Y += shift_y;}
01261   delete paint; paint=0;
01262   repaint();
01263   emit (scaleChanged());
01264 }
01265 
01266 void PlotWidget::mousePressEvent(QMouseEvent *e) {
01267   if (e->button() == Qt::MidButton) {
01268     //cout << "MP: " << e->x() << endl;
01269     MidMouseDown = true;
01270     MidMouseMove = false;
01271     MidMouseX = e->x();
01272     MidMouseY = e->y();
01273   }
01274   if (e->button() == Qt::LeftButton) {
01275     LeftMouseX = e->x();
01276     LeftMouseY=e->y();
01277     RepaintReason = LeftButtonPressed;
01278     update();
01279   }
01280 
01281   if (e->button() == Qt::RightButton) {
01282     if (RegionGroups.empty())
01283       emit pressedRMB(detectCollision(e->pos()),e->pos());
01284     else
01285       emit pressedRMB(detectRegionGroup(e->pos()),e->pos());
01286   }
01287 }
01288 
01289 void PlotWidget::colorRegionGroup(int id) {
01290   QColor A= QColorDialog::getColor();
01291   if ( !A.isValid() ) return; // dialog was cancelled
01292   QColor a= QColorDialog::getColor();
01293   if ( !a.isValid() ) return; // dialog was cancelled
01294 #if 0
01295   bool ok;
01296   QColor A= QColorDialog::getRgba(Qt::white, &ok);
01297   if ( !ok ) return;
01298   QColor a= QColorDialog::getRgba(Qt::white, &ok);
01299   if ( !ok ) return;
01300 #endif
01301 
01302   ConfidenceRegionGroup &group  = RegionGroups[id];
01303   double x = group.Regions.size()-1; // how many need to be shaded ?
01304   x = max(x,1.0);
01305 
01306   int r = a.red(); int g = a.green(); int b = a.blue(); int t = a.alpha();
01307   int R = A.red(); int G = A.green(); int B = A.blue(); int T = A.alpha();
01308 
01309   //cout << "r: " << r << "  g: " << g << " b: " << b << endl;
01310   //cout << "R: " << R << "  G: " << G << " B: " << B << endl;
01311 
01312 
01313   double count = 0;
01314   for (list<ConfidenceRegion>::iterator i = group.Regions.begin(); i != group.Regions.end(); i++) {
01315     float v_r =  (r + count*(R-r)/x) / 255.;
01316     float v_g =  (g + count*(G-g)/x) / 255.;
01317     float v_b =  (b + count*(B-b)/x) /255.;
01318     float v_t =  (t + count*(T-t)/x) /255.;
01319     cout << "count: " << count << " v_r: " << v_r   << " v_g: " << v_g  << " v_b: " << v_b << " v_t: "<< v_t << endl;
01320     count++;
01321 //X     i->FillColor = Color(v_r,v_g,v_b,v_t);
01322     i->FillColor = Color(v_r,v_g,v_b);
01323     // check if the pencolor is black or white indicating 1,2,3 sigma boundaries
01324     float cr = i->PenColor.r;
01325     float cg =  i->PenColor.g;
01326     float cb =  i->PenColor.b;
01327     bool isspecial = false;
01328     if (cr == 1 && cg == 1 && cb == 1) isspecial = true;
01329     if (cr == 0 && cg == 0 && cb == 0) isspecial = true;
01330     if (! isspecial) i->PenColor = Color(v_r,v_g,v_b);
01331   }
01332 }
01333 
01334 void PlotWidget::deleteRegionGroup(int id) {
01335   map<int,ConfidenceRegionGroup> replace;              
01336   int k =0;
01337   for (unsigned int i =0; i < RegionGroups.size(); i++) {
01338     if ((int) i != id) replace[k++] = RegionGroups[i];
01339   }
01340   RegionGroups = replace;
01341   drawRegions();
01342 }
01343 
01344 void PlotWidget::toFront(int id) {
01345   cout << "to front for : " << id << endl;
01346   ConfidenceRegionGroup tmp = RegionGroups[id];
01347   for ( unsigned int j = (unsigned int)id + 1; j < RegionGroups.size(); j++) RegionGroups[j-1] = RegionGroups[j];
01348   RegionGroups[RegionGroups.size()-1] = tmp;
01349   cout << "done to front" << endl;
01350 }
01351 void PlotWidget::toBack(int id) {
01352   cout << "to back for : " << id << endl;
01353   ConfidenceRegionGroup tmp = RegionGroups[id];
01354   for (unsigned int j = RegionGroups.size()-1; j > 0 ; j--) RegionGroups[j] = RegionGroups[j-1];
01355   RegionGroups[0] = tmp;
01356 }
01357 
01358 
01359 
01360 void PlotWidget::paintOnLeftButtonPress()
01361 {
01362     checkPainter();
01363     paint->setPen(Qt::DashLine);
01364     paint->setPen(QColor(150,150,150));
01365     paint->drawLine(LeftMouseX,0,LeftMouseX,Height()-yoffset);
01366     paint->drawLine(xoffset,LeftMouseY,Width(),LeftMouseY);
01367     paint->setPen(Qt::black);
01368     displayCoords(reverse_x(LeftMouseX),reverse_y(LeftMouseY));
01369     paint->setPen(Qt::SolidLine);
01370 }
01371 
01372 void PlotWidget::mouseReleaseEvent(QMouseEvent *e) {
01373   if (e->button() == Qt::MidButton) {
01374     MidMouseDown = false; 
01375     if (MidMouseMove) {
01376       // repaint(OldMidMouse);
01377       // we got to store this, otherwise reverse_x gets corrupted
01378       double d2  = pow((double)MidMouseX-e->x(),2) + pow((double)MidMouseY-e->y(),2); 
01379       // if box is too small, maybe this is only an accident then do
01380       // nothing
01381       //cout << "D2: " << d2 << endl;
01382       if (d2 > 200) {  
01383         Zoom.push(Co);  // store old
01384         double mx = reverse_x(OldMidMouse.x()); 
01385         Co.X = reverse_x(OldMidMouse.x()+OldMidMouse.width());
01386         Co.x = mx;
01387         mx = reverse_y(OldMidMouse.y());
01388         Co.y = reverse_y(OldMidMouse.y()+OldMidMouse.height());
01389         Co.Y = mx;
01390       }
01391     } else  revertZoom();
01392     delete paint; paint=0;
01393     repaint();
01394     emit(scaleChanged());
01395   }
01396   if (e->button() == Qt::LeftButton) {
01397     LeftMouseMove=false;
01398     delete paint; paint=0;
01399     repaint();
01400   }
01401 }
01402 
01403 void PlotWidget::leaveEvent(QEvent *e) {
01404   if ( RegionGroups.empty() ) return;
01405 
01406   unHighlightRegionGroups();
01407   RepaintReason = MouseMoved;
01408   repaint();
01409 }
01410 
01417 void PlotWidget::mouseMoveEvent(QMouseEvent *e) {
01418   //if (e->button() == QMouseEvent::LeftButton) {
01419   //checkPainter(); 
01420   //cout << "MM" << e->x() << endl;
01421   if (MidMouseDown) {
01422     if (!MidMouseMove) {
01423       delete paint;paint=0;
01424       repaint(); // in this case, get rid of the coordinate crosshair
01425     }
01426     //cout << "MM and LEFTMOUSE"<<endl;
01427     MidMouseMove = true;
01428     int x = MidMouseX, y = MidMouseY;
01429     int w = x - e->x();
01430     int h = y - e->y();
01431     if (w > 0) x = e->x();
01432     if (h > 0) y = e->y();
01433     w = abs(w); h = abs(h);
01434     NewMidMouse = QRect( x, y, w, h );
01435     RepaintReason = MidButtonMoved;
01436     update();
01437   } else if (e->buttons() == Qt::LeftButton) {
01438     RepaintReason = LeftButtonMoved;
01439     NewLeftMouseX = e->x();
01440     NewLeftMouseY = e->y();
01441     repaint();
01442   } else {
01443     mouseMovedPos = e->pos();
01444     RepaintReason = MouseMoved;
01445     update();
01446  }
01447 }
01448 
01449 void PlotWidget::paintOnMidMouseMove()
01450 {
01451   if (OldMidMouse.isValid()) {
01452  /* Georg: it seems we don't need this?
01453     QRect &o = OldMidMouse;
01454     checkPainter(); 
01455     paint->setPen(Qt::white);
01456     paint->drawRect(OldMidMouse);
01457     delete paint; paint=0;
01458     //cout << "old mid mouse repaint" << endl;
01459     update(o.x()+1,o.y()+1,2,o.height());
01460     update(o.right(),o.y(),2,o.height());
01461     update(o.x(),o.y(),o.width(),2);
01462     update(o.x(),o.bottom(),o.width(),2);
01463 */
01464   }
01465   checkPainter(); 
01466   paint->setPen(Qt::black);
01467   //cout << "drawRect: " << x << "  " << y << "  :: " << abs(w) << "   " << abs(h) << endl;
01468   OldMidMouse = NewMidMouse;
01469   paint->drawRect(OldMidMouse);
01470   //paint->drawRect(x, y, abs(w),abs(h));
01471 }
01472 
01473 
01474 void PlotWidget::paintOnLeftMouseMove()
01475 {
01476     // first erase the old stuff :-)
01477     checkPainter();
01478 /*
01479     paint->setPen(Qt::white);
01480     if (LeftMouseX != NewLeftMouseX) paint->drawLine(NewLeftMouseX,0,NewLeftMouseX,Height()-yoffset);
01481     if (LeftMouseY != NewLeftMouseY) paint->drawLine(xoffset,NewLeftMouseY,Width(),NewLeftMouseY);
01482 */
01483     displayCoords(reverse_x(NewLeftMouseX),reverse_y(NewLeftMouseY));
01484      delete paint;paint=0;
01485 /*
01486     update(0,NewLeftMouseY,Width(),2);
01487     update(NewLeftMouseX,0,2,Height());
01488 */
01489     // paint->fillRect(0,LeftMouseY,Width(),2,QBrush(QColor(255,0,0)));
01490     //paint->fillRect(LeftMouseX,0,2,Height(),QBrush(QColor(0,0,255)));
01491     delete paint;paint=0;
01492     LeftMouseX = NewLeftMouseX;
01493     LeftMouseY = NewLeftMouseY;
01494 
01495     checkPainter();
01496     paint->setPen(Qt::DashLine);
01497     paint->setPen(QColor(150,150,150));    
01498     paint->drawLine(LeftMouseX,0,LeftMouseX,Height()-yoffset);
01499     paint->drawLine(xoffset,LeftMouseY,Width(),LeftMouseY);
01500     paint->setPen(Qt::black);
01501     displayCoords(reverse_x(LeftMouseX),reverse_y(LeftMouseY));
01502     paint->setPen(Qt::SolidLine);
01503 }
01504 
01505 void PlotWidget::paintOnMouseMove()
01506 {
01507   static int clean = 0;
01508   int id = detectCollision(mouseMovedPos,3);
01509   if (id) {
01510     if (id != clean && clean != 0) drawSplines();
01511     clean = id;
01512     drawSpline(id, QColor(200,200,0), Qt::SolidLine);
01513     emit highlighted(id);
01514   } else {
01515     if (clean) drawSplines();
01516     clean = 0;
01517   }
01518   // after checking for spline collisions, let's check 
01519   // for confidenceregions
01520   id = detectRegionGroup(mouseMovedPos);
01521   //cout << "id from detectRegion: " << id << endl;
01522   if (id != -1) {
01523     if (! RegionGroups[id].Highlighted) { //not yet set for highlighting
01524       for (map<int,ConfidenceRegionGroup>::iterator g = RegionGroups.begin(); g != RegionGroups.end(); g++) {
01525         g->second.Highlighted=false;
01526       }
01527       RegionGroups[id].Highlighted = true;   
01528       drawRegions();
01529     }
01530   } else {
01531     // so no region is under cursor, but maybe was ?
01532     for (map<int,ConfidenceRegionGroup>::iterator g = RegionGroups.begin(); g != RegionGroups.end(); g++) {
01533       if (g->second.Highlighted) {
01534         g->second.Highlighted=false;
01535         drawRegions();
01536         break;
01537       }
01538     }
01539   } 
01540 }
01541 
01542 void PlotWidget::unHighlightRegionGroups()
01543 {
01544     for (map<int,ConfidenceRegionGroup>::iterator g = RegionGroups.begin(); g != RegionGroups.end(); g++) {
01545       if (g->second.Highlighted) {
01546         g->second.Highlighted=false;
01547         break;
01548       }
01549     }
01550 }
01551 
01552 int PlotWidget::detectRegionGroup(const QPoint &pos) {
01553   if ( !visibleRegion().contains( pos ) ) return -1;
01554 
01555   for (map<int,ConfidenceRegionGroup>::reverse_iterator g = RegionGroups.rbegin(); g != RegionGroups.rend(); g++) {
01556     //    ConfidenceRegionGroup &group = g->second;
01557     list<QRegion> &QRegions = g->second.QRegions;       
01558     //    cout << "Size of Regions: " << g->second.Regions.size() << "  QRegions: " << g->second.QRegions.size()  << endl;
01559     //    cout << endl;
01560     for (list<QRegion>::iterator i = QRegions.begin(); i != QRegions.end(); i++) {
01561       if (i->contains(pos)) {
01562         LastDetectedGroupCollision = CoordPoint(reverse_x(pos.x()),reverse_y(pos.y()));
01563         return g->first;
01564       }
01565     }
01566   }
01567   return -1;
01568 }
01569 
01573 int  PlotWidget::detectCollision(const QPoint &pos, int accept) {
01574   // we misuse the drawPath as a list<QPoint> that tell us the position of the curves
01575   //cout << "detectcollission" << endl;
01576   double least = 10000;
01577   int id = 0;
01578   for (map<int,Spline*>::iterator i=splines.begin(); i != splines.end();i++) {
01579     clearDrawPath();
01580 
01581     int left = max(xoffset, pos.x() - accept);
01582     int right = min(Width(), pos.x() + accept);
01583     left = min(Width(), left);
01584     right = max(xoffset, right);
01585 
01586     // cout << "left: " << left << "  " << right << endl;
01587     
01588     for (int pixel =left; pixel  <=  right; pixel ++) {
01589       double x = reverse_x(pixel);
01590       //cout << " reverse x of " << pixel << "  =  " << x << endl;
01591       if ( x <=  i->second->stop()  && x >= i->second->start() )  drawDataPoint( x,  i->second->fastY(x), true );     
01592     }
01593     double min_d = 1000;
01594     for (list<QPoint>::iterator j = DrawPath.begin(); j != DrawPath.end(); j++) {
01595       double dx = j->x() - pos.x();
01596       double dy = j->y() - pos.y();
01597       double d = sqrt( dx*dx + dy*dy); 
01598       if (d  < min_d) min_d = d;
01599     }
01600     if (min_d < least) { 
01601       least = min_d; 
01602       if (least <= accept) id = i->first; 
01603     }
01604   }
01605   //cout << "best match: " << id << "  with " << least << endl;
01606   return id;
01607 }
01608 
01609 double PlotWidget::reverse_x(int x) {
01610   double frac = ((double)(x - xoffset)) / ((double)(Width() - xoffset)); // frac is between 0 ... 1
01611   
01612   if (logX()) return  exp ( log(Co.x) + frac*(log(Co.X) - log(Co.x)) );
01613   return Co.x + frac*(Co.X - Co.x);
01614 }
01615 
01616 double PlotWidget::reverse_y(int y) {
01617   if (y > Height() - yoffset) return Co.y;
01618   double frac = ((double)y) / ((double)(Height() - yoffset)); // frac is between 0 ... 1
01619   frac = 1.0 - frac;
01620 
01621   if (logY()) return  exp ( log(Co.y) + frac*(log(Co.Y) - log(Co.y)) );
01622   return Co.y + frac*(Co.Y - Co.y);
01623 }
01624 
01625 void PlotWidget::printStatus() {
01626   cout << "PLOTWIDGET:: PRINTSTATUS: " << this << endl;
01627   cout << "splines.size() " << splines.size() << endl;
01628   for (map<int,Spline*>::iterator i = splines.begin(); i != splines.end(); i++)
01629     cout << "content[]: " << i->first << "    points to: "  << i->second << endl;
01630   cout << "::::: ENDSTATUS" << endl;
01631 
01632 
01633 
01634 
01635 }
01636 
01637 void PlotWidget::printGnuplot() {
01638   static QPrinter *prt = new QPrinter();
01639   cout << "PRINTER AT: " << prt << endl;
01640   QPrintDialog dlg(prt);
01641   if (dlg.exec()) {
01642     bool aa = AntiAlias;
01643     AntiAlias = false;
01644     // first, we save all splines in /tmp/cmbeasyprt
01645 
01646     ofstream o("/tmp/cmbeasyprt");
01647     saveToFile(o);
01648     o.close();
01649     
01650     // next, we generate the gnuplot file
01651 
01652     o.open("/tmp/cmbeasy_gnuplot");
01653     cout << "plot:print:1" << endl;
01654 
01655     QString output = "/tmp/o.ps";
01656     QProcess *proc = new QProcess();
01657     if (!prt->outputFileName().isEmpty()) {
01658       output = prt->outputFileName();
01659       // DO SOMETHING ABOUT IT
01660     }  else {
01661       PrinterName = prt->printerName();
01662       connect(proc,SIGNAL(finished(int)),this,SLOT(launchLPR()));
01663     }
01664      cout << "plot:print:2" << endl;
01665 
01666 
01667      o << "set terminal postscript" << endl;
01668      o << "set output \"" << output.toStdString() << "\""<<endl;
01669      if (LogX || LogY) {
01670        o << "set logscale ";
01671        if (LogX) o << "x";
01672        if (LogY) o << "y";
01673        o << endl;
01674      }
01675      o << "plot [" << Co.x << ":" << Co.X << "] ";
01676      int count =0;
01677      for (map<int,Spline*>::iterator i=splines.begin(); i != splines.end(); i++) {
01678        if (count) o << ", ";
01679        o << "\"/tmp/cmbeasyprt\" ";
01680        o << "i " << count++;
01681        o << " w l";
01682      }
01683      if (data) {
01684       for (list<Data*>::iterator i= data->begin(); i != data->end(); i++,count++) {
01685         if (count) o << ", ";
01686         o << "\"" << (*i)->FileName << "\" u 1:(" << (*i)->Normal << "*$2):3:(" << (*i)->Normal << "*$4) ";
01687         o << "title \""<< (*i)->Name << "\"  with xyerrorbars"; 
01688       }
01689     }
01690 
01691     o << endl;
01692     cout << "plot:print:3" << endl;
01693 
01694     proc->start("gnuplot", QStringList()<<"/tmp/cmbeasy_gnuplot");
01695      cout << "plot:print:4" << endl;
01696      AntiAlias=aa;
01697 
01698   } 
01699 }
01700 
01701 void PlotWidget::saveToFile(int i, ostream& o) {
01702   if (splines.find(i) == splines.end()) return;
01703   Spline &s = *splines[i];
01704   for (int k = 0; k < s.size()-1; k++) {
01705     for (double  X = s.x(k); X <= s.x(k+1); X += 0.05*(s.x(k+1) - s.x(k)) )
01706       o << X << "\t" << s(X) << endl;
01707   }
01708 }
01709 
01710 void PlotWidget::saveToFile(ostream& o) {
01711   for (map<int,Spline*>::iterator i=splines.begin(); i != splines.end(); i++) {
01712     saveToFile(i->first,o);
01713     o << endl << endl;
01714   }
01715 }
01716 
01717 void PlotWidget::launchLPR() {
01718   //cout << "LAUNCHLPR: " << PrinterName << endl;
01719   QProcess *proc = new QProcess();
01720   QStringList args;
01721   args << "-P";
01722   args << PrinterName;
01723   args << "/tmp/o.ps";
01724   proc->start("lpr", args);
01725 }
01726 
01727 /*
01728 void PlotWidget::drawWeb() { 
01729   if (!BadDraw) {
01730     vector< vector<double> >* v;
01731     v = drawWebLayer(0.95,QColor(200,200,200), true);
01732     drawWebLayer(0.67,QColor(150,150,150));  
01733     drawWebLayer(0.1,QColor(100,100,100));  
01734     delete v; // trust me, this makes sense: the vector created and stored in drawWebLayer is now deleted
01735     pair<double,double> max = Web->maximum();
01736     cout << "THE MAXIMUM OF THE WEB IS AT: " << max.first << "  :  " << max.second << endl;
01737   }
01738 }
01739 */
01740 
01741 
01742 void PlotWidget::drawBlocks() {
01743   cout << "DRAWBLOCKS" << endl;
01744   int stepregion = 1; // draw each #stepregion stepregion
01745   int elapsed = LastDraw->elapsed();      // ask this once
01746   if (elapsed < 1000) {   // if we redrew recently
01747     if (! EnsureBlockDrawing->isActive()) { // so if the timer is not already busy
01748       EnsureBlockDrawing->setSingleShot(true);
01749       EnsureBlockDrawing->start(1000 - elapsed); // call this
01750     }
01751     stepregion = 10; // less regions
01752   } 
01753   
01754   list<Block> &b = *Blocks;
01755   //  cout << "PlotWidget::drawBLOCKS()"<< endl;
01756   //  cout << "Coord: " << Co.x << " " << Co.X << "  :: " << Co.y << "  " << Co.Y << endl;
01757   for (list<Block>:: reverse_iterator i = b.rbegin(); i!=b.rend(); i++) {
01758     int linewidth = (int)ceil( (Width()-xoffset)*(  i->Width / (Co.X - Co.x) ));
01759     //for (int i = r.regions-1; i >= 0; i-=stepregion) {
01760     //    cout << "i: " << i << endl;
01761 
01762     QColor c(ToColor(i->PenColor)); 
01763     if (i->UsePen) drawBlockArea(i->lines,c,linewidth,true);
01764     c = ToColor(i->FillColor); 
01765     drawBlockArea(i->lines,c,linewidth,false);
01766     
01767     //    drawBlockArea(i->lines,ToColor(i->FillColor),linewidth,false);
01768     //    cout << "done draw block area" << endl;
01769   }
01770   //  paint->fillRect(20,20,100,100,QBrush(QColor(100,100,100)));
01771   if (stepregion == 1) LastDraw->start();
01772 }
01773 
01774 
01775 void PlotWidget::drawBlockArea(map<float, list<CoordPoint> >& lines, QColor& color,int linewidth, bool bound) {
01776   QBrush brush(color);
01777  
01778   for (map<float, list<CoordPoint > >::iterator i = lines.begin(); i != lines.end(); i++) {
01779     float x;
01780     for (list<CoordPoint>::iterator j = i->second.begin(); j != i->second.end(); j++) {
01781       x = i->first;
01782       float y1 = j->x;
01783       float y2 = j->y;
01784       
01785       y1 = (y1 - Co.y)/(Co.Y - Co.y);
01786       y2 = (y2 - Co.y)/(Co.Y - Co.y);
01787       x =  (x - Co.x)/(Co.X - Co.x);
01788 
01789       if (bound) {
01790         fillRect(tx(x)-1,ty(y2)-1,linewidth+2,sy(y2-y1)+2,brush);
01791       } else {
01792         fillRect(tx(x),ty(y2),linewidth,sy(y2-y1),brush);
01793       }
01794     }
01795   }
01796 }
01797 
01798 void PlotWidget::fillRect(int x,int y,int w,int h, QBrush& brush) {
01799   
01800   if (x < xoffset) { x=xoffset; w -= xoffset; }
01801   if (y < 0) { h += y; y=0; }
01802 
01803   w = min(Width() - x, w);
01804   h = min(Height() - yoffset - y, h);
01805 
01806   //  h = min(Height()-yoffset - y,h);
01807   //  if (y+h > Height()-yoffset) h = Height()-y-yoffset;
01808 
01809   if (x > Width() || y > Height()-yoffset) return;
01810   if (w <0 || h <0) return;
01811 
01812   //  if (x < 0 || y < 0 || w < 0 || h < 0) cout << "AAAH: " << x << "  " << y << "  " << w << "   " << h << endl;
01813 
01814 
01815   paint->fillRect(x,y,w,h,brush);
01816 }
01817 
01818 void PlotWidget::drawRegions() {
01819   checkPainter();
01820   paint->setClipRect(xoffset,0,Width(),Height()-yoffset);
01821   // For all RegionsGroups
01822   for (map<int,ConfidenceRegionGroup>::iterator g = RegionGroups.begin(); g != RegionGroups.end(); g++) {
01823     CoordRect Clip(g->second.Clip);
01824     CoordPoint ClipLeftUpper(Clip.x,Clip.y);
01825     CoordPoint ClipRightLower(Clip.X,Clip.Y);
01826 
01827     CoordPoint LeftUpper = translateCoordPoint(ClipLeftUpper);
01828     CoordPoint RightLower = translateCoordPoint(ClipRightLower);
01829 
01830 
01831     int cx = tx(LeftUpper.x);
01832     int cX = tx(RightLower.x);
01833     int cy = ty(LeftUpper.y);
01834     int cY=ty(RightLower.y);
01835 
01836 //X     cout << "CLIPRECT: " << xoffset << "  :  " << 0 << "  :  " << Width() << " :   "  << Height()-yoffset << endl;
01837 //X     cout << "CLIPRECT: " << cx << "  :  " << cY << "  :  " << cX << " :   "  << cy << endl;
01838 
01839     cx = max(xoffset,cx);
01840     cY = max(0,cY);
01841     cX = min(Width(),cX);
01842     cy = min(Height()-yoffset,cy);
01843     cout << "CLIPRECT: " << cx << "  :  " << cY << "  :  " << cX << " :   "  << cy << endl;
01844     //paint->setClipRect(xoffset,0,Width(),Height()-yoffset);
01845     paint->setClipRect(cx,cY,cX,cy);  
01846 
01847 
01848 
01849     list<ConfidenceRegion> & Regions = g->second.Regions;
01850     g->second.QRegions.clear();
01851     for (list<ConfidenceRegion>::iterator i = Regions.begin(); i != Regions.end();i++) {
01852       list<CoordPoint> &current = i->region;
01853       QPolygon a(current.size());
01854       int count=0;
01855       for (list<CoordPoint>::iterator k = current.begin(); k != current.end(); k++,count++) {
01856         CoordPoint p = translateCoordPoint(*k);
01857         a[count] = QPoint(tx(p.x),ty(p.y));
01858         //cout << "( " << k->first << " , " <<  k->second << " )  --> ( " << p.first << ", " << p.second << ")  == ( " << tx(p.first) << ", " << tx(p.second) << ") " << endl;
01859       }
01860       Color c = i->FillColor;     
01861       Color p = i->PenColor;
01862       //      if (g->second.Highlighted) c=highlightColor(c,1.5);
01863       //if (g->second.Highlighted) p=highlightColor(p,1.5);
01864       paint->setPen(ToColor(p));
01865       QBrush brush(ToColor(c)); 
01866       if (i->Fill) {
01867         if (g->second.Highlighted) {
01868           paint->setBrush(QColor(255,255,255));
01869           paint->drawPolygon(a); 
01870           brush.setStyle(Qt::Dense3Pattern);
01871           paint->setBrush(brush);
01872         }
01873         paint->setBrush(brush);
01874         paint->drawPolygon(a); 
01875         if (g->second.Sticky) {
01876           CoordPoint pinpos = translateCoordPoint(g->second.PinPos);
01877           int x = tx(pinpos.x);
01878           int y = ty(pinpos.y);
01879           paint->drawPixmap(x,y,Pin);
01880         }
01881       } else paint->drawPolyline(a);
01882 
01883       // draw optional colorpoints
01884       ColorPoints& cp = g->second.cp;
01885       if (!cp.v.empty()) {
01886         //      ofstream prove("prove.dat");
01887         int size = cp.v.size();
01888         for (int i  = 0; i < size; i++) {
01889           float x = cp.v[i][0];
01890           float y = cp.v[i][1];  
01891           float z = cp.v[i][2];
01892           Color c;
01893           if (z > 0.5) PostscriptPlot::InterpolateColor(c,cp.MaxColor,cp.MiddleColor,z,0.5,1);
01894           else PostscriptPlot::InterpolateColor(c,cp.MiddleColor,cp.MinColor,z,0,0.5);
01895           QBrush brush(ToColor(c)); 
01896           paint->setPen(ToColor(c));      
01897           paint->setBrush(brush);
01898           pair<double,double> tr = translate(x,y);
01899           
01900           float X = tr.first,  Y = tr.second;
01901           float R = cp.Radius;
01902           paint->drawEllipse(tx(X-R),ty(Y-R),sx(2*R),sy(2*R));
01903           
01904           //        paint->drawPoint(tx(tr.first),ty(tr.second));         
01905           //      prove << x << " " << y << endl;
01906         } 
01907         // Draw A colored scale for the color points
01908         float dz = 0.01;
01909         int w = sx(0.04);
01910         w = max(w,15);
01911         int p = tx(0.95);
01912         p = min(p,Width()-20);
01913         
01914         w = 15;
01915         p = Width()-20;         
01916         for (float z =  0; z < 1; z +=dz) {
01917           float y = 0.05 + z*0.3;
01918           Color c;
01919           if (z > 0.5) PostscriptPlot::InterpolateColor(c,cp.MaxColor,cp.MiddleColor,z,0.5,1);
01920           else PostscriptPlot::InterpolateColor(c,cp.MiddleColor,cp.MinColor,z,0,0.5);
01921           QBrush brush(ToColor(c)); 
01922           paint->setPen(ToColor(c));      
01923           //      paint->setBrush(brush);
01924           int h = sy(0.35*dz);
01925           h = max(2,h);
01926           paint->fillRect(p,ty(y),w,h, brush);
01927         }
01928         paint->setPen(Qt::black);
01929         paint->setBrush(Qt::NoBrush);
01930         paint->drawRect(p,ty(0.05+0.3), w,sy(0.3));
01931         // end of drawing a colored scale for the color points
01932       } 
01933       //      cout << "Pushing back QRegion: " << &current << endl;
01934       g->second.QRegions.push_back(a);
01935       // store as QRegion for later detection
01936       }
01937     }
01938 
01939   if ( DrawBestFitModel ) {
01940     float x = BestFitModel.first;
01941     float y = BestFitModel.second;
01942     QBrush brush(Qt::red); 
01943     paint->setPen(Qt::red);       
01944     paint->setBrush(brush);
01945 
01946     pair<double,double> tr = translate(x,y);
01947 
01948     float X = tr.first,  Y = tr.second;
01949 
01950     QPainterPath starPath;
01951     float R = 12e-3;
01952     starPath.moveTo( tx( X+R ), ty( Y ) );
01953     for ( int i = 1; i < 5; ++i ) {
01954       starPath.lineTo(  tx( X ) + sx( R ) * cos( 0.8 *i * M_PI ) ,
01955                         ty( Y ) + sy( R ) * sin( .8 *i * M_PI ) );
01956     }
01957     starPath.closeSubpath();
01958     paint->drawPath( starPath );
01959   }
01960 
01961   if ( DrawModelToMark ) {
01962     float x = ModelToMark.first;
01963     float y = ModelToMark.second;
01964     QBrush brush(Qt::blue); 
01965     paint->setPen(Qt::blue);      
01966     paint->setBrush(brush);
01967 
01968     pair<double,double> tr = translate(x,y);
01969     float X = tr.first,  Y = tr.second;
01970     float R = 12e-3;
01971     paint->drawEllipse(tx(X-R),ty(Y-R),sx(2*R),sy(2*R));
01972   }
01973 
01974   delete paint; paint=0;
01975   checkPainter();
01976 }
01977 
01978 int PlotWidget::Height() {
01979   if (IsPrinting) {
01980     return PrintingHeight;
01981   } else return height(); 
01982 }
01983 
01984 int PlotWidget::Width() {
01985   if (IsPrinting) {
01986     return PrintingWidth;
01987   } else return width(); 
01988 }
01989 
02034 void PlotWidget::setBlocks(list<Block>* b) {
02035   if (Blocks) delete Blocks;
02036   Blocks =b;
02037 }
02038 
02039 /*
02040 void PlotWidget::setRegions(list<ConfidenceRegion>* r) {
02041   if (Regions) delete Regions;
02042   Regions =r;
02043 }
02044 */
02045 
02046 void PlotWidget::addRegionGroup(list<ConfidenceRegion>* r) {
02047   map<int,ConfidenceRegionGroup> replace;              
02048   int k =0;
02049   for (unsigned int i =0; i < RegionGroups.size(); i++) {
02050     if (RegionGroups[i].Sticky) replace[k++] = RegionGroups[i];
02051   }
02052   RegionGroups = replace;
02053   int size = RegionGroups.size();
02054   RegionGroups[size] = ConfidenceRegionGroup(*r);
02055   RegionGroups[size].Clip = Co;
02056 }
02057 void  PlotWidget::attachColorPoints(ColorPoints& cp) {
02058   int size = RegionGroups.size();
02059   RegionGroups[size-1].cp = cp;
02060 } 
02061 
02062 
02063 void PlotWidget::setRegionGroupSticky(int id) {
02064   RegionGroups[id].Sticky = true;
02065   RegionGroups[id].PinPos = LastDetectedGroupCollision;
02066   drawRegions();
02067   repaint();
02068 }
02069 
02070 
02071 
02072 void PlotWidget::setRectangles(list<Rectangle>* r) {
02073   if (Rectangles) delete Rectangles;
02074   Rectangles =r;
02075 }
02076 
02077 Color PlotWidget::highlightColor(Color &c,float factor) {
02078   c.r += 0.5; c.b += 0.5; c.g += 0.5;
02079   if (c.r > 1.0) c.r =1.0;
02080   if (c.g > 1.0) c.g =1.0;
02081   if (c.b > 1.0) c.b =1.0;
02082   return c;
02083 }
02084 
02085 
02086 int PlotWidget::idCount(int id) {
02087   int count =-1;
02088   for (map<int,bool>::iterator i = validIds->begin(); i != validIds->end(); i++) {
02089     count++;
02090     if (i->first == id) return count;
02091   }
02092   return 0;
02093 }
02094 
02095 void PlotWidget::revertZoom() {
02096   if (Zoom.empty()) return;
02097   Co = Zoom.top();
02098   Zoom.pop();
02099 }
02100 
02101 
02102 void PlotWidget::displayCoords(double x, double y) {
02103   QString t = "["+toStr(x,4) + " : " +toStr(y,4)+" ]";
02104   paint->drawText(width()-fontMetrics().width(t),10,t);
02105 }
02106 

Generated on Mon May 5 17:48:33 2008 for cmbeasy by  doxygen 1.4.6