Engauge Digitizer  2
Public Member Functions | Friends | List of all members
SplineDrawer Class Reference

This class takes the output from Spline and uses that to draw the curve in the graphics window, as a sequence of moves and draws. More...

#include <SplineDrawer.h>

Collaboration diagram for SplineDrawer:
Collaboration graph

Public Member Functions

 SplineDrawer (const Transformation &transformation)
 Single constructor. More...
 
void bindToSpline (const LineStyle &lineStyle, int numSegments, const Spline &spline)
 Analyze each segment in the Spline. More...
 
bool segmentIsMultiValued (const Spline &spline, int numSegments, int segment) const
 Return true if specified segment is multi-valued, else false. More...
 
SplineDrawerOperation segmentOperation (int segment) const
 Indicate if, and how, segment is to be drawn. More...
 

Friends

class TestSplineDrawer
 

Detailed Description

This class takes the output from Spline and uses that to draw the curve in the graphics window, as a sequence of moves and draws.

The moves and draws by themselves would be trivial (move,draw,draw,draw...) but this actually draws, when needed, differently styled curve segments to indicate each curve segment should be CONNECT_AS_FUNCTION_SMOOTH but actually is not single-valued (=not a function)

This class is aware of the Transformation, unlike the Spline class which is decoupled from that for simplicity. Specifically, this class converts the screen coordinates to graph coordinates to check for single-valuedness.

The algorithm used here has to work in cartesian, polar, linear and/or log coordinates. This requirement, along with the goal of keeping the Spline class simple, pretty much requires using the Transformation and working in graph coordinates.

Definition at line 35 of file SplineDrawer.h.

Constructor & Destructor Documentation

◆ SplineDrawer()

SplineDrawer::SplineDrawer ( const Transformation transformation)

Single constructor.

Definition at line 13 of file SplineDrawer.cpp.

13  :
14  m_transformation (transformation)
15 {
16 }

Member Function Documentation

◆ bindToSpline()

void SplineDrawer::bindToSpline ( const LineStyle lineStyle,
int  numSegments,
const Spline spline 
)

Analyze each segment in the Spline.

Definition at line 18 of file SplineDrawer.cpp.

21 {
22  m_segmentOperations.resize (numSegments);
23 
24  // Loop through segments to get move/draw choice. We do not need to worry about
25  // applying a move (versus a draw) for the first segment since that first point
26  // is handled by external code
27  for (int segment = 0; segment < numSegments; segment++) {
28 
29  bool itsAKeeper = true;
30  if (m_transformation.transformIsDefined()) {
31 
32  // We have the graph<->screen transformation so let's use it. Could there be an ambiguity issue?
33  if ((lineStyle.curveConnectAs() == CONNECT_AS_FUNCTION_SMOOTH) &&
34  segmentIsMultiValued (spline,
35  numSegments,
36  segment)) {
37  itsAKeeper = false;
38  }
39 
40  // Invisible or visible?
41  m_segmentOperations [segment] = (itsAKeeper ?
44  }
45  }
46 }
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition: LineStyle.cpp:63
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
bool segmentIsMultiValued(const Spline &spline, int numSegments, int segment) const
Return true if specified segment is multi-valued, else false.

◆ segmentIsMultiValued()

bool SplineDrawer::segmentIsMultiValued ( const Spline spline,
int  numSegments,
int  segment 
) const

Return true if specified segment is multi-valued, else false.

Definition at line 48 of file SplineDrawer.cpp.

51 {
52  ENGAUGE_ASSERT (m_transformation.transformIsDefined());
53 
54  if (segment < numSegments - 1) {
55 
56  // Not at very end
57  double tI = double (segment);
58  double tIp1 = double (segment + 1);
59 
60  // Compute number of pixels between endpoints
61  SplinePair posScreenStart = spline.interpolateCoeff (tI);
62  SplinePair posScreenEnd = spline.interpolateCoeff (tIp1);
63 
64  int deltaX = qFloor (posScreenEnd.x() - posScreenStart.x());
65  int deltaY = qFloor (posScreenEnd.y() - posScreenStart.y());
66  double pixelDistance = qSqrt (deltaX * deltaX + deltaY * deltaY);
67  double numSteps = pixelDistance;
68 
69  // Search through a sufficiently large number of points to verify single-valuedness
70  double tIDelta = 1.0 / numSteps;
71  for (int itI = 1; itI < numSteps - 1; itI++) {
72 
73  double tIm1 = segment + (itI - 1) * tIDelta;
74  double tI = segment + (itI ) * tIDelta;
75  double tIp1 = segment + (itI + 1) * tIDelta;
76 
77  SplinePair spBefore = spline.interpolateCoeff (tIm1);
78  SplinePair spCurrent = spline.interpolateCoeff (tI);
79  SplinePair spAfter = spline.interpolateCoeff (tIp1);
80 
81  QPointF posScreenBefore (spBefore.x(), spBefore.y());
82  QPointF posScreenCurrent (spCurrent.x(), spCurrent.y());
83  QPointF posScreenAfter (spAfter.x(), spAfter.y());
84 
85  QPointF posGraphBefore, posGraphCurrent, posGraphAfter;
86  m_transformation.transformScreenToRawGraph (posScreenBefore,
87  posGraphBefore);
88  m_transformation.transformScreenToRawGraph (posScreenCurrent,
89  posGraphCurrent);
90  m_transformation.transformScreenToRawGraph (posScreenAfter,
91  posGraphAfter);
92 
93  // In between the start and end points we look for deltaXBefore>0 and deltaXAfter<0,
94  // or deltaXBefore<0 and deltaXAfter>0, either of those two cases indicates multi-valued
95  double deltaXBefore = posGraphCurrent.x() - posGraphBefore.x();
96  double deltaXAfter = posGraphAfter.x() - posGraphCurrent.x();
97 
98  if ((deltaXBefore > 0 && deltaXAfter < 0) ||
99  (deltaXBefore < 0 && deltaXAfter > 0)) {
100 
101  // Multi-valued
102  return true;
103  }
104  }
105  }
106 
107  return false;
108 }
SplinePair interpolateCoeff(double t) const
Return interpolated y for specified x.
Definition: Spline.cpp:233
double y() const
Get method for y.
Definition: SplinePair.cpp:88
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
double x() const
Get method for x.
Definition: SplinePair.cpp:83
Single X/Y pair for cubic spline interpolation initialization and calculations.
Definition: SplinePair.h:13
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...
Definition: EngaugeAssert.h:20

◆ segmentOperation()

SplineDrawerOperation SplineDrawer::segmentOperation ( int  segment) const

Indicate if, and how, segment is to be drawn.

Definition at line 110 of file SplineDrawer.cpp.

111 {
112  if (segment < m_segmentOperations.count()) {
113  return m_segmentOperations.at (segment);
114  } else {
116  }
117 }

Friends And Related Function Documentation

◆ TestSplineDrawer

friend class TestSplineDrawer
friend

Definition at line 38 of file SplineDrawer.h.


The documentation for this class was generated from the following files: