LinePointRep.cxx

Go to the documentation of this file.
00001 
00012 #ifdef _MSC_VER
00013 // include max() and min() missing from MicroSoft Visual C++
00014 #include "msdevstudio/MSconfig.h"
00015 #endif //_MSC_VER
00016 
00017 #include "LinePointRep.h"
00018 
00019 #include "axes/Range.h"
00020 #include "datasrcs/DataPointTuple.h"
00021 #include "datasrcs/DataSource.h"
00022 #include "graphics/ViewBase.h"
00023 #include "transforms/BinaryTransform.h"
00024 
00025 #include <cmath>
00026 
00027 using std::vector;
00028 
00029 using namespace hippodraw;
00030 
00031 LinePointRep::LinePointRep ()
00032   : PointRepBase ( "Line", 1.0 ),
00033     m_line_style ( Line::Solid )
00034 {
00035 }
00036 
00037 LinePointRep::
00038 LinePointRep ( const char * name, float size )
00039   : PointRepBase ( name, size ),
00040     m_line_style ( Line::Solid )
00041 {
00042 }
00043 
00044 LinePointRep::LinePointRep ( float size )
00045   : PointRepBase ( "Line", size ),
00046     m_line_style ( Line::Solid )
00047 {
00048 }
00049 
00050 LinePointRep::LinePointRep ( const LinePointRep & point_rep )
00051   : PointRepBase ( point_rep ), 
00052     m_line_style ( point_rep.m_line_style )
00053 {
00054 }
00055 
00056 LinePointRep::~LinePointRep ()
00057 {
00058 }
00059 
00060 RepBase * LinePointRep::clone()
00061 {
00062   return new LinePointRep( *this );
00063 }
00064 
00065 void
00066 LinePointRep::
00067 setStyle ( unsigned int style )
00068 {
00069   m_line_style = Line::convert ( style );
00070 }
00071 
00072 unsigned int
00073 LinePointRep::
00074 getStyle ( ) const
00075 {
00076   return m_line_style;
00077 }
00078 
00079 namespace dp = hippodraw::DataPoint2DTuple;
00080 
00081 void
00082 LinePointRep::
00083 transformValues ( const DataSource * ntuple, TransformBase * transform )
00084 {
00085   unsigned int size = ntuple -> rows ();
00086   if ( size == 0 ) return;
00087 
00088   m_x.clear();
00089   m_y.clear();
00090 
00091   m_x.reserve ( size );
00092   m_y.reserve ( size );
00093 
00094   unsigned int i = 0; // for VC++ 7.1
00095   for ( ; i < size; i++ ) {
00096     const vector < double > & row = ntuple -> getRow ( i );
00097     double x = row [ dp::X ];    
00098     double y = row [ dp::Y ];
00099     m_x.push_back ( x );
00100     m_y.push_back ( y );
00101   }
00102   const BinaryTransform * t
00103     = dynamic_cast < const BinaryTransform * > ( transform );
00104 
00105   t -> transform ( m_x, m_y );
00106 }
00107 
00108 void
00109 LinePointRep::
00110 drawProjectedValues ( const DataSource * ntuple,
00111                       TransformBase * transform,
00112                       ViewBase * view )
00113 {
00114   transformValues ( ntuple, transform );
00115   drawValues ( view );
00116 }
00117 
00118 void
00119 LinePointRep::
00120 drawValues ( ViewBase * view )
00121 {
00122   unsigned int size = m_x.size ();
00123   if ( size == 0 ) return;
00124 
00125   m_user_rect = &(view -> getUserRect ());
00126 
00127   vector < double > x;
00128   vector < double > y;
00129   x.reserve ( size );
00130   y.reserve ( size );
00131 
00132   const Color & cur_color = color();
00133 
00134   m_xmin = m_user_rect->getX ();
00135   m_xmax = m_xmin + m_user_rect->getWidth ();
00136   m_ymin = m_user_rect->getY ();
00137   m_ymax = m_ymin + m_user_rect->getHeight ();
00138 
00139   // Plot each interval and truncate at the boundaries.
00140   unsigned int i = 0;
00141   std::vector<double>::const_iterator ix = m_x.begin();
00142   std::vector<double>::const_iterator iy = m_y.begin();
00143   bool isCorner(false);
00144   std::vector<double> xcorner;
00145   std::vector<double> ycorner;
00146 
00147   while (i < size-1) {
00148      if (outside_box(ix, iy)) {
00149         if (!x.empty()) {
00150            view -> drawPolyLine ( x, y, m_line_style, cur_color, m_size );
00151         }
00152         x.clear();
00153         y.clear();
00154         if (isCorner) {
00155            view -> drawPolyLine ( xcorner, ycorner, m_line_style,
00156                                   cur_color, m_size );
00157         }
00158      } else {
00159         isCorner = cornerCase(ix, iy, xcorner, ycorner);
00160         if (!isCorner) {
00161            addEndPoints(ix, iy, x, y);
00162         }
00163      }
00164      ++i;
00165      ++ix;
00166      ++iy;
00167   }
00168   if (!x.empty()) {
00169      view -> drawPolyLine ( x, y, m_line_style, cur_color, m_size );
00170   }
00171 }
00172 
00173 bool LinePointRep::
00174 outside_box(std::vector<double>::const_iterator ix,
00175             std::vector<double>::const_iterator iy) const {
00176    return ( (*ix <= m_xmin && *(ix+1) <= m_xmin) || 
00177             (*ix >= m_xmax && *(ix+1) >= m_xmax) ||
00178             (*iy <= m_ymin && *(iy+1) <= m_ymin) || 
00179             (*iy >= m_ymax && *(iy+1) >= m_ymax) );
00180 }
00181 
00182 bool LinePointRep::
00183 straddles_x_boundary(std::vector<double>::const_iterator ix,
00184                      std::vector<double>::const_iterator iy,
00185                      Point & pt1, Point & pt2,
00186                      double & distance) const {
00187    if ( outside_box(ix, iy) || 
00188         (*ix >= m_xmin && *(ix+1) >= m_xmin && 
00189          *ix <= m_xmax && *(ix+1) <= m_xmax) ) {
00190       return false;
00191    }
00192    // Treat case if interval straddles both boundaries.
00193    if (*ix < m_xmin && *(ix+1) > m_xmax) { 
00194       pt1.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
00195       pt2.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
00196    } else if (*ix > m_xmax && *(ix+1) < m_xmin) {
00197       pt1.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
00198       pt2.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
00199    }
00200    // Interval straddles lower boundary.
00201    else if (*ix < m_xmin && *(ix+1) > m_xmin) {
00202       pt1.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
00203       pt2.setPoint(*(ix+1), *(iy+1));
00204    } else if (*ix > m_xmin && *(ix+1) < m_xmin) {
00205       pt1.setPoint(*ix, *iy);
00206       pt2.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
00207    }
00208    // Interval straddles upper boundary.
00209    else if (*ix < m_xmax && *(ix+1) > m_xmax) {
00210       pt1.setPoint(*ix, *iy);
00211       pt2.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
00212    } else if (*ix > m_xmax && *(ix+1) < m_xmax) {
00213       pt1.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
00214       pt2.setPoint(*(ix+1), *(iy+1));
00215    }
00216    distance = separation(pt1, pt2);
00217    return true;
00218 }
00219 
00220 bool LinePointRep::
00221 straddles_y_boundary(std::vector<double>::const_iterator ix,
00222                      std::vector<double>::const_iterator iy,
00223                      Point & pt1, Point & pt2,
00224                      double & distance) const {
00225    if ( outside_box(ix, iy) || 
00226         (*iy >= m_ymin && *(iy+1) >= m_ymin && 
00227          *iy <= m_ymax && *(iy+1) <= m_ymax) ) {
00228       return false;
00229    }
00230    // Treat case if interval straddles both boundaries.
00231    if (*iy < m_ymin && *(iy+1) > m_ymax) { 
00232       pt1.setPoint(interpolate(m_ymin, iy, ix), m_ymin);
00233       pt2.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
00234    } else if (*iy > m_ymax && *(iy+1) < m_ymin) {
00235       pt1.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
00236       pt2.setPoint(interpolate(m_ymin, iy, ix), m_ymin);
00237    } 
00238    // Interval straddles lower boundary.
00239    else if (*iy < m_ymin && *(iy+1) > m_ymin) {
00240       pt1.setPoint(interpolate(m_ymin, iy, ix), m_ymin );
00241       pt2.setPoint(*(ix+1), *(iy+1));
00242    } else if (*iy > m_ymin && *(iy+1) < m_ymin) {
00243       pt1.setPoint(*ix, *iy);
00244       pt2.setPoint(interpolate(m_ymin, iy, ix), m_ymin);
00245    }
00246    // Interval straddles upper boundary.
00247    else if (*iy < m_ymax && *(iy+1) > m_ymax) {
00248       pt1.setPoint(*ix, *iy);
00249       pt2.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
00250    } else if (*iy > m_ymax && *(iy+1) < m_ymax) {
00251       pt1.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
00252       pt2.setPoint(*(ix+1), *(iy+1));
00253    }
00254    distance = separation(pt1, pt2);
00255    return true;
00256 }
00257 
00258 double LinePointRep::
00259 interpolate(double x, std::vector<double>::const_iterator ix,
00260             std::vector<double>::const_iterator iy) const {
00261    return (x - *ix)/(*(ix+1) - *ix)*(*(iy+1) - *iy) + *iy;
00262 }
00263 
00264 double LinePointRep::
00265 separation(const Point & pt1, const Point & pt2) const {
00266    return sqrt( (pt1.getX() - pt2.getX())*(pt1.getX() - pt2.getX()) + 
00267                 (pt1.getY() - pt2.getY())*(pt1.getY() - pt2.getY()) );
00268 }
00269 
00270 void LinePointRep::
00271 addEndPoints(std::vector<double>::const_iterator ix,
00272              std::vector<double>::const_iterator iy,
00273              std::vector<double> & x, std::vector<double> & y) const {
00274    Point pt1, pt2;
00275    findEndPoints(ix, iy, pt1, pt2);
00276    if (m_user_rect->isInBounds((pt1.getX() + pt2.getX())/2.,
00277                                (pt1.getY() + pt2.getY())/2.) ) {
00278       x.push_back(pt1.getX());
00279       y.push_back(pt1.getY());
00280       x.push_back(pt2.getX());
00281       y.push_back(pt2.getY());
00282    }
00283 }
00284 
00285 void LinePointRep::
00286 findEndPoints(std::vector<double>::const_iterator ix,
00287               std::vector<double>::const_iterator iy,
00288               Point & pt1, Point & pt2) const {
00289    Point xpt1, xpt2, ypt1, ypt2;
00290    double xdist, ydist;
00291    bool xstrad = straddles_x_boundary(ix, iy, xpt1, xpt2, xdist);
00292    bool ystrad = straddles_y_boundary(ix, iy, ypt1, ypt2, ydist);
00293    if (xstrad || ystrad) {
00294       if ( (xstrad && ystrad && xdist < ydist) || xstrad ) {
00295          pt1 = xpt1;
00296          pt2 = xpt2;
00297       } else if ( (xstrad && ystrad && xdist > ydist) || ystrad ) {
00298          pt1 = ypt1;
00299          pt2 = ypt2;
00300       }
00301    } else {
00302       pt1.setPoint(*ix, *iy);
00303       pt2.setPoint(*(ix+1), *(iy+1));
00304    }
00305 }
00306 
00307 bool LinePointRep::
00308 cornerCase(std::vector<double>::const_iterator ix,
00309            std::vector<double>::const_iterator iy, 
00310            std::vector<double> & x, std::vector<double> & y) const {
00311    Point xpt1, xpt2, ypt1, ypt2;
00312    double dist;
00313    bool xstrad = straddles_x_boundary(ix, iy, xpt1, xpt2, dist);
00314    bool ystrad = straddles_y_boundary(ix, iy, ypt1, ypt2, dist);
00315    if (!m_user_rect->isInBounds(*ix, *iy) &&
00316        !m_user_rect->isInBounds(*(ix+1), *(iy+1)) &&
00317        xstrad && ystrad) {
00318       x.clear();
00319       y.clear();
00320       if (xpt1.getX() == m_xmin || xpt1.getX() == m_xmax) {
00321          x.push_back(xpt1.getX());
00322          y.push_back(xpt1.getY());
00323       } else {
00324          x.push_back(xpt2.getX());
00325          y.push_back(xpt2.getY());
00326       }
00327       if (ypt1.getY() == m_ymin || ypt1.getY() == m_ymax) {
00328          x.push_back(ypt1.getX());
00329          y.push_back(ypt1.getY());
00330       } else {
00331          x.push_back(ypt2.getX());
00332          y.push_back(ypt2.getY());
00333       }
00334       if ( m_user_rect->isInBounds(x[0], y[0]) &&
00335            m_user_rect->isInBounds(x[1], y[1]) ) {
00336          return true;
00337       } else {
00338          return false;
00339       }
00340    }
00341    return false;
00342 }
00343 
00344 bool
00345 LinePointRep::
00346 uses ( Line::Style ) const
00347 {
00348   return true;
00349 }

Generated for HippoDraw Class Library by doxygen