00001
00012 #ifdef _MSC_VER
00013
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;
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
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
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
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
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
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
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
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 }