00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "Marx2DGraph.h"
00021
00022 using namespace std;
00023 using namespace Marsyas;
00024
00025 namespace MarsyasQt
00026 {
00028
00031 Marx2DGraph::Marx2DGraph( QWidget *parent )
00032 : QWidget(parent)
00033 {
00034 Marx2DGraph(0, 0);
00035 }
00036
00037
00039
00046 Marx2DGraph::Marx2DGraph( int size, QWidget *parent )
00047 : QWidget(parent)
00048 {
00049
00050 xpos = 0;
00051 ypos = 0;
00052 xaxisoffset = 80;
00053 yaxisoffset = 30;
00054 width = QWidget::width() - 2*xpos;
00055 height = QWidget::height() - 2*ypos;
00056 gheight = height - yaxisoffset*2;
00057 gwidth = width - xaxisoffset*2;
00058
00059 yaxisscale = 20.0;
00060 showXaxis = true;
00061
00062 buffersize = size;
00063 buffer = new realvec(buffersize);
00064
00065 plot_type = POINTS;
00066 point_size = 5;
00067 point_type = XS;
00068 pen_width = 2.;
00069 data_pen_width = 2.;
00070
00071 antialias = false;
00072
00073 ticks = true;
00074 axis_display_type = CONNECTED;
00075 show_axis_scale = false;
00076
00077 data_color = QColor(255, 0, 0);
00078 label_color = QColor(0, 0, 0);
00079 bg_color = QColor(255, 255, 255);
00080
00081 QPen pen;
00082
00083 pen.setColor( QColor(0, 0, 0) );
00084 pen.setWidthF( pen_width );
00085
00086 label = "";
00087 xlabelmessage = "";
00088 xlabel = false;
00089 ylabelmessage = "";
00090 ylabel = false;
00091
00092 display = false;
00093 dsamplestring = "";
00094 dvaluestring = "";
00095
00096 setPalette( QPalette( QColor(0, 0, 0) ) );
00097 }
00098
00099
00101
00106 void
00107 Marx2DGraph::displayXaxis( bool tf )
00108 {
00109 showXaxis = tf;
00110 update();
00111 }
00112
00113
00115
00120 void
00121 Marx2DGraph::setXAxisLabel( string m )
00122 {
00123 xlabelmessage = m;
00124 update();
00125 }
00126
00127
00129
00134 void
00135 Marx2DGraph::setYAxisLabel( string m )
00136 {
00137 ylabelmessage = m;
00138 update();
00139 }
00140
00141
00143
00148 void
00149 Marx2DGraph::setXAxisLabelOn( bool tf )
00150 {
00151 if (tf && !xlabel) { yaxisoffset += 16; }
00152 else if (!tf && xlabel) { yaxisoffset -= 16; }
00153
00154 xlabel = tf;
00155 update();
00156 }
00157
00158
00160
00165 void
00166 Marx2DGraph::setYAxisLabelOn( bool tf )
00167 {
00168 if (tf && !ylabel) { xaxisoffset += 24; }
00169 else if (!tf && ylabel) { xaxisoffset -= 24; }
00170
00171 ylabel = tf;
00172 update();
00173 }
00174
00175
00176
00178
00183 void
00184 Marx2DGraph::setAxisDisplayType( int type )
00185 {
00186 axis_display_type = type;
00187 }
00188
00189
00191
00196 void
00197 Marx2DGraph::setGraphDataColor( QColor c )
00198 {
00199 data_color = c;
00200 update();
00201 }
00202
00203
00205
00211 void
00212 Marx2DGraph::setGraphLabelsAndAxisColor( QColor c )
00213 {
00214 label_color = c;
00215 update();
00216 }
00217
00218
00220
00225 void
00226 Marx2DGraph::setBGColor( QColor c )
00227 {
00228 bg_color = c;
00229 update();
00230 }
00231
00232
00234
00239 void
00240 Marx2DGraph::setGraphDataPointSize(float p)
00241 {
00242 point_size = p;
00243 update();
00244 }
00245
00246
00248
00254 void
00255 Marx2DGraph::setGraphDataPointType( int t )
00256 {
00257 point_type = t;
00258 update();
00259 }
00260
00261
00263
00269 void
00270 Marx2DGraph::setGraphDataLineSize( float p )
00271 {
00272 data_pen_width = p;
00273 update();
00274 }
00275
00276
00278
00284 void
00285 Marx2DGraph::setPlotType(int type)
00286 {
00287 plot_type = type;
00288 update();
00289 }
00290
00291
00293
00298 void
00299 Marx2DGraph::setAntialias(bool tf)
00300 {
00301 antialias = tf;
00302 update();
00303 }
00304
00305
00307
00312 void
00313 Marx2DGraph::setShowAxisScale( bool tf )
00314 {
00315 show_axis_scale = tf;
00316 update();
00317 }
00318
00319
00321
00329 bool
00330 Marx2DGraph::setBuffer( realvec& rv )
00331 {
00332
00333 if ( rv.getSize() == buffersize ) {
00334 *buffer = rv;
00335
00336 int xu = (int)(xaxisoffset+xpos) + pen.width() + 1;
00337 int yu = (int)(yaxisoffset+ypos);
00338 int xl = (int)(xaxisoffset+xpos+gwidth);
00339 int yl = (int)(yaxisoffset+ypos+gheight) - pen.width() - 1;
00340
00341
00342 update();
00343
00344 return true;
00345 }
00346 return false;
00347 }
00348
00349 void
00350 Marx2DGraph::setYMaxMin(float ymax, float ymin)
00351 {
00352 ymaxval = ymax;
00353 yminval = ymin;
00354 }
00355
00356
00357
00358 void
00359 Marx2DGraph::draw_y_ticks(QPainter *painter)
00360 {
00361 float interval = gheight/10;
00362
00363 int stop = 10;
00364 int start = 0;
00365 if (!showXaxis){ stop = 11; }
00366 if (axis_display_type == BROKEN){
00367 stop = 10;
00368 start = 1;
00369 }
00370
00371 for (int i=start; i<stop; i++) {
00372 painter->drawLine( QLineF( xaxisoffset+xpos, yaxisoffset+ypos+i*interval,
00373 xaxisoffset+xpos-5, yaxisoffset+ypos+i*interval) );
00374
00375
00376 if (show_axis_scale) {
00377 ostringstream ds;
00378 float tinterval;
00379 tinterval = (ymaxval-yminval)/10.0;
00380
00381
00382
00383 ds << setprecision(3) << ymaxval - i * tinterval;
00384
00385
00386
00387
00388 painter->drawText( QPointF(xaxisoffset+xpos-80, yaxisoffset+ypos+i*interval),
00389 QString( QString::fromStdString(ds.str()) )
00390 );
00391 }
00392
00393 }
00394
00395 }
00396
00397
00398
00399 void Marx2DGraph::draw_x_ticks(QPainter *painter)
00400 {
00401 float interval = gwidth/10;
00402
00403 int stop=11;
00404 if (axis_display_type == BROKEN){ stop = 10; }
00405 for (int i=1; i<stop; i++) {
00406 painter->drawLine( QLineF( xaxisoffset+xpos+i*interval, yaxisoffset+ypos+gheight,
00407 xaxisoffset+xpos+i*interval, yaxisoffset+ypos+gheight+5)
00408 );
00409
00410
00411 if (show_axis_scale) {
00412 ostringstream ds;
00413 ds << fixed << setprecision(0) << ((float)buffersize/10.0)*(float)i;
00414
00415 painter->drawText( QPointF(xaxisoffset+xpos+i*interval-10, yaxisoffset+ypos+gheight+17),
00416 QString( QString::fromStdString(ds.str()) )
00417 );
00418 }
00419 }
00420 }
00421
00422
00423
00425
00430 void
00431 Marx2DGraph::addLabel( string lb )
00432 {
00433 label = lb;
00434 update();
00435 }
00436
00437
00438 void
00439 Marx2DGraph::paintEvent( QPaintEvent * )
00440 {
00441 QPainter painter(this);
00442
00443 pen.setColor( bg_color);
00444 painter.setPen( pen );
00445 painter.setBrush( QBrush( bg_color, Qt::SolidPattern ) );
00446
00447 if (antialias) {
00448 painter.setRenderHint( QPainter::Antialiasing );
00449 }
00450
00451
00452
00453 painter.drawRect( QRectF( xpos, ypos, width, height ) );
00454 pen.setColor( QColor(0, 0, 0));
00455 painter.setPen( pen );
00456
00457
00458 float ext = 0.0;
00459 if (axis_display_type == BROKEN){ ext = gheight/10; }
00460 painter.drawLine( QLineF( xaxisoffset+xpos, yaxisoffset+ypos+ext,
00461 xaxisoffset+xpos, yaxisoffset+ypos+gheight-ext ) );
00462 if (ticks)
00463 draw_y_ticks( &painter );
00464
00465 if (ylabel) {
00466 painter.rotate(270);
00467 painter.drawText( QPointF(-1*(height/2)-32,
00468 xpos+xaxisoffset-32 ),
00469 QString(QString::fromStdString(ylabelmessage))
00470 );
00471 painter.rotate(90);
00472 }
00473
00474
00475 if (showXaxis) {
00476 ext = 0.0;
00477 if (axis_display_type == BROKEN){ ext = gwidth/10; }
00478 painter.drawLine( QLineF( xaxisoffset+xpos+ext, yaxisoffset+ypos+gheight,
00479 xaxisoffset+xpos+gwidth-ext, yaxisoffset+ypos+gheight ) );
00480 if (ticks)
00481 draw_x_ticks( &painter );
00482
00483 if (xlabel) {
00484 painter.drawText( QPointF((width/2)-32,
00485 yaxisoffset+ypos+gheight+30 ),
00486 QString(QString::fromStdString(xlabelmessage))
00487 );
00488 }
00489 }
00490
00491
00492 if (label != "") {
00493
00494
00495
00496
00497
00498
00499 painter.drawText( QPointF(60,30),
00500 QString(QString::fromStdString(label))
00501
00502 );
00503
00504 }
00505
00506
00507
00508
00509
00510 painter.setBrush( QBrush( data_color, Qt::SolidPattern ) );
00511 pen.setColor( data_color );
00512 pen.setWidthF( data_pen_width );
00513 painter.setPen(pen);
00514
00515 switch (plot_type) {
00516 case POINTS:
00517 plotpoints(&painter); break;
00518 case PRECISION:
00519 plotprecision(&painter); break;
00520 case LINEAR_INTERPOLATION:
00521 plotlinearinterpolation(&painter); break;
00522 case POLYNOMIAL_INTERPOLATION:
00523 plotpolyinterpolation(&painter);
00524 break;
00525 default:
00526 plotpoints(&painter); break;
00527 }
00528 pen.setWidthF( pen_width );
00529
00530
00531
00532 if (display) {
00533 mousex += 15;
00534 mousey += 15;
00535
00536 if (mousex + 150 > QWidget::width()) { mousex = mousex - 150; }
00537 if (mousey + 33 > QWidget::height()) { mousey = mousey - 33; }
00538
00539 painter.setBrush( QBrush( QColor(215, 215, 215), Qt::Dense4Pattern ) );
00540 painter.setPen( QPen( Qt::NoPen ) );
00541 painter.drawRect( QRectF( mousex, mousey, 150, 33 ) );
00542
00543 painter.setPen( QPen( QColor(0, 0, 0) ) );
00544 painter.drawText( QPointF( mousex + 5, mousey + 13) ,
00545 QString(QString::fromStdString(dsamplestring)) );
00546 painter.drawText( QPointF( mousex + 5, mousey + 30) ,
00547 QString(QString::fromStdString(dvaluestring)) );
00548
00549 display = false;
00550 }
00551
00552 painter.end();
00553 }
00554
00555
00556 void
00557 Marx2DGraph::plotpolyinterpolation(QPainter* painter)
00558 {
00559
00560
00561
00562 float lastw=-1, lasth;
00563 for (int h=0; h<buffersize-3; h++) {
00564 float *table, *coeff, *x, *pz, *z;
00565 float term;
00566
00567 int steps = 64;
00568
00569 table = new float[4];
00570 x = new float[4];
00571 coeff = new float[4];
00572 pz = new float[steps];
00573 z = new float[steps];
00574
00575 x[0] = h+0; x[1] = h+1; x[2] = h+2; x[3] = h+3;
00576 table[0] = (float)((*buffer)(h));
00577 table[1] = (float)((*buffer)(h+1));
00578 table[2] = (float)((*buffer)(h+2));
00579 table[3] = (float)((*buffer)(h+3));
00580
00581 coeff[0] = table[0];
00582
00583 int j;
00584 int n=4;
00585 for (int k=1; k<n; k++) {
00586 for (int i=0; i<n-k; i++) {
00587 j = i + k;
00588 table[i] = (table[i+1] - table[i])/(x[j] - x[i]);
00589 }
00590 coeff[k] = table[0];
00591 }
00592
00593 int m=steps;
00594 float zn=h;
00595 for (int k=0; k<m; k++) {
00596 pz[k] = coeff[0];
00597
00598 for (j=1; j<n; j++) {
00599 term = coeff[j];
00600
00601 for (int i=0; i<j; i++) {
00602 term = term * (zn - x[i]);
00603 }
00604
00605 pz[k] = pz[k] + term;
00606 }
00607
00608 z[k] = zn;
00609 zn = zn + 4./m;
00610
00611 if ((h != buffersize-4 && k <= m/4) ||
00612 h == buffersize-4) {
00613 float w = (gwidth/(buffersize-1))*z[k] + xpos + xaxisoffset;
00614 float h = (gheight/2.0 + ypos + yaxisoffset) - (gheight/2)*pz[k];
00615 if ( w > gwidth + xpos + xaxisoffset) {
00616 break;
00617 }
00618
00619 if (lastw >=0) { painter->drawLine( QLineF( lastw, lasth, w, h ) ); }
00620
00621 lastw = w;
00622 lasth = h;
00623 }
00624 }
00625 }
00626
00627 }
00628
00629
00630 void
00631 Marx2DGraph::plotlinearinterpolation(QPainter* painter)
00632 {
00633 float lastw=-1, lasth;
00634 for (int i=0; i<buffersize; i++) {
00635 float val = (float)((*buffer)(i));
00636
00637 float w = ((gwidth/(buffersize-1)))*i + xpos + xaxisoffset;
00638 float h = (gheight/2.0 + ypos + yaxisoffset) - (gheight/2)*val;
00639
00640 if (lastw >=0) {
00641 painter->drawLine( QLineF( lastw, lasth, w, h ) );
00642 }
00643
00644 lastw = w;
00645 lasth = h;
00646 }
00647 }
00648
00649
00650 void
00651 Marx2DGraph::plotprecision(QPainter* painter)
00652 {
00653 for (int i=0; i<buffersize; i++) {
00654 float val = (float)((*buffer)(i));
00655
00656 float w = (gwidth/(buffersize-1))*i + xpos + xaxisoffset;
00657 float h = (gheight/2.0 + ypos + yaxisoffset) - (gheight/2)*val;
00658 float b = yaxisoffset+ypos+gheight;
00659 painter->drawLine( QLineF( w, h, w, b ) );
00660 }
00661 }
00662
00663
00664 void
00665 Marx2DGraph::plotpoints(QPainter* painter)
00666 {
00667 float p = point_size/2.;
00668 for (int i=0; i<buffersize; i++) {
00669 float val = (float)((*buffer)(i));
00670
00671
00672
00673 float w = (gwidth/(buffersize-1))*i + xpos + xaxisoffset;
00674 float h = (gheight/2.0 + ypos + yaxisoffset) - (gheight/2.0)*val;
00675
00676 switch (point_type) {
00677 case CIRCLES:
00678 painter->drawEllipse( QRectF( w, h, point_size, point_size ) );
00679 break;
00680 case SQUARES:
00681 painter->drawRect( QRectF( w, h, point_size, point_size ) );
00682 break;
00683 case XS:
00684 painter->drawLine( QLineF(w-p, h-p, w+p, h+p ) );
00685 painter->drawLine( QLineF(w-p, h+p, w+p, h-p ) );
00686 break;
00687 default:
00688 painter->drawEllipse( QRectF( w, h, point_size, point_size ) );
00689 }
00690 }
00691 }
00692
00693
00694 void
00695 Marx2DGraph::resizeEvent(QResizeEvent *)
00696 {
00697
00698 if ( QWidget::width() < width - 2*xpos ||
00699 QWidget::width() > width - 2*xpos - 20 ) {
00700 width = QWidget::width() - 2*xpos;
00701 gwidth = width - xaxisoffset*2;
00702 }
00703
00704 if ( QWidget::height() < height - 2*ypos ||
00705 QWidget::height() > height - 2*ypos - 20 ) {
00706 height = QWidget::height() - 2*ypos;
00707 gheight = height - yaxisoffset*2;
00708 }
00709
00710 }
00711
00712
00713 void
00714 Marx2DGraph::mousePressEvent(QMouseEvent* me)
00715 {
00716 mousex = (float)me->x();
00717 mousey = (float)me->y();
00718
00719 dsample = (mousex - xpos - xaxisoffset)*(buffersize - 1)/gwidth;
00720 display = true;
00721
00722 if (me->button() == Qt::LeftButton) {
00723 dsamplestring = "x = ";
00724 dvaluestring = "y = ";
00725
00726 if (dsample - floor(dsample) > .5) { dsample = ceil(dsample);}
00727 else { dsample = floor(dsample); }
00728 dvalue = (*buffer)((int)dsample);
00729
00730
00731 dvalue *= 0.5;
00732 dvalue += 0.5;
00733 dvalue *= (ymaxval - yminval);
00734 dvalue += yminval;
00735
00736
00737 }
00738 else if (me->button() == Qt::RightButton) {
00739 dsamplestring = "x = ";
00740 dvaluestring = "y = ";
00741
00742 dvalue = (mousey - gheight/2. - ypos - yaxisoffset)*-2/gheight;
00743 }
00744
00745 ostringstream ds, dv;
00746 ds << setprecision(4) << dsample;
00747 dsamplestring.append( ds.str() );
00748 dv << setprecision(4) << dvalue;
00749 dvaluestring.append( dv.str() );
00750
00751 update();
00752 }
00753
00754
00755 void
00756 Marx2DGraph::mouseMoveEvent(QMouseEvent *)
00757 {
00758
00759 }
00760
00761
00762 void
00763 Marx2DGraph::mouseReleaseEvent(QMouseEvent *)
00764 {
00765 update();
00766 }
00767
00768 }