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

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

Generated for HippoDraw-1.14.8.5 by doxygen 1.4.3