Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ContourPointRep.cxx

Go to the documentation of this file.
00001 
00012 // For truncation warning
00013 #ifdef _MSC_VER
00014 #include "msdevstudio/MSconfig.h"
00015 #endif
00016 
00017 #include "ContourPointRep.h"
00018 
00019 #include "BinToColor.h"
00020 #include "BinToColorFactory.h"
00021 
00022 #include "axes/AxisModelBase.h"
00023 #include "datasrcs/DataPointTuple.h"
00024 #include "datasrcs/DataSource.h"
00025 #include "graphics/ViewBase.h"
00026 #include "projectors/NTupleProjector.h"
00027 #include "transforms/BinaryTransform.h"
00028 
00029 #include <cassert>
00030 
00031 using namespace hippodraw;
00032 
00033 using std::max;
00034 using std::min;
00035 using std::vector;
00036 
00037 ContourPointRep::ContourPointRep ( float size )
00038   : LinePointRep ( size )
00039 {
00040   init ();
00041 }
00042 
00043 ContourPointRep::ContourPointRep ( )
00044   : LinePointRep ( )
00045 {
00046   init();
00047 }
00048 
00049 void
00050 ContourPointRep::
00051 init ()
00052 {
00053   BinToColorFactory * factory = BinToColorFactory::instance ();
00054   m_bin_to_color = factory -> create ( "Rainbow" );
00055   m_name = "Contour"; // need to override what base class did
00056   m_numContours = 6;
00057   m_usingUserValues = false;
00058   m_values.clear();
00059   m_values.reserve ( m_numContours );
00060 }
00061 
00062 ContourPointRep::ContourPointRep( const ContourPointRep & rep )
00063   : LinePointRep ( rep )
00064 {
00065   BinToColor * btc = rep.m_bin_to_color;
00066   m_bin_to_color = btc -> clone ();
00067 
00068   m_numContours = rep.getNumContours();
00069   m_usingUserValues = rep.getUsingUserValues();
00070   m_values.clear();
00071   m_values.reserve ( m_numContours );
00072 }
00073 
00074 ContourPointRep::~ContourPointRep()
00075 {
00076   delete m_bin_to_color;
00077 }
00078 
00079 RepBase * ContourPointRep::clone()
00080 {
00081   return new ContourPointRep ( *this );
00082 }
00083 
00084 const BinToColor *
00085 ContourPointRep::
00086 getValueTransform ( ) const
00087 {
00088   return m_bin_to_color;
00089 }
00090 
00091 void
00092 ContourPointRep::
00093 setValueTransform ( BinToColor * btc )
00094 {
00095   delete m_bin_to_color;
00096   m_bin_to_color = btc;
00097 }
00098 
00099 void ContourPointRep::endPlot ( const TransformBase & tf, 
00100                                 ViewBase & vb,
00101                                 const Range & range )
00102 {
00103   // Draw Contour Ticks
00104 
00105   drawContourTicks ( tf, vb, m_values );
00106 
00107   // Draw Lines.
00108 
00109   try {
00110     const BinaryTransform & t 
00111       = dynamic_cast < const BinaryTransform & > ( tf );
00112 
00113     t.transform ( m_x, m_y );
00114     const HippoRectangle & user_rect = vb.getUserRect ();
00115     user_rect.makeInBounds ( m_x, m_y );
00116     
00117     vb.drawColorLines ( m_x, m_y, m_line_style, m_colorvec, m_size );
00118     
00119   }
00120   catch ( ... ) {
00121     assert ( false );
00122   }
00123 }
00124 
00125 void
00126 ContourPointRep::
00127 drawContourTicks ( const TransformBase & tb,
00128                    ViewBase & vb,
00129                    const std::vector < double > & values )
00130 {
00131   
00132   vector< double > xv;
00133   vector< double > yv;
00134   
00135   unsigned int size = values.size ();
00136   xv.reserve ( size );
00137   yv.reserve ( size );
00138 
00139   const Range & range = vb.getRange ( Axes::Z );
00140 
00141   const BinaryTransform & bt 
00142     = dynamic_cast < const BinaryTransform & > ( tb );
00143   
00144   const HippoRectangle view_rect = vb.getMarginRect ();
00145   double tick_length = 0.05 * view_rect.getHeight ();
00146 
00147   double y_base = view_rect.getY() -
00148     ( 1.05 / 9.0 ) * view_rect.getHeight() + 0.05 * view_rect.getHeight();
00149 
00150   for ( unsigned int i = 0; i < values.size(); i++ ) {
00151     
00152     double user_z = values[i];
00153 
00154     if ( range.excludes ( user_z ) ) continue;
00155 
00156     bt.transformZ ( user_z );
00157     
00158     //double y = 1.0;
00159     // Reinstate the following line when XYZ transform exists.
00160     //t.transform ( user_z, y ); // Some valid value on Y.
00161   
00162     double view_x = vb.userToDrawColor ( user_z );
00163     xv.push_back ( view_x );
00164     yv.push_back ( y_base );
00165     xv.push_back ( view_x );
00166     yv.push_back ( y_base + tick_length );
00167   
00168   }
00169 
00170   vb.drawViewLines ( xv, yv, Line::Solid, false, 0 );
00171   
00172 }
00173 
00174 namespace dp = hippodraw::DataPoint3DTuple;
00175 
00176 void
00177 ContourPointRep::
00178 createContours (  const DataSource * ntuple,
00179                   const TransformBase * transform )
00180 {
00181   int size = m_values.size();
00182   assert ( size == m_numContours );
00183 
00184   if ( ntuple -> rows () == 0 ) return;
00185 
00186   double      h [5];
00187   int         sh [5];
00188   double      xh [5];
00189   double      yh [5];
00190   int         m1;
00191   int         m2;
00192   int         m3;
00193   int         case_value;
00194   double      dmin;
00195   double      dmax;
00196   double      x1 = 0.0;
00197   double      x2 = 0.0;
00198   double      y1 = 0.0;
00199   double      y2 = 0.0;
00200   unsigned int i,j;
00201   int         k,m;
00202        
00203   int im[4] = {0,1,1,0};
00204   int jm[4] = {0,0,1,1};
00205         
00206   // Castab = Case Table.
00207   
00208   // castab[0][0][0] ==> all three points of the triangle are below
00209   // the plane of the contour.
00210   // 1 ==> in the plane of the contour.
00211   // 2 ==> above the plane of the contour.
00212   
00213   int castab [3][3][3] =
00214     {
00215       {
00216         {0,0,8},{0,2,5},{7,6,9}
00217       },
00218       {
00219         {0,3,4},{1,0,1},{4,3,0}
00220       },
00221       {
00222         {9,6,7},{5,2,0},{8,0,0}
00223       }
00224     };
00225   const vector < unsigned int > & shape = ntuple -> getShape ();
00226   unsigned int i_size = shape[0];  
00227   unsigned int j_size = shape[1];  
00228   vector < unsigned int > index ( 3 );
00229 
00230   for ( i = 0; i < i_size - 1; i++ ) {
00231 
00232     for ( j = 0; j < j_size - 1; j++ ) {
00233       // For box given by (i,j), (i,j+1), (i+1,j), (i+1,j+1),
00234       // find max and min value.
00235 
00236       double temp1,temp2;
00237       index[0] = i;
00238       index[1] = j;
00239       index[2] = dp::Z;
00240       double tempij = ntuple -> operator [] ( index );
00241 
00242       index[1] = j+1;
00243       double tempij1 = ntuple -> operator [] ( index );
00244 
00245       temp1 = min ( tempij, tempij1 );
00246 
00247       index[0] = i+1;
00248       index[1] = j;
00249       double tempi1j = ntuple -> operator[] ( index );
00250 
00251       index[1] = j+1;
00252       double tempi1j1 = ntuple -> operator [] ( index );
00253       temp2 = min ( tempi1j, tempi1j1 );
00254 
00255       dmin  = min ( temp1, temp2 );
00256       
00257       temp1 = max ( tempij, tempij1 );
00258       temp2 = max ( tempi1j, tempi1j1 );
00259       dmax  = max ( temp1, temp2 );
00260   
00261       if ( dmax >= m_values [0] &&
00262            dmin <= m_values [m_numContours-1] ) {
00263         
00264         for ( k = 0; k < m_numContours; k++ ) {
00265           
00266           double curContour = m_values[k];
00267           
00268           if ( curContour >= dmin &&
00269                curContour <= dmax ) {
00270 
00271             // Contour level k passes through the box.
00272             
00273             for ( m = 4; m >= 0; m--) {
00274               
00275               if ( m > 0 ) {
00276                 
00277                 index[0] = i + im[m-1];
00278                 index[1] = j + jm[m-1];
00279                 index[2] = dp::Z;
00280                 h[m] = ntuple -> operator [] ( index ) - curContour;
00281 
00282                 index[2] = dp::X;
00283                 xh[m] = ntuple -> operator [] ( index );
00284 
00285                 index[2] = dp::Y;
00286                 yh[m] = ntuple -> operator [] ( index );
00287               
00288               } 
00289               
00290               else {
00291                 
00292                 h[0]  = 0.25 * ( h[1] + h[2] + h[3] + h[4] );
00293                 index[0] = i;
00294                 index[1] = j;
00295                 index[2] = dp::X;
00296                 double xij = ntuple -> operator [] ( index );
00297 
00298                 index [0] = i+1;
00299                 double xi1j = ntuple -> operator [] ( index );
00300 
00301                 index[0] = i;
00302                 index[1] = j;
00303                 index[2] = dp::Y;
00304                 double yij = ntuple -> operator [] ( index );
00305 
00306                 index [1] = j+1;
00307                 double yij1 = ntuple -> operator [] ( index );
00308 
00309                 xh[0] = 0.50 * ( xij + xi1j );
00310                 yh[0] = 0.50 * ( yij + yij1 );
00311               }
00312               
00313               if ( h[m] > 0.0 ) {
00314                 sh[m] = 1;
00315               } 
00316 
00317               else if ( h[m] < 0.0 ) {
00318                 sh[m] = -1;
00319               } 
00320 
00321               else {
00322                 sh[m] = 0;
00323               }
00324             
00325             }
00326 
00327 //          // Note: at this stage the relative heights of the corners and the
00328 //          // centre are in the h array, and the corresponding coordinates are
00329 //          // in the xh and yh arrays. The centre of the box is indexed by 0
00330 //          // and the 4 corners by 1 to 4 as shown below.
00331 //          // Each triangle is then indexed by the parameter m, and the 3
00332 //          // vertices of each triangle are indexed by parameters m1,m2,and
00333 //          // m3.
00334 //          // It is assumed that the centre of the box is always vertex 2
00335 //          // though this isimportant only when all 3 vertices lie exactly on
00336 //          // the same contour level, in which case only the side of the box
00337 //          // is drawn.
00338 //          //
00339 //          //
00340 //          //      vertex 4 +-------------------+ vertex 3
00341 //          //               | \               / |
00342 //          //               |   \    m=3    /   |
00343 //          //               |     \       /     |
00344 //          //               |       \   /       |
00345 //          //               |  m=4    0   m=2   |       the centre is vertex 0
00346 //          //               |       /   \       |
00347 //          //               |     /       \     |
00348 //          //               |   /    m=1    \   |
00349 //          //               | /               \ |
00350 //          //      vertex 1 +-------------------+ vertex 2
00351             
00352             for (m=1;m<=4;m++) {
00353               
00354               m1 = m;
00355               m2 = 0;
00356               if (m!=4) {
00357                 m3 = m+1;
00358               } else {
00359                 m3 = 1;
00360               }
00361               
00362               case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1];
00363               
00364               if (case_value!=0) {
00365                 switch (case_value) {
00366                 case 1: // Line between vertices 1 and 2
00367                   x1=xh[m1];
00368                   y1=yh[m1];
00369                   x2=xh[m2];
00370                   y2=yh[m2];
00371                   break;
00372                 case 2: // Line between vertices 2 and 3
00373                   x1=xh[m2];
00374                   y1=yh[m2];
00375                   x2=xh[m3];
00376                   y2=yh[m3];
00377                   break;
00378                 case 3: // Line between vertices 3 and 1
00379                   x1=xh[m3];
00380                   y1=yh[m3];
00381                   x2=xh[m1];
00382                   y2=yh[m1];
00383                   break;
00384                 case 4: // Line between vertex 1 and side 2-3
00385                   x1=xh[m1];
00386                   y1=yh[m1];
00387                   x2=intersect(m2,m3,h,xh);
00388                   y2=intersect(m2,m3,h,yh);
00389                   break;
00390                 case 5: // Line between vertex 2 and side 3-1
00391                   x1=xh[m2];
00392                   y1=yh[m2];
00393                   x2=intersect(m3,m1,h,xh);
00394                   y2=intersect(m3,m1,h,yh);
00395                   break;
00396                 case 6: //  Line between vertex 3 and side 1-2
00397                   x1=xh[m3];
00398                   y1=yh[m3];
00399                   x2=intersect(m1,m2,h,xh);
00400                   y2=intersect(m1,m2,h,yh);
00401                   break;
00402                 case 7: // Line between sides 1-2 and 2-3
00403                   x1=intersect(m1,m2,h,xh);
00404                   y1=intersect(m1,m2,h,yh);
00405                   x2=intersect(m2,m3,h,xh);
00406                   y2=intersect(m2,m3,h,yh);
00407                   break;
00408                 case 8: // Line between sides 2-3 and 3-1
00409                   x1=intersect(m2,m3,h,xh);
00410                   y1=intersect(m2,m3,h,yh);
00411                   x2=intersect(m3,m1,h,xh);
00412                   y2=intersect(m3,m1,h,yh);
00413                   break;
00414                 case 9: // Line between sides 3-1 and 1-2
00415                   x1=intersect(m3,m1,h,xh);
00416                   y1=intersect(m3,m1,h,yh);
00417                   x2=intersect(m1,m2,h,xh);
00418                   y2=intersect(m1,m2,h,yh);
00419                   break;
00420                 default:
00421                   break;
00422                 }
00423                 
00424                 const Range & r = m_bin_to_color->getRange();
00425                 double val = curContour;
00426                 
00427                 const BinaryTransform * bt 
00428                   = dynamic_cast < const BinaryTransform * > ( transform );
00429                 bt -> transformZ ( val );
00430 
00431                 if ( ! r.excludes ( val ) ) {
00432                   
00433                   m_x.push_back ( x1 );
00434                   m_x.push_back ( x2 );
00435                   m_y.push_back ( y1 );
00436                   m_y.push_back ( y2 );
00437                 
00438                   // Pushing twice just to ensure symmetry.
00439                   Color color;
00440                   m_bin_to_color -> doubleToColor ( val, color );
00441                   m_colorvec.push_back ( color );
00442                   m_colorvec.push_back ( color );
00443                 }
00444               }
00445             }
00446           }
00447         }
00448       }
00449     }
00450   } 
00451 }
00452 
00455 double ContourPointRep::getContour ( int i, const TransformBase * transform  )
00456 {
00457   double high = m_maxValue;
00458   double low = m_minValue;
00459 
00460   double width = high - low;
00461   low = low + 0.05 * width;
00462   high = high - 0.05 * width;
00463 
00464 //   assert ( low > 0 );
00465 
00466   const BinaryTransform * t 
00467     = dynamic_cast < const BinaryTransform * > ( transform );
00468 
00469   t -> transformZ ( high );
00470   t -> transformZ ( low );
00471 
00472   double value = low + ( 
00473                         ( high - low ) * 
00474                         ((double)(i)) /
00475                         ((double)(m_numContours)) 
00476                         );
00477 
00478   t -> inverseTransformZ ( value );
00479 
00480   return value;
00481 
00482 }
00483 
00484 double ContourPointRep::intersect ( int p1, int p2, double * h, double * xh )
00485 {
00486   return (h[p2]*xh[p1]-h[p1]*xh[p2])/(h[p2]-h[p1]);
00487 }
00488 
00489 int ContourPointRep::getNumContours() const
00490 {
00491   return m_numContours;
00492 }
00493 
00494 void ContourPointRep::setNumContours ( int i )
00495 {
00496   m_numContours = i;
00497 }
00498 
00499 void ContourPointRep::setUsingUserValues ( bool flag )
00500 {
00501   m_usingUserValues = flag;
00502 }
00503 
00504 bool ContourPointRep::getUsingUserValues () const
00505 {
00506   return m_usingUserValues;
00507 }
00508 
00509 void
00510 ContourPointRep::
00511 setContourValues ( std::vector < double > & values,
00512                    ProjectorBase * proj )
00513 {
00514   
00515   m_usingUserValues = true;
00516   m_numContours = values.size();
00517   m_values.clear();
00518   m_values.reserve ( m_numContours );
00519 
00520   AxisModelBase * a = proj->getAxisModel ( Axes::Z );
00521   assert ( a );
00522   
00523   double sf = a->getScaleFactor();
00524   
00525   vector < double > :: iterator iter = values.begin ();
00526   for ( ; iter != values.end (); iter++ ) {
00527     m_values.push_back ( (*iter)/sf );
00528   }
00529   
00530 }
00531 
00532 void ContourPointRep::setContourVector ( const TransformBase * transform )
00533 {
00534   
00535   if ( m_usingUserValues ) return;
00536   
00537   m_values.clear();
00538   m_values.reserve ( m_numContours );
00539 
00540   for ( int i = 0; i < m_numContours; i++ ){
00541     m_values.push_back ( getContour ( i, transform ) );
00542   }
00543 
00544 }
00545 
00546 void
00547 ContourPointRep::
00548 drawProjectedValues ( const DataSource * ntuple,
00549                       TransformBase * transform,
00550                       ViewBase * view )
00551 {
00552   const Range & range = view -> getRange ( Axes::Z );
00553   double high = range.high();
00554   double low = range.low();
00555 
00556   const BinaryTransform * bt
00557     = dynamic_cast < const BinaryTransform * > ( transform );
00558 
00559   bt -> transformZ ( high );
00560   bt -> transformZ ( low );
00561 
00562   Range newrange ( low, high );
00563 
00564   m_bin_to_color->setRange ( newrange );
00565 
00566   m_x.clear();
00567   m_y.clear();
00568   m_colorvec.clear();
00569 
00570   unsigned int size = ntuple -> rows () * ntuple -> columns ();
00571   m_x.reserve ( size );
00572   m_y.reserve ( size );
00573   m_colorvec.reserve ( size );
00574 
00575   // Set the min and max values.
00576   setMinMax ( ntuple );
00577 
00578   // Set the contour values.
00579   setContourVector ( bt );
00580   
00581   // Do the contouring algorithm.
00582   createContours ( ntuple, bt );
00583   // Now you are ready to draw when you get endplot.
00584 
00585   endPlot ( *bt, *view, newrange );
00586 
00587 }
00588 
00589 void
00590 ContourPointRep::
00591 setMinMax ( const DataSource * ntuple )
00592 {
00593   const vector < double > & values = ntuple -> getColumn ( dp::Z );
00594   Range range ( values );
00595 
00596   m_minValue = range.low ();
00597   m_maxValue = range.high ();
00598 }

Generated for HippoDraw-1.14.8.5 by doxygen 1.4.3