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
00064
00065 checkPainter();
00066
00067 paint->setPen( Qt::black);
00068
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
00110 return;
00111
00112 QPrinter *prt = new QPrinter();
00113 QSettings s;
00114
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
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());
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
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
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
00187
00188
00189 if (! RegionGroups.empty()) {
00190 for (map<int,ConfidenceRegionGroup>::iterator g = RegionGroups.begin(); g != RegionGroups.end(); g++) {
00191
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]);
00197 cp.v[i][0] = tr.first;
00198 cp.v[i][1] = tr.second;
00199 }
00200 things.CPs.push_back(cp);
00201
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
00216 list<ConfidenceRegion> &Regions = g->second.Regions;
00217 for (list<ConfidenceRegion>::iterator i = Regions.begin(); i != Regions.end(); i++) {
00218 ConfidenceRegion r =*i;
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
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
00242
00243
00244 if (Blocks) {
00245 for (list<Block>::reverse_iterator i = Blocks->rbegin(); i != Blocks->rend(); i++) {
00246 Block b = *i;
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
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
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
00309 }
00310 x += (Co.X - Co.x)*2e-5;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 curve.color = FromColor(*colors[idCount(i->first)]);
00322 things.Curves.push_back(curve);
00323 }
00324
00325
00326
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
00336
00337
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
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;
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
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 }
00402 }
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
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
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
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);
00461 }
00462
00463
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
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
00502 drawSplines(rect);
00503
00504 }
00505 paint->setClipRect(0,0,Width(),Height());
00506 drawAxis();
00507 }
00508
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
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
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
00592 }
00593
00594
00595 void PlotWidget::autoTick(LowLevelPlot& plot) {
00596
00597
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
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
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
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
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
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
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
00694
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
00703 double x = (rint(min / unit)-1)*unit;
00704 tick.clear();
00705 do {
00706 if (fabs(x/unit) < 1e-5) x = 0;
00707
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
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
00738
00739 while (pack < 5 && pack*2 <12) { unit*=0.5; pack*=2;}
00740
00741 int k = (int) rint(min / unit);
00742
00743
00744
00745
00746
00747
00748
00749
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
00765
00766 int count =0;
00767 for (list<Data*>::iterator i= data->begin(); i != data->end(); i++,count++) drawDataSet(*i,count);
00768
00769
00770 }
00771 }
00772
00773 void PlotWidget::drawDataSet(Data* d, int count ) {
00774
00775 paint->setPen(*dataColors[count]);
00776
00777 for (list<DataEntry>::iterator i = d->points.begin(); i != d->points.end(); i++) drawSingleDataEntry(*i);
00778
00779 }
00780
00781 void PlotWidget::drawSingleDataEntry(const DataEntry &point) {
00782
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;
00802 if (e == -1) return tmp.left(k+1+post);
00803
00804
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));
00829 if (validIds->find(id) != validIds->end()) validIds->erase(validIds->find(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
00846
00847
00848
00849
00850 checkPainter();
00851 paint->setPen(c);
00852 paint->setClipRect(xoffset,0,Width(),Height()-yoffset);
00853
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;
00866 bool drawn=false;
00867
00868 double y;
00869 for (int pixel=left; pixel <= right; pixel++) {
00870 double x = reverse_x(pixel);
00871
00872 if ( x <= s.stop() && x >= s.start()) {
00873 y = s(x);
00874
00875 if (y <= ymax && y>=ymin) {
00876 if (stored) {
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) {
00885 drawn = false;
00886 drawDataPoint(x,s(x),true);
00887 }
00888 }
00889 }
00890 }
00891 drawPath();
00892
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
00956
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
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
01032
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
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)) {
01086 int count_y = 0;
01087
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
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
01152
01153 for ( int i = 0; i < a.size(); i++ ) {
01154
01155 if ( ( i&1 ) == 1 ) {
01156
01157 b.setPoint( j++,a.point( i ).x(),a.point( i ).y() );
01158 }
01159
01160 }
01161 b.resize(j);
01162 paint->drawPolyline(b);
01163 } else paint->drawPoints(a);
01164
01165
01166
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
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) {
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) {
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
01230
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) {
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
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
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
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;
01292 QColor a= QColorDialog::getColor();
01293 if ( !a.isValid() ) return;
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;
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
01310
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
01322 i->FillColor = Color(v_r,v_g,v_b);
01323
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
01377
01378 double d2 = pow((double)MidMouseX-e->x(),2) + pow((double)MidMouseY-e->y(),2);
01379
01380
01381
01382 if (d2 > 200) {
01383 Zoom.push(Co);
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
01419
01420
01421 if (MidMouseDown) {
01422 if (!MidMouseMove) {
01423 delete paint;paint=0;
01424 repaint();
01425 }
01426
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
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464 }
01465 checkPainter();
01466 paint->setPen(Qt::black);
01467
01468 OldMidMouse = NewMidMouse;
01469 paint->drawRect(OldMidMouse);
01470
01471 }
01472
01473
01474 void PlotWidget::paintOnLeftMouseMove()
01475 {
01476
01477 checkPainter();
01478
01479
01480
01481
01482
01483 displayCoords(reverse_x(NewLeftMouseX),reverse_y(NewLeftMouseY));
01484 delete paint;paint=0;
01485
01486
01487
01488
01489
01490
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
01519
01520 id = detectRegionGroup(mouseMovedPos);
01521
01522 if (id != -1) {
01523 if (! RegionGroups[id].Highlighted) {
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
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
01557 list<QRegion> &QRegions = g->second.QRegions;
01558
01559
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
01575
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
01587
01588 for (int pixel =left; pixel <= right; pixel ++) {
01589 double x = reverse_x(pixel);
01590
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
01606 return id;
01607 }
01608
01609 double PlotWidget::reverse_x(int x) {
01610 double frac = ((double)(x - xoffset)) / ((double)(Width() - xoffset));
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));
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
01645
01646 ofstream o("/tmp/cmbeasyprt");
01647 saveToFile(o);
01648 o.close();
01649
01650
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
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
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
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 void PlotWidget::drawBlocks() {
01743 cout << "DRAWBLOCKS" << endl;
01744 int stepregion = 1;
01745 int elapsed = LastDraw->elapsed();
01746 if (elapsed < 1000) {
01747 if (! EnsureBlockDrawing->isActive()) {
01748 EnsureBlockDrawing->setSingleShot(true);
01749 EnsureBlockDrawing->start(1000 - elapsed);
01750 }
01751 stepregion = 10;
01752 }
01753
01754 list<Block> &b = *Blocks;
01755
01756
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
01760
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
01768
01769 }
01770
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
01807
01808
01809 if (x > Width() || y > Height()-yoffset) return;
01810 if (w <0 || h <0) return;
01811
01812
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
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
01837
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
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> ¤t = 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
01859 }
01860 Color c = i->FillColor;
01861 Color p = i->PenColor;
01862
01863
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
01884 ColorPoints& cp = g->second.cp;
01885 if (!cp.v.empty()) {
01886
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
01905
01906 }
01907
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
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
01932 }
01933
01934 g->second.QRegions.push_back(a);
01935
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
02041
02042
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