00001
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #else
00015 #ifdef _MSC_VER
00016 #include "msdevstudio/MSconfig.h"
00017 #endif
00018 #endif
00019
00020 #include "CompositePlotter.h"
00021
00022 #include "PlotterException.h"
00023
00024 #include "axes/AxisModelLinear.h"
00025 #include "datareps/DataRep.h"
00026
00027 #include "datasrcs/NTuple.h"
00028 #include "datasrcs/TupleCut.h"
00029
00030 #include "graphics/ViewBase.h"
00031 #include "projectors/ProjectorBase.h"
00032
00033 #include "reps/AxisRepBase.h"
00034 #include "reps/RepBase.h"
00035
00036 #include "transforms/PeriodicBinaryTransform.h"
00037 #include "transforms/TransformFactory.h"
00038 #include "transforms/XYZTransform.h"
00039
00040 #include <algorithm>
00041 #include <functional>
00042
00043 #include <cmath>
00044 #include <cassert>
00045
00046 using namespace hippodraw;
00047
00048 #ifdef ITERATOR_MEMBER_DEFECT
00049 using namespace std;
00050 #else
00051 using std::mem_fun;
00052 using std::string;
00053 using std::vector;
00054 using std::find;
00055 #endif
00056
00057 CompositePlotter::
00058 CompositePlotter ( )
00059 : m_x_axis ( 0 ),
00060 m_y_axis ( 0 ),
00061 m_z_axis ( 0 ),
00062 m_x_label( "%x" ),
00063 m_y_label( "%y" ),
00064 m_z_label( "%z" ),
00065 m_transform ( 0 ),
00066 m_datarep_index ( -1 ),
00067 m_has_autoscaled ( false ),
00068 m_has_z ( false )
00069 {
00070 m_x_axis = new AxisModelLinear ( PLOTBOTTOM, PLOTBOTTOM );
00071 m_y_axis = new AxisModelLinear ( PLOTLEFT, PLOTLEFT );
00072 m_z_axis = 0;
00073
00074 TransformFactory * factory = TransformFactory::instance ();
00075 m_transform = factory->createTransform ( "Linear Linear" );
00076 }
00077
00078 CompositePlotter::CompositePlotter ( const CompositePlotter & plotter )
00079 : m_x_label( plotter.m_x_label ),
00080 m_y_label( plotter.m_y_label ),
00081 m_z_label( plotter.m_z_label ),
00082 m_datarep_index ( plotter.m_datarep_index ),
00083 m_has_autoscaled ( plotter.m_has_autoscaled ),
00084 m_has_z ( plotter.m_has_z )
00085 {
00086 m_x_axis = plotter.m_x_axis ? plotter.m_x_axis->clone () : 0;
00087 m_y_axis = plotter.m_y_axis ? plotter.m_y_axis->clone () : 0;
00088 m_z_axis = plotter.m_z_axis ? plotter.m_z_axis->clone () : 0;
00089
00090 if ( m_has_z ) setEnableZ ( true );
00091
00092 if ( plotter.m_transform != 0 ) {
00093 m_transform = plotter.m_transform->clone ();
00094 }
00095 const vector < DataRep * > & datareps = plotter.m_datareps;
00096 vector< DataRep * >::const_iterator first = datareps.begin ();
00097
00098 for ( ; first != datareps.end (); ++first ) {
00099 DataRep * datarep = (*first)->clone ();
00100 m_datareps.push_back ( datarep );
00101 }
00102
00103 }
00104
00105 CompositePlotter::~CompositePlotter ()
00106 {
00107 delete m_x_axis;
00108 delete m_y_axis;
00109 if ( m_z_axis != 0 ) delete m_z_axis;
00110
00111 if ( m_transform != 0 ) delete m_transform;
00112
00113 vector < DataRep * > :: iterator first = m_datareps.begin();
00114 while ( first != m_datareps.end() ) {
00115 delete *first++;
00116 }
00117 }
00118
00119 CompositePlotter *
00120 CompositePlotter::
00121 clone ()
00122 {
00123 return new CompositePlotter ( *this );
00124 }
00125
00126 DataRep * CompositePlotter::selectedDataRep () const
00127 {
00128 if ( m_datarep_index < 0 ) return 0;
00129
00130 return m_datareps[m_datarep_index];
00131 }
00132
00133
00134 bool CompositePlotter::hasNTupleBindings () const
00135 {
00136 DataRep * rep = selectedDataRep ();
00137 if ( rep == 0 ) return false;
00138
00139 return rep->hasNTupleBindings ();
00140 }
00141
00142 bool CompositePlotter::hasZoomY () const
00143 {
00144 int retVal = 1;
00145
00146 for ( unsigned int i = 0; i < m_datareps.size () ; i++ )
00147 {
00148 retVal = retVal * ( m_datareps[i] -> hasZoomY () );
00149 }
00150 return retVal != 0;
00151
00152 }
00153
00154 int CompositePlotter::setActivePlot ( int index, bool redraw )
00155 {
00156 int retval = -1;
00157
00158 vector< DataRep * >::iterator it = m_datareps.begin();
00159
00160 if ( index < 0 ) {
00161 bool yes = index == -1;
00162 for ( ; it != m_datareps.end(); ++it ) {
00163 (*it)->setSelected ( yes );
00164 }
00165 retval = index;
00166 }
00167 else {
00168 it = m_datareps.begin();
00169 for ( int i = 0; it != m_datareps.end(); ++it, ++i ) {
00170 if ( i == index ) {
00171 (*it)->setSelected ( true );
00172 }
00173 else {
00174 (*it)->setSelected ( false );
00175 }
00176 }
00177 retval = m_datarep_index;
00178 }
00179 checkAxisScaling();
00180 m_datarep_index = index;
00181
00182 return retval;
00183 }
00184
00185 int CompositePlotter::activePlotIndex () const
00186 {
00187 return m_datarep_index;
00188 }
00189
00190 void CompositePlotter::push_back ( DataRep * rep )
00191 {
00192 vector < DataRep * > :: iterator first
00193 = find ( m_datareps.begin (), m_datareps.end(), rep );
00194 if ( first != m_datareps.end () ) return;
00195
00196 m_datareps.push_back ( rep );
00197 }
00198
00199 void CompositePlotter::addDataRep ( DataRep * rep )
00200 {
00201 push_back ( rep );
00202
00203 if ( m_datareps.size() == 1 ) {
00204 setActivePlot ( 0, false );
00205 }
00206 else {
00207 setActivePlot ( -1, false );
00208 }
00209
00210 assert ( m_x_axis );
00211 assert ( m_y_axis );
00212
00213 rep->setAxisModel ( Axes::X, m_x_axis );
00214 rep->setAxisModel ( Axes::Y, m_y_axis );
00215
00216
00217
00218 if ( hasAxis ( Axes::Z ) ) rep->setAxisModel ( Axes::Z, m_z_axis );
00219
00220 checkAxisScaling ();
00221 }
00222
00223 ProjectorBase * CompositePlotter::activeProjector () const
00224 {
00225 DataRep * active_datarep = 0;
00226
00227 if ( m_datarep_index < 0 ) {
00228 active_datarep = m_datareps.front();
00229 }
00230 else {
00231 active_datarep = m_datareps[m_datarep_index];
00232 }
00233
00234 return active_datarep->getProjector ();
00235 }
00236
00237 ProjectorBase * CompositePlotter::getProjector ( int index ) const
00238 {
00239 assert( index < getNumDataReps() );
00240
00241 DataRep * datarep = m_datareps[index];
00242
00243 return datarep->getProjector();
00244 }
00245
00246 int CompositePlotter::getNumDataReps() const
00247 {
00248 int i = static_cast< int >( m_datareps.size() );
00249
00250 return i;
00251 }
00252
00253
00254 DataRep * CompositePlotter::getDataRep ( int index ) const
00255 {
00256 if ( index < 0 ) return 0;
00257 if ( index < getNumDataReps () ) return m_datareps[index];
00258
00259 return 0;
00260 }
00261
00262 DataRep * CompositePlotter::getParentDataRep ( int index ) const
00263 {
00264 DataRep * drep = getDataRep( index );
00265 if( drep != 0 )
00266 return drep -> getParentDataRep();
00267 else
00268 return 0;
00269
00270 return 0;
00271 }
00272
00273 DataRep * CompositePlotter::getParentDataRep () const
00274 {
00275 DataRep * drep = getDataRep( m_datarep_index );
00276 if( drep != 0 )
00277 return drep -> getParentDataRep();
00278 else
00279 return 0;
00280
00281 return 0;
00282 }
00283
00284 void CompositePlotter::setParentDataRep ( int index, DataRep * parent )
00285 {
00286 DataRep * drep = getDataRep( index );
00287
00288 assert( drep );
00289
00290 drep -> setParentDataRep( parent );
00291 }
00292
00293 void CompositePlotter::setParentDataRep ( DataRep * parent )
00294 {
00295 DataRep * drep = getDataRep( m_datarep_index );
00296
00297 assert( drep );
00298
00299 drep -> setParentDataRep( parent );
00300 }
00301
00302
00303 void CompositePlotter::removeDataRep ( DataRep * rep )
00304 {
00305
00306 vector < DataRep * >::iterator it
00307 = find ( m_datareps.begin(), m_datareps.end(), rep );
00308 if ( it == m_datareps.end () ) {
00309 return;
00310 }
00311
00312 m_datareps.erase ( it );
00313
00314 if ( getNumDataReps() == 1 ) m_datarep_index = 0;
00315 if ( m_datarep_index >= getNumDataReps() ) m_datarep_index = 0;
00316
00317 checkAxisScaling ();
00318 }
00319
00320 void CompositePlotter::setAllAxisModels ()
00321 {
00322 vector < DataRep * >::iterator first = m_datareps.begin ();
00323 for ( ; first != m_datareps.end (); ++first ) {
00324 (*first)->setAxisModel ( Axes::X, m_x_axis );
00325 (*first)->setAxisModel ( Axes::Y, m_y_axis );
00326 (*first)->setAxisModel ( Axes::Z, m_z_axis );
00327 }
00328 }
00329
00330 void
00331 CompositePlotter::
00332 autoScale ( AxisModelBase * model, hippodraw::Axes::Type axis )
00333 {
00334 if ( model->isAutoRanging () == false ) return;
00335
00336 BinaryTransform * transform
00337 = dynamic_cast < BinaryTransform * > ( m_transform );
00338
00339 bool all_empty = true;
00340 vector< DataRep * >::iterator it = m_datareps.begin();
00341
00342 while ( it != m_datareps.end () ) {
00343 DataRep * rep = *it++;
00344 if ( rep->hasZeroRows() ) continue;
00345 all_empty = false;
00346 Range range = rep->preferredRange ( axis );
00347 model->setUnionRange ( range );
00348 }
00349 if ( all_empty == true ) return;
00350
00351 if ( axis == Axes::X ) {
00352 const Range & range = transform->limitX ();
00353 transform->adjustValues ( *model, axis, range );
00354 }
00355 else if ( axis == Axes::Y ) {
00356 const Range & range = transform->limitY ();
00357 transform->adjustValues ( *model, axis, range );
00358 }
00359
00360 it = m_datareps.begin();
00361 while ( it != m_datareps.end() ) {
00362 DataRep * rep = *it++;
00363 rep->setRange ( axis, false );
00364 }
00365 }
00366
00367 void
00368 CompositePlotter::
00369 autoScale ( hippodraw::Axes::Type axis )
00370 {
00371 switch ( axis )
00372 {
00373 case Axes::X :
00374 m_x_axis -> setEmpty ();
00375 autoScale ( m_x_axis, axis );
00376 break;
00377 case Axes::Y :
00378 m_y_axis -> setEmpty ();
00379 autoScale ( m_y_axis, axis );
00380 break;
00381 case Axes::Z :
00382 autoScaleZ ();
00383 break;
00384 default :
00385 break;
00386 }
00387 }
00388
00389 void CompositePlotter::autoScale ( )
00390 {
00391 bool z_auto = m_z_axis != 0 ? m_z_axis->isAutoRanging () : false;
00392
00393 m_x_axis -> setEmpty ();
00394 m_y_axis -> setEmpty ();
00395 autoScale ( m_x_axis, Axes::X );
00396 autoScale ( m_y_axis, Axes::Y );
00397
00398
00399 if ( z_auto ) {
00400 autoScaleZ ();
00401 }
00402
00403 setAutoScaled ( true );
00404 }
00405
00406 void
00407 CompositePlotter::
00408 autoScaleZ ()
00409 {
00410 m_z_axis->setEmpty ();
00411
00412 vector< DataRep * >::iterator it = m_datareps.begin();
00413 while ( it != m_datareps.end () ) {
00414 DataRep * rep = *it++;
00415 if ( rep->hasZeroRows() ) continue;
00416
00417 if ( rep -> hasAxis ( Axes::Z ) == true ) {
00418 Range range = rep->preferredRange ( Axes::Z );
00419 m_z_axis->setUnionRange ( range );
00420 }
00421 }
00422
00423 BinaryTransform * transform
00424 = dynamic_cast < BinaryTransform * > ( m_transform );
00425 Range range = transform->limitZ ();
00426 const Range & cur_range = m_z_axis -> getRange ( false );
00427 double pos = cur_range.pos();
00428 range.setPos ( pos );
00429 m_z_axis -> setIntersectRange ( cur_range, range );
00430 it = m_datareps.begin();
00431 while ( it != m_datareps.end() ) {
00432 DataRep * rep = *it++;
00433 if ( rep -> hasAxis ( Axes::Z ) ) {
00434 rep->setRange ( Axes::Z, false );
00435 }
00436 }
00437 }
00438
00439 bool CompositePlotter::isDirty () const
00440 {
00441 bool yes = false;
00442 vector < DataRep * >:: const_iterator first = m_datareps.begin();
00443 for ( ; first != m_datareps.end(); ++ first ) {
00444 yes |= (*first)->isDirty();
00445 }
00446 return yes;
00447 }
00448
00449
00450 void CompositePlotter::drawProjValues ( ViewBase * view )
00451 {
00452 DataRep * active_datarep = 0;
00453 if ( m_datarep_index < 0 ) {
00454 unsigned int size = m_datareps.size ();
00455
00456 for ( unsigned int i = 0; i < size; i++ ) {
00457 DataRep * rep = m_datareps[i];
00458 if ( rep -> hasCut () ) {
00459 rep -> drawProjectedValues ( m_transform, view );
00460 }
00461 }
00462
00463 for ( unsigned int i = 0; i < size; i++ ) {
00464 DataRep * rep = m_datareps[i];
00465 if ( rep -> hasCut () == false ) {
00466 rep -> drawProjectedValues ( m_transform, view );
00467 }
00468 }
00469 }
00470 else {
00471 active_datarep = m_datareps[m_datarep_index];
00472
00473 vector< DataRep * >::iterator it = m_datareps.begin();
00474
00475 for ( ; it != m_datareps.end(); ++it ) {
00476 if ( *it != active_datarep ) {
00477 (*it)->drawProjectedValues ( m_transform, view );
00478 }
00479 }
00480 active_datarep->drawProjectedValues ( m_transform, view );
00481 }
00482 }
00483
00484 void
00485 CompositePlotter::
00486 setRange ( hippodraw::Axes::Type axis, const Range & range,
00487 bool scaled, bool adjust_width )
00488 {
00489 setRangePrivate ( axis, range, scaled, adjust_width );
00490 vector< DataRep * >::iterator it = m_datareps.begin();
00491
00492 for ( ; it != m_datareps.end(); ++it ) {
00493 (*it)->setRange ( axis, ! adjust_width );
00494 }
00495 }
00496
00497 double
00498 CompositePlotter::
00499 getPosRange ( hippodraw::Axes::Type axis ) const
00500 {
00501 double min_pos = DBL_MAX;
00502 vector< DataRep * >::const_iterator it = m_datareps.begin();
00503 for ( ; it != m_datareps.end(); ++it ) {
00504 double pos = (*it)->getPosRange ( axis );
00505 if ( pos > 0.0 ) min_pos = std::min ( min_pos, pos );
00506 }
00507
00508 return min_pos;
00509 }
00510
00511 void
00512 CompositePlotter::
00513 setNumberOfBins ( hippodraw::Axes::Type axis, unsigned int number )
00514 {
00515 vector < DataRep * >:: iterator it = m_datareps.begin();
00516 while ( it != m_datareps.end() ) {
00517 ProjectorBase * projector = (*it++)->getProjector ();
00518 projector->setNumberOfBins ( axis, number );
00519 }
00520 }
00521
00522 void
00523 CompositePlotter::
00524 setBinWidth ( hippodraw::Axes::Type axis, double width )
00525 {
00526 vector < DataRep * >:: iterator it = m_datareps.begin();
00527 while ( it != m_datareps.end() ) {
00528 ProjectorBase * projector = (*it++)->getProjector ();
00529 projector->setBinWidth ( axis, width );
00530 }
00531 }
00532
00533 void
00534 CompositePlotter::
00535 reset ()
00536 {
00537 vector < DataRep * >:: iterator it = m_datareps.begin();
00538 while ( it != m_datareps.end() ) {
00539 ProjectorBase * projector = (*it++)->getProjector ();
00540 projector->reset ( );
00541 }
00542 }
00543
00544 void
00545 CompositePlotter::
00546 matrixTranspose ( bool yes )
00547 {
00548 for_each ( m_datareps.begin(), m_datareps.end(),
00549 bind2nd ( mem_fun ( &DataRep::matrixTranspose ), yes ) );
00550 }
00551
00552 void
00553 CompositePlotter::
00554 setOffset ( hippodraw::Axes::Type axis, double offset )
00555 {
00556 vector < DataRep * >:: iterator it = m_datareps.begin();
00557 while ( it != m_datareps.end() ) {
00558 ProjectorBase * projector = (*it++)->getProjector ();
00559 projector->setOffset ( axis, offset );
00560 }
00561 }
00562
00563 void
00564 CompositePlotter::
00565 setErrorDisplay ( hippodraw::Axes::Type axis, bool flag )
00566 {
00567 if ( m_datarep_index < 0 ) return;
00568
00569 DataRep * datarep = m_datareps[m_datarep_index];
00570 datarep->setErrorDisplay ( axis, flag );
00571 }
00572
00573 bool
00574 CompositePlotter::
00575 errorDisplay ( hippodraw::Axes::Type axis ) const
00576 {
00577 DataRep * datarep = m_datareps.front ();
00578
00579 return datarep->isErrorDisplayed ( axis );
00580 }
00581
00582 void CompositePlotter::setRepresentation ( RepBase * pointrep )
00583 {
00584 if ( m_datarep_index < 0 ) return;
00585
00586 DataRep * datarep = m_datareps[m_datarep_index];
00587 datarep->setRepresentation ( pointrep );
00588 }
00589
00590 RepBase * CompositePlotter::representation ( ) const
00591 {
00592 DataRep * datarep = 0;
00593 if ( m_datarep_index < 0 ) {
00594 datarep = m_datareps.front();
00595 }
00596 else {
00597 datarep = m_datareps[m_datarep_index];
00598 }
00599
00600 return datarep->getRepresentation ();
00601 }
00602
00603 const BinToColor *
00604 CompositePlotter::
00605 getValueRep () const
00606 {
00607 RepBase * rep = representation ();
00608
00609 return rep -> getValueTransform ();
00610 }
00611
00612
00613
00614 void
00615 CompositePlotter::
00616 setValueRep ( BinToColor * btc )
00617 {
00618 RepBase * rep = representation ();
00619 rep -> setValueTransform ( btc );
00620 }
00621
00622 int
00623 CompositePlotter::
00624 getNumberOfEntries () const
00625 {
00626 int index = activePlotIndex();
00627 int number = 0;
00628
00629 if ( ! ( index < 0 ) ) {
00630 const DataRep * rep = getDataRep ( index );
00631 number = rep -> getNumberOfEntries ();
00632 }
00633 return number;
00634 }
00635
00636
00637 double
00638 CompositePlotter::
00639 getBinWidth ( hippodraw::Axes::Type axis ) const
00640 {
00641 int index = activePlotIndex ();
00642
00643 if ( !( index < 0 ) ) {
00644 ProjectorBase * projector = getProjector ( index );
00645 return projector->getBinWidth ( axis );
00646 }
00647
00648 vector< DataRep * >::const_iterator it = m_datareps.begin();
00649
00650 string saxis;
00651 if ( axis == Axes::X ) {
00652 saxis = "X";
00653 } else if ( axis == Axes::Y ) {
00654 saxis = "Y";
00655 } else {
00656 saxis = "Z";
00657 }
00658
00659 double first = -1.0;
00660 for ( ; it != m_datareps.end(); ++it ) {
00661
00662 ProjectorBase * projector = (*it)->getProjector();
00663
00664 if ( !( projector->isAxisBinned ( saxis ) ) ) {
00665 continue;
00666 }
00667
00668 if ( first < 0.0 ) {
00669 first = projector->getBinWidth ( axis );
00670 continue;
00671 }
00672
00673 double next = projector->getBinWidth ( axis );
00674
00675
00676
00677
00678
00679 if ( std::abs ( first - next ) > DBL_EPSILON ) {
00680 return -1.0;
00681 }
00682 }
00683
00684 return first;
00685 }
00686
00687 double
00688 CompositePlotter::
00689 getOffset ( hippodraw::Axes::Type axis ) const
00690 {
00691 int index = activePlotIndex ();
00692
00693 if ( !( index < 0 ) ) {
00694 ProjectorBase * projector = getProjector ( index );
00695 return projector->getOffset ( axis );
00696 }
00697
00698 vector< DataRep * >::const_iterator it = m_datareps.begin();
00699
00700 string saxis;
00701 if ( axis == Axes::X ) {
00702 saxis = "X";
00703 } else if ( axis == Axes::Y ) {
00704 saxis = "Y";
00705 } else {
00706 saxis = "Z";
00707 }
00708
00709 double first = -1.0;
00710 for ( ; it != m_datareps.end(); ++it ) {
00711
00712 ProjectorBase * projector = (*it)->getProjector();
00713
00714 if ( !( projector->isAxisBinned ( saxis ) ) ) {
00715 continue;
00716 }
00717
00718 if ( first < 0.0 ) {
00719 first = projector->getOffset ( axis );
00720 continue;
00721 }
00722
00723 double next = projector->getOffset ( axis );
00724 if ( first != next ) return -1.0;
00725 }
00726
00727 return first;
00728 }
00729
00730 void CompositePlotter::setRepColor ( const Color & color )
00731 {
00732 if ( m_datarep_index < 0 ) return;
00733
00734 DataRep * datarep = m_datareps[m_datarep_index];
00735 datarep->setRepColor ( color );
00736 }
00737
00738 const Color & CompositePlotter::repColor ( ) const
00739 {
00740 DataRep * datarep = 0;
00741 if ( m_datarep_index < 0 ) {
00742 datarep = m_datareps.front();
00743 }
00744 else {
00745 datarep = m_datareps[m_datarep_index];
00746 }
00747
00748 return datarep->getRepColor ( );
00749 }
00750
00751 void
00752 CompositePlotter::
00753 setAxisModel ( AxisModelBase * model, hippodraw::Axes::Type axis )
00754 {
00755
00756 assert ( axis == Axes::X || axis == Axes::Y || axis == Axes::Z );
00757
00758 if ( axis == Axes::X ) m_x_axis = model;
00759 if ( axis == Axes::Y ) m_y_axis = model;
00760 if ( axis == Axes::Z && hasAxis ( Axes::Z ) ) m_z_axis = model;
00761
00762 assert ( model );
00763
00764 vector< DataRep * >:: iterator first = m_datareps.begin ();
00765 for ( ; first != m_datareps.end (); ++first ) {
00766 (*first)->setAxisModel ( axis, model );
00767 }
00768
00769 setAutoScaled ( false );
00770 }
00771
00772 void CompositePlotter::setAutoRanging ( bool flag )
00773 {
00774 setAutoRanging ( Axes::X, flag );
00775 setAutoRanging ( Axes::Y, flag );
00776 if ( hasAxis ( Axes::Z ) ) setAutoRanging ( Axes::Z, flag );
00777 }
00778
00779 TransformBase *
00780 CompositePlotter::
00781 getTransform () const
00782 {
00783 return m_transform;
00784 }
00785
00786
00787 void CompositePlotter::setTransform ( TransformBase * tf )
00788 {
00789 BinaryTransform * p = dynamic_cast< BinaryTransform * > ( tf );
00790 if (p) {
00791 TransformBase * tmp = tf -> clone ();
00792 std::swap ( tmp, m_transform );
00793 delete tmp;
00794
00795 setAutoScaled ( false );
00796 } else {
00797 std::string what("CompositePlotter::setTransform: ");
00798 what += "Require a BinaryTransform in this context.";
00799 throw PlotterException(what);
00800 }
00801 }
00802
00805 void
00806 CompositePlotter::
00807 toUserXY ( double x, double y, bool scaled,
00808 double & ux, double & uy ) const
00809 {
00810 BinaryTransform * transform
00811 = dynamic_cast < BinaryTransform * > ( m_transform );
00812 assert ( transform );
00813
00814 transform -> inverseTransform ( x, y );
00815
00816 ux = processReturnValue ( x, Axes::X, scaled );
00817 uy = processReturnValue ( y, Axes::Y, scaled );
00818 }
00819
00820 NTuple *
00821 CompositePlotter::
00822 createPickTuple ( )
00823 {
00824 unsigned int size = 3;
00825 vector < string > labels;
00826 labels.reserve ( 5 );
00827
00828 labels.push_back ( "Item number" );
00829 labels.push_back ( getLabel ( Axes::X ) );
00830 labels.push_back ( getLabel ( Axes::Y ) );
00831
00832 if ( hasAxis ( Axes::Z ) ) {
00833 size = 4;
00834 labels.push_back ( getLabel ( Axes::Z ) );
00835 if ( isAxisScaled ( Axes::Z ) ) {
00836 size = 5;
00837 labels.push_back ( "Density" );
00838 }
00839 }
00840 else {
00841 if ( isAxisScaled ( Axes::Y ) ) {
00842 size = 4;
00843 labels.push_back ( "Density" );
00844 }
00845 }
00846
00847 NTuple * ntuple = new NTuple ( labels );
00848
00849 return ntuple;
00850 }
00851
00852 double
00853 CompositePlotter::
00854 getZValue ( double x, double y, bool scaled ) const
00855 {
00856 DataRep * datarep = selectedDataRep ();
00857 if ( !datarep ){
00858 datarep = getDataRep ( 0 );
00859 }
00860 assert ( datarep );
00861
00862 ProjectorBase * proj = datarep->getProjector();
00863 assert ( proj );
00864
00865 double retval = proj->getZValue ( x, y );
00866
00867 return processReturnValue ( retval, Axes::Z, scaled );
00868 }
00869
00870 void
00871 CompositePlotter::
00872 fillPickedPoint ( double x, double y, std::vector < double > & picked ) const
00873 {
00874 BinaryTransform * tf
00875 = dynamic_cast < BinaryTransform * > ( m_transform );
00876 assert ( tf );
00877
00878 tf -> inverseTransform ( x, y );
00879
00880 double ux = processReturnValue ( x, Axes::X, true );
00881 double uy = processReturnValue ( y, Axes::Y, true );
00882
00883
00884
00885
00886 if ( tf->isPeriodic() )
00887 {
00888 const PeriodicBinaryTransform * tp
00889 = dynamic_cast < const PeriodicBinaryTransform * > ( tf );
00890
00891 double xoffset = tp->xOffset();
00892 double yoffset = tp->yOffset();
00893
00894 ux = tp->moduloAddX( ux, xoffset );
00895 uy = tp->moduloAddY( uy, yoffset );
00896 }
00897 picked.clear ();
00898 picked.push_back ( 0.0 );
00899 picked.push_back ( ux );
00900 picked.push_back ( uy );
00901 if ( hasAxis ( Axes::Z ) ) {
00902 if ( isAxisScaled ( Axes::Z ) ) {
00903 picked.push_back ( getZValue ( ux, uy, true ) );
00904 picked.push_back ( getZValue ( ux, uy, false ) );
00905 picked[0] = 3.0;
00906 }
00907 else {
00908 picked.push_back ( getZValue ( ux, uy, false ) );
00909 picked[0] = 2.0;
00910 }
00911 }
00912 else {
00913 if ( isAxisScaled ( Axes::Y ) ) {
00914 picked.push_back ( processReturnValue ( y, Axes::Y, false ) );
00915 picked[0] = 1.0;
00916 }
00917 }
00918
00919 }
00920
00921 double
00922 CompositePlotter::
00923 processReturnValue ( double retval,
00924 hippodraw::Axes::Type axis,
00925 bool scaled ) const
00926 {
00927
00928 DataRep * datarep = mouseSelectedDataRep ();
00929 if ( !datarep ){
00930 datarep = getDataRep ( 0 );
00931 }
00932 assert ( datarep );
00933
00934 ProjectorBase * proj = datarep->getProjector();
00935 assert ( proj );
00936
00937 AxisModelBase * a = proj->getAxisModel ( axis );
00938 assert ( a );
00939
00940 double sf = a->getScaleFactor();
00941
00942 double scaledRetval = retval * sf;
00943
00944 if ( scaled ) {
00945 retval = retval * sf;
00946 }
00947
00948 const Range r = a->getRange ( true );
00949
00950 if ( scaledRetval > r.high() ) {
00951 if ( scaled ) {
00952 return r.high();
00953 }
00954 else {
00955 return r.high() / sf;
00956 }
00957 }
00958
00959 if ( scaledRetval < r.low() ) {
00960 if ( scaled ) {
00961 return r.low();
00962 }
00963 else {
00964 return r.low() / sf;
00965 }
00966 }
00967
00968 return retval;
00969 }
00970
00971 DataRep * CompositePlotter::mouseSelectedDataRep() const
00972 {
00973 return selectedDataRep();
00974 }
00975
00976 void
00977 CompositePlotter::
00978 addValues ( const std::vector < double > & v )
00979 {
00980 DataRep * rep = getDataRep ( 0 );
00981 rep->addValues ( v );
00982 }
00983
00984 NTuple *
00985 CompositePlotter::
00986 createNTuple () const
00987 {
00988 DataRep * rep = selectedDataRep ();
00989 if ( rep == 0 ) {
00990 rep = getDataRep ( 0 );
00991 }
00992 NTuple * ntuple = rep -> createNTuple ();
00993
00994 return ntuple;
00995 }
00996
00997 void
00998 CompositePlotter::
00999 update ()
01000 {
01001 vector < DataRep * > :: iterator first = m_datareps.begin ();
01002
01003 while ( first != m_datareps.end () ) {
01004 (*first++) -> update ();
01005 }
01006 }
01007
01008 void
01009 CompositePlotter::
01010 setAutoTicks ( hippodraw::Axes::Type axis, bool yes )
01011 {
01012 AxisModelBase * model = getAxisModel ( axis );
01013
01014 model -> setAutoTicks ( yes );
01015 }
01016
01017 void
01018 CompositePlotter::
01019 setTicks ( hippodraw::Axes::Type axis,
01020 const std::vector < AxisTick > & ticks )
01021 {
01022 AxisModelBase * model = getAxisModel ( axis );
01023
01024 model -> setTicks ( ticks );
01025 }
01026
01027 bool
01028 CompositePlotter::
01029 isTargetable ( ) const
01030 {
01031 bool yes = false;
01032 std::size_t number = m_datareps.size ();
01033
01034 if ( number == 1 ) {
01035 DataRep * datarep = m_datareps.front();
01036 yes = datarep -> isTargetable ();
01037 }
01038 else {
01039 int targets = 0;
01040 for ( std::size_t i = 0; i < number; i++ ) {
01041 DataRep * datarep = m_datareps[i];
01042 if ( datarep -> isTargetable () &&
01043 datarep -> isSelected () ) {
01044 targets ++;
01045 }
01046 }
01047 if ( targets == 1 ) yes = true;
01048 }
01049
01050 return yes;
01051 }
01052
01053 DataRep *
01054 CompositePlotter::
01055 getTarget () const
01056 {
01057 DataRep * rep = 0;
01058 std::size_t size = m_datareps.size ();
01059
01060 for ( std::size_t i = 0; i < size; i++ ) {
01061 DataRep * dr = m_datareps[i];
01062 if ( dr -> isSelected () ) {
01063 rep = dr;
01064 break;
01065 }
01066 }
01067
01068 return rep;
01069 }
01070
01071 int
01072 CompositePlotter::
01073 indexOf ( const DataRep * rep ) const
01074 {
01075 int index = -1;
01076 std::size_t size = m_datareps.size();
01077 for ( std::size_t i = 0; i < size; i++ ) {
01078 DataRep * dr = m_datareps[i];
01079 if ( dr == rep ) {
01080 index = i;
01081 break;
01082 }
01083 }
01084
01085 return index;
01086 }
01087
01088 bool
01089 CompositePlotter::
01090 hasAxis ( hippodraw::Axes::Type axis ) const
01091 {
01092 if ( axis == Axes::X ) return m_x_axis != 0;
01093 if ( axis == Axes::Y ) return m_y_axis != 0;
01094 if ( axis == Axes::Z ) return m_z_axis != 0;
01095
01096 return false;
01097 }
01098
01099 bool
01100 CompositePlotter::
01101 isAxisScaled ( hippodraw::Axes::Type axis ) const
01102 {
01103 bool yes = false;
01104 if ( axis == Axes::X ) yes = m_x_axis -> isScaling ();
01105 if ( axis == Axes::Y ) yes = m_y_axis -> isScaling ();
01106 if ( axis == Axes::Z ) yes = m_z_axis -> isScaling ();
01107
01108 return yes;
01109 }
01110
01111 AxisModelBase *
01112 CompositePlotter::
01113 getAxisModel ( hippodraw::Axes::Type axis ) const
01114 {
01115 if ( axis == Axes::X ) return m_x_axis;
01116 else if ( axis == Axes::Y ) return m_y_axis;
01117 else if ( axis == Axes::Z ) return m_z_axis;
01118
01119 assert ( false );
01120
01121 return 0;
01122 }
01123
01124
01125
01126
01127
01128 void
01129 CompositePlotter::
01130 setAutoRanging ( hippodraw::Axes::Type axis, bool flag )
01131 {
01132
01133 assert ( axis == Axes::X || axis == Axes::Y || axis == Axes::Z );
01134
01135 AxisModelBase * model = 0;
01136 if ( axis == Axes::X ) model = m_x_axis;
01137 else if ( axis == Axes::Y ) model = m_y_axis;
01138 else
01139 {
01140 if(!m_z_axis)return;
01141 model = m_z_axis;
01142 }
01143
01144 assert (model);
01145
01146 model->setAutoRanging ( flag );
01147 if ( flag == false ) return;
01148
01149 m_x_axis->setEmpty();
01150 m_y_axis->setEmpty();
01151 if ( m_z_axis ) m_z_axis->setEmpty();
01152
01153 setAutoScaled ( false );
01154 }
01155
01156 bool
01157 CompositePlotter::
01158 isAutoRanging ( hippodraw::Axes::Type axis ) const
01159 {
01160 assert ( axis == Axes::X || axis == Axes::Y || axis == Axes::Z );
01161 if ( axis == Axes::X ) {
01162 return m_x_axis->isAutoRanging ( );
01163 } else if ( axis == Axes::Y ) {
01164 return m_y_axis->isAutoRanging ( );
01165 }
01166
01167 if( !m_z_axis ) return false;
01168
01169 return m_z_axis->isAutoRanging ( );
01170 }
01171
01172 void
01173 CompositePlotter::
01174 setRangePrivate ( hippodraw::Axes::Type axis, const Range & range,
01175 bool scaled, bool adjust_width )
01176 {
01177 BinaryTransform * transform
01178 = dynamic_cast< BinaryTransform * > ( m_transform );
01179 if ( axis == Axes::X ) {
01180 m_x_axis->setRange ( range, scaled );
01181 const Range & current = m_x_axis->getRange ( false );
01182 const Range & limit = transform->limitX ();
01183 m_x_axis->setIntersectRange ( current, limit );
01184 m_x_axis->setAutoRanging ( false );
01185 }
01186 else if ( axis == Axes::Y ) {
01187 m_y_axis->setRange ( range, scaled );
01188 const Range & current = m_y_axis->getRange ( false );
01189 const Range & limit = transform->limitY ();
01190 m_y_axis->setIntersectRange ( current, limit );
01191 m_y_axis->setAutoRanging ( false );
01192 }
01193 else if ( axis == Axes::Z ) {
01194 m_z_axis->setRange ( range, scaled );
01195 const Range & current = m_z_axis->getRange ( false );
01196 const Range & limit = transform->limitZ ();
01197 m_z_axis->setIntersectRange ( current, limit );
01198 m_z_axis->setAutoRanging ( false );
01199 }
01200 }
01201
01202 void
01203 CompositePlotter::
01204 setLowRange ( hippodraw::Axes::Type type,
01205 int parm, bool dragging )
01206 {
01207 AxisModelBase * model = 0;
01208
01209 if ( type == Axes::X ) model = m_x_axis;
01210 else if ( type == Axes::Y ) model = m_y_axis;
01211 else if ( type == Axes::Z ) model = m_z_axis;
01212 assert ( model );
01213
01214 Range new_range = model->calcLow ( parm, dragging );
01215 setRangePrivate ( type, new_range );
01216 }
01217
01218 void
01219 CompositePlotter::
01220 setHighRange ( hippodraw::Axes::Type type,
01221 int parm, bool dragging )
01222 {
01223 AxisModelBase * model = 0;
01224
01225 if ( type == Axes::X ) model = m_x_axis;
01226 else if ( type == Axes::Y ) model = m_y_axis;
01227 else if ( type == Axes::Z ) model = m_z_axis;
01228 assert ( model );
01229
01230 Range new_range = model->calcHigh ( parm, dragging );
01231
01232 setRangePrivate ( type, new_range );
01233 }
01234
01235 const Range &
01236 CompositePlotter::
01237 getRange ( hippodraw::Axes::Type axis, bool scaled ) const
01238 {
01239 bool ok = axis == Axes::X || axis == Axes::Y || axis == Axes::Z;
01240 if ( ok == false ||
01241 ( axis == Axes::Z && m_z_axis == 0 ) ) {
01242 string what ( "PlotterBase::getRange: " );
01243 what += "This plotter does not have such axis";
01244 throw PlotterException ( what );
01245 }
01246
01247 if ( axis == Axes::X ) return m_x_axis->getRange ( scaled );
01248
01249 if ( axis == Axes::Y ) return m_y_axis->getRange ( scaled );
01250
01251 return m_z_axis->getRange ( scaled );
01252 }
01253
01254 void
01255 CompositePlotter::
01256 setScaleFactor ( hippodraw::Axes::Type axis, double factor )
01257 {
01258 if ( axis == Axes::X ) {
01259 m_x_axis->setScaleFactor ( factor );
01260 }
01261 else if ( axis == Axes::Y ) {
01262 m_y_axis->setScaleFactor ( factor );
01263 }
01264 else if ( axis == Axes::Z ) {
01265 if ( m_z_axis ) m_z_axis->setScaleFactor ( factor );
01266 }
01267 }
01268
01269 void
01270 CompositePlotter::
01271 setScaling ( hippodraw::Axes::Type axis, bool on )
01272 {
01273 if ( axis == Axes::X ) {
01274 m_x_axis->setScaling ( on );
01275 }
01276 else if ( axis == Axes::Y ) {
01277 m_y_axis->setScaling ( on );
01278 }
01279 else if ( axis == Axes::Z ) {
01280 if ( m_z_axis ) m_z_axis->setScaling ( on );
01281 }
01282 }
01283
01284 void
01285 CompositePlotter::
01286 setLabel ( hippodraw::Axes::Type axis, const std::string & value )
01287 {
01288 assert ( axis == Axes::X || axis == Axes::Y || axis == Axes::Z );
01289
01290 if ( axis == Axes::X ) m_x_label = value;
01291 else if ( axis == Axes::Y ) m_y_label = value;
01292 else if ( axis == Axes::Z ) m_z_label = value;
01293 }
01294
01295 const string &
01296 CompositePlotter::
01297 getLabel ( hippodraw::Axes::Type axis ) const
01298 {
01299 assert ( axis == Axes::X || axis == Axes::Y || axis == Axes::Z );
01300
01301 ProjectorBase * projector = activeProjector();
01302
01303 if ( axis == Axes::X ) {
01304 if ( projector == 0 || m_x_label != "%x" ) return m_x_label;
01305 else return projector->getXLabel ( );
01306 }
01307 if ( axis == Axes::Y ) {
01308 if ( projector == 0 || m_y_label != "%y" ) return m_y_label;
01309 else return projector->getYLabel ( );
01310 }
01311
01312 if ( projector == 0 || m_z_label != "%z" ) return m_z_label;
01313 return projector->getZLabel ( );
01314 }
01315
01316 const string &
01317 CompositePlotter::
01318 getInternalLabel ( hippodraw::Axes::Type axis ) const
01319 {
01320 assert ( axis == Axes::X || axis == Axes::Y || axis == Axes::Z );
01321
01322 if ( axis == Axes::X ) {
01323 return m_x_label;
01324 }
01325 else if ( axis == Axes::Y ) {
01326 return m_y_label;
01327 }
01328
01329 return m_z_label;
01330 }
01331
01332 double
01333 CompositePlotter::
01334 getAspectRatio () const
01335 {
01336 if ( m_transform == 0 ) return 0.0;
01337
01338 return m_transform->aspectRatio ();
01339 }
01340
01341 void
01342 CompositePlotter::
01343 checkAxisScaling ( )
01344 {
01345 int number = getNumDataReps ();
01346 if ( number < 2 ) return;
01347
01348 bool wants_scaling = false;
01349 for ( int i = 0; i < number; i++ ) {
01350 ProjectorBase * projector = getProjector ( i );
01351 wants_scaling |= projector->wantsScaleFactor ( "Y" );
01352 }
01353 if ( wants_scaling == true ) {
01354
01355 double width = getBinWidth ( Axes::X );
01356
01357 if ( width <= 0.0 ) {
01358 setScaling ( Axes::Y, false );
01359 }
01360 else {
01361 setScaleFactor ( Axes::Y, width );
01362 }
01363 }
01364
01365 }
01366
01367 void
01368 CompositePlotter::
01369 setAutoScaled ( bool flag )
01370 {
01371 m_has_autoscaled = flag;
01372 }
01373
01374 bool
01375 CompositePlotter::
01376 hasAutoScaled () const
01377 {
01378 return m_has_autoscaled;
01379 }
01380
01381 bool
01382 CompositePlotter::
01383 checkAutoScale ()
01384 {
01385 bool has_scaled = hasAutoScaled ();
01386 bool is_dirty = isDirty ();
01387
01388 bool yes = ( has_scaled == false ) || is_dirty == true;
01389
01390 return yes;
01391 }
01392
01393 void
01394 CompositePlotter::
01395 prepareToDraw ()
01396 {
01397 Range x_range = m_x_axis->getRange ( false );
01398 Range y_range = m_y_axis->getRange ( false );
01399
01400
01401 TransformBase * tbase = getTransform ();
01402 BinaryTransform * transform = dynamic_cast < BinaryTransform * > ( tbase );
01403
01404 transform->validate ( x_range, y_range );
01405
01406 double z_lo = 0.;
01407 double z_hi = 0.;
01408
01409 if ( m_x_axis -> isAutoTicks () ) {
01410 const vector < AxisTick > & x_ticks
01411 = transform -> setTicks ( *m_x_axis, Axes::X );
01412 m_x_axis -> setTicks ( x_ticks );
01413 }
01414
01415 if ( m_y_axis -> isAutoTicks () ) {
01416 const vector < AxisTick > & y_ticks
01417 = transform -> setTicks ( *m_y_axis, Axes::Y );
01418 m_y_axis -> setTicks ( y_ticks );
01419 }
01420
01421 if ( m_has_z ) {
01422 const Range & z_range = m_z_axis->getRange ( false );
01423 if ( m_z_axis -> isAutoTicks () ) {
01424 const vector < AxisTick > & z_ticks
01425 = transform -> setTicks ( *m_z_axis, Axes::Z );
01426 m_z_axis -> setTicks ( z_ticks );
01427 }
01428 z_lo = z_range.low ();
01429 z_hi = z_range.high ();
01430
01431 transform->transformZ ( z_lo );
01432 transform->transformZ ( z_hi );
01433 }
01434
01435 m_x_axis->setRange ( x_range, false );
01436 m_y_axis->setRange ( y_range, false );
01437 }
01438
01439 HippoRectangle
01440 CompositePlotter::
01441 calcUserRectangle ( ) const
01442 {
01443 BinaryTransform * transform
01444 = dynamic_cast < BinaryTransform * > ( m_transform );
01445 const Range & x_range = m_x_axis -> getRange ( false );
01446 const Range & y_range = m_y_axis -> getRange ( false );
01447
01448 HippoRectangle rect = transform -> calcRectangle ( x_range, y_range );
01449 if ( m_has_z ) {
01450 const Range & range = m_z_axis -> getRange ( false );
01451 double z_lo = range.low ();
01452 double z_hi = range.high ();
01453 transform -> transformZ ( z_lo );
01454 transform -> transformZ ( z_hi );
01455 rect.setZ ( z_lo );
01456 rect.setDepth ( z_hi - z_lo );
01457 }
01458
01459 return rect;
01460 }
01461
01462 void
01463 CompositePlotter::
01464 drawAxisRep ( AxisRepBase * rep, ViewBase * view,
01465 bool do_y, bool do_z )
01466 {
01467 rep->setFontSize ( m_x_axis, m_y_axis, m_z_axis, *view );
01468
01469 rep->drawXLabels( *m_x_axis, *view, ( m_x_label == "%x" ) ?
01470 getLabel ( Axes::X ) : m_x_label );
01471
01472 if ( do_y ) {
01473 rep->drawYLabels( *m_y_axis, *view, ( m_y_label == "%y" ) ?
01474 getLabel ( Axes::Y ) : m_y_label );
01475 }
01476
01477 if ( m_has_z && do_z ) {
01478 rep->drawZLabels( *m_z_axis, *view, ( m_z_label == "%z" ) ?
01479 getLabel ( Axes::Z ) : m_z_label );
01480 const BinToColor * btc = getValueRep ();
01481 rep ->drawColorScale ( *btc, *view );
01482 }
01483
01484 const Range & x_range = m_x_axis -> getRange ( false );
01485 const Range & y_range = m_y_axis -> getRange ( false );
01486
01487 rep->drawAxesLines( *m_transform, *view, x_range, y_range );
01488
01489
01490 BinaryTransform * transform
01491 = dynamic_cast < BinaryTransform * > ( m_transform );
01492 if ( transform->needsXTicks() ) {
01493 rep->drawAllXTicks( *m_x_axis, *m_y_axis, *transform, *view );
01494 }
01495
01496
01497 if ( do_y && transform->needsYTicks() ) {
01498 rep->drawAllYTicks( *m_x_axis, *m_y_axis, *transform, *view );
01499 }
01500
01501 if ( do_z && m_has_z ) {
01502 rep->drawAllZTicks( *m_z_axis, *transform, *view );
01503 }
01504
01505 if ( transform->needsGrid() ) {
01506 rep->drawGridLines( *m_x_axis, *m_y_axis, *transform, *view );
01507 }
01508 }
01509
01510 void
01511 CompositePlotter::
01512 setEnableZ ( bool yes )
01513 {
01514 if ( yes ) {
01515 m_z_axis = new AxisModelLinear ( PLOTTOP, PLOTTOP );
01516 }
01517 else {
01518 if ( m_z_axis != 0 ) delete m_z_axis;
01519 }
01520
01521 m_has_z = yes;
01522 }
01523
01524 void
01525 CompositePlotter::
01526 fillCutList ( std::vector < const TupleCut * > & cuts ) const
01527 {
01528 DataRepList_t::const_iterator first = m_datareps.begin();
01529 while ( first != m_datareps.end () ) {
01530 const DataRep * rep = *first++;
01531 const vector < TupleCut > & tcuts = rep ->getCuts ();
01532 unsigned int size = tcuts.size ();
01533 for ( unsigned int i = 0; i < size; i++ ) {
01534 cuts.push_back ( &tcuts[i] );
01535 }
01536 }
01537 }
01538
01539 void
01540 CompositePlotter::
01541 setCutRangeAt ( const Range & range, unsigned int i )
01542 {
01543 DataRep * rep = selectedDataRep ();
01544 rep -> setCutRangeAt ( range, i );
01545 }