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