LinePointRep.cxx
Go to the documentation of this file.
1 
12 #ifdef _MSC_VER
13 // include max() and min() missing from MicroSoft Visual C++
14 #include "msdevstudio/MSconfig.h"
15 #endif //_MSC_VER
16 
17 #include "LinePointRep.h"
18 
19 #include "axes/Range.h"
21 #include "datasrcs/DataSource.h"
22 #include "graphics/ViewBase.h"
24 
25 #include <cmath>
26 
27 using std::vector;
28 
29 using namespace hippodraw;
30 
32  : PointRepBase ( "Line", 1.0 ),
33  m_line_style ( Line::Solid )
34 {
35 }
36 
38 LinePointRep ( const char * name, float size )
39  : PointRepBase ( name, size ),
40  m_line_style ( Line::Solid )
41 {
42 }
43 
45  : PointRepBase ( "Line", size ),
46  m_line_style ( Line::Solid )
47 {
48 }
49 
51  : PointRepBase ( point_rep ),
52  m_line_style ( point_rep.m_line_style )
53 {
54 }
55 
57 {
58 }
59 
61 {
62  return new LinePointRep( *this );
63 }
64 
65 void
67 setStyle ( unsigned int style )
68 {
69  m_line_style = Line::convert ( style );
70 }
71 
72 unsigned int
74 getStyle ( ) const
75 {
76  return m_line_style;
77 }
78 
79 namespace dp = hippodraw::DataPoint2DTuple;
80 
81 void
83 transformValues ( const DataSource * ntuple, TransformBase * transform )
84 {
85  unsigned int size = ntuple -> rows ();
86  if ( size == 0 ) return;
87 
88  m_x.clear();
89  m_y.clear();
90 
91  m_x.reserve ( size );
92  m_y.reserve ( size );
93 
94  unsigned int i = 0; // for VC++ 7.1
95  for ( ; i < size; i++ ) {
96  const vector < double > & row = ntuple -> getRow ( i );
97  double x = row [ dp::X ];
98  double y = row [ dp::Y ];
99  m_x.push_back ( x );
100  m_y.push_back ( y );
101  }
102  const BinaryTransform * t
103  = dynamic_cast < const BinaryTransform * > ( transform );
104 
105  t -> transform ( m_x, m_y );
106 }
107 
108 void
111  TransformBase * transform,
112  ViewBase * view )
113 {
114  transformValues ( ntuple, transform );
115  drawValues ( view );
116 }
117 
118 void
121 {
122  unsigned int size = m_x.size ();
123  if ( size == 0 ) return;
124 
125  m_user_rect = &(view -> getUserRect ());
126 
127  vector < double > x;
128  vector < double > y;
129  x.reserve ( size );
130  y.reserve ( size );
131 
132  const Color & cur_color = color();
133 
134  m_xmin = m_user_rect->getX ();
136  m_ymin = m_user_rect->getY ();
138 
139  // Plot each interval and truncate at the boundaries.
140  unsigned int i = 0;
141  std::vector<double>::const_iterator ix = m_x.begin();
142  std::vector<double>::const_iterator iy = m_y.begin();
143  bool isCorner(false);
144  std::vector<double> xcorner;
145  std::vector<double> ycorner;
146 
147  while (i < size-1) {
148  if (outside_box(ix, iy)) {
149  if (!x.empty()) {
150  view -> drawPolyLine ( x, y, m_line_style, cur_color, m_size );
151  }
152  x.clear();
153  y.clear();
154  if (isCorner) {
155  view -> drawPolyLine ( xcorner, ycorner, m_line_style,
156  cur_color, m_size );
157  }
158  } else {
159  isCorner = cornerCase(ix, iy, xcorner, ycorner);
160  if (!isCorner) {
161  addEndPoints(ix, iy, x, y);
162  }
163  }
164  ++i;
165  ++ix;
166  ++iy;
167  }
168  if (!x.empty()) {
169  view -> drawPolyLine ( x, y, m_line_style, cur_color, m_size );
170  }
171 }
172 
173 bool LinePointRep::
174 outside_box(std::vector<double>::const_iterator ix,
175  std::vector<double>::const_iterator iy) const {
176  return ( (*ix <= m_xmin && *(ix+1) <= m_xmin) ||
177  (*ix >= m_xmax && *(ix+1) >= m_xmax) ||
178  (*iy <= m_ymin && *(iy+1) <= m_ymin) ||
179  (*iy >= m_ymax && *(iy+1) >= m_ymax) );
180 }
181 
182 bool LinePointRep::
183 straddles_x_boundary(std::vector<double>::const_iterator ix,
184  std::vector<double>::const_iterator iy,
185  Point & pt1, Point & pt2,
186  double & distance) const {
187  if ( outside_box(ix, iy) ||
188  (*ix >= m_xmin && *(ix+1) >= m_xmin &&
189  *ix <= m_xmax && *(ix+1) <= m_xmax) ) {
190  return false;
191  }
192  // Treat case if interval straddles both boundaries.
193  if (*ix < m_xmin && *(ix+1) > m_xmax) {
194  pt1.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
195  pt2.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
196  } else if (*ix > m_xmax && *(ix+1) < m_xmin) {
197  pt1.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
198  pt2.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
199  }
200  // Interval straddles lower boundary.
201  else if (*ix < m_xmin && *(ix+1) > m_xmin) {
202  pt1.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
203  pt2.setPoint(*(ix+1), *(iy+1));
204  } else if (*ix > m_xmin && *(ix+1) < m_xmin) {
205  pt1.setPoint(*ix, *iy);
206  pt2.setPoint(m_xmin, interpolate(m_xmin, ix, iy));
207  }
208  // Interval straddles upper boundary.
209  else if (*ix < m_xmax && *(ix+1) > m_xmax) {
210  pt1.setPoint(*ix, *iy);
211  pt2.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
212  } else if (*ix > m_xmax && *(ix+1) < m_xmax) {
213  pt1.setPoint(m_xmax, interpolate(m_xmax, ix, iy));
214  pt2.setPoint(*(ix+1), *(iy+1));
215  }
216  distance = separation(pt1, pt2);
217  return true;
218 }
219 
220 bool LinePointRep::
221 straddles_y_boundary(std::vector<double>::const_iterator ix,
222  std::vector<double>::const_iterator iy,
223  Point & pt1, Point & pt2,
224  double & distance) const {
225  if ( outside_box(ix, iy) ||
226  (*iy >= m_ymin && *(iy+1) >= m_ymin &&
227  *iy <= m_ymax && *(iy+1) <= m_ymax) ) {
228  return false;
229  }
230  // Treat case if interval straddles both boundaries.
231  if (*iy < m_ymin && *(iy+1) > m_ymax) {
232  pt1.setPoint(interpolate(m_ymin, iy, ix), m_ymin);
233  pt2.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
234  } else if (*iy > m_ymax && *(iy+1) < m_ymin) {
235  pt1.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
236  pt2.setPoint(interpolate(m_ymin, iy, ix), m_ymin);
237  }
238  // Interval straddles lower boundary.
239  else if (*iy < m_ymin && *(iy+1) > m_ymin) {
240  pt1.setPoint(interpolate(m_ymin, iy, ix), m_ymin );
241  pt2.setPoint(*(ix+1), *(iy+1));
242  } else if (*iy > m_ymin && *(iy+1) < m_ymin) {
243  pt1.setPoint(*ix, *iy);
244  pt2.setPoint(interpolate(m_ymin, iy, ix), m_ymin);
245  }
246  // Interval straddles upper boundary.
247  else if (*iy < m_ymax && *(iy+1) > m_ymax) {
248  pt1.setPoint(*ix, *iy);
249  pt2.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
250  } else if (*iy > m_ymax && *(iy+1) < m_ymax) {
251  pt1.setPoint(interpolate(m_ymax, iy, ix), m_ymax);
252  pt2.setPoint(*(ix+1), *(iy+1));
253  }
254  distance = separation(pt1, pt2);
255  return true;
256 }
257 
258 double LinePointRep::
259 interpolate(double x, std::vector<double>::const_iterator ix,
260  std::vector<double>::const_iterator iy) const {
261  return (x - *ix)/(*(ix+1) - *ix)*(*(iy+1) - *iy) + *iy;
262 }
263 
264 double LinePointRep::
265 separation(const Point & pt1, const Point & pt2) const {
266  return sqrt( (pt1.getX() - pt2.getX())*(pt1.getX() - pt2.getX()) +
267  (pt1.getY() - pt2.getY())*(pt1.getY() - pt2.getY()) );
268 }
269 
270 void LinePointRep::
271 addEndPoints(std::vector<double>::const_iterator ix,
272  std::vector<double>::const_iterator iy,
273  std::vector<double> & x, std::vector<double> & y) const {
274  Point pt1, pt2;
275  findEndPoints(ix, iy, pt1, pt2);
276  if (m_user_rect->isInBounds((pt1.getX() + pt2.getX())/2.,
277  (pt1.getY() + pt2.getY())/2.) ) {
278  x.push_back(pt1.getX());
279  y.push_back(pt1.getY());
280  x.push_back(pt2.getX());
281  y.push_back(pt2.getY());
282  }
283 }
284 
285 void LinePointRep::
286 findEndPoints(std::vector<double>::const_iterator ix,
287  std::vector<double>::const_iterator iy,
288  Point & pt1, Point & pt2) const {
289  Point xpt1, xpt2, ypt1, ypt2;
290  double xdist, ydist;
291  bool xstrad = straddles_x_boundary(ix, iy, xpt1, xpt2, xdist);
292  bool ystrad = straddles_y_boundary(ix, iy, ypt1, ypt2, ydist);
293  if (xstrad || ystrad) {
294  if ( (xstrad && ystrad && xdist < ydist) || xstrad ) {
295  pt1 = xpt1;
296  pt2 = xpt2;
297  } else if ( (xstrad && ystrad && xdist > ydist) || ystrad ) {
298  pt1 = ypt1;
299  pt2 = ypt2;
300  }
301  } else {
302  pt1.setPoint(*ix, *iy);
303  pt2.setPoint(*(ix+1), *(iy+1));
304  }
305 }
306 
307 bool LinePointRep::
308 cornerCase(std::vector<double>::const_iterator ix,
309  std::vector<double>::const_iterator iy,
310  std::vector<double> & x, std::vector<double> & y) const {
311  Point xpt1, xpt2, ypt1, ypt2;
312  double dist;
313  bool xstrad = straddles_x_boundary(ix, iy, xpt1, xpt2, dist);
314  bool ystrad = straddles_y_boundary(ix, iy, ypt1, ypt2, dist);
315  if (!m_user_rect->isInBounds(*ix, *iy) &&
316  !m_user_rect->isInBounds(*(ix+1), *(iy+1)) &&
317  xstrad && ystrad) {
318  x.clear();
319  y.clear();
320  if (xpt1.getX() == m_xmin || xpt1.getX() == m_xmax) {
321  x.push_back(xpt1.getX());
322  y.push_back(xpt1.getY());
323  } else {
324  x.push_back(xpt2.getX());
325  y.push_back(xpt2.getY());
326  }
327  if (ypt1.getY() == m_ymin || ypt1.getY() == m_ymax) {
328  x.push_back(ypt1.getX());
329  y.push_back(ypt1.getY());
330  } else {
331  x.push_back(ypt2.getX());
332  y.push_back(ypt2.getY());
333  }
334  if ( m_user_rect->isInBounds(x[0], y[0]) &&
335  m_user_rect->isInBounds(x[1], y[1]) ) {
336  return true;
337  } else {
338  return false;
339  }
340  }
341  return false;
342 }
343 
344 bool
346 uses ( Line::Style ) const
347 {
348  return true;
349 }

Generated for HippoDraw Class Library by doxygen