Engauge Digitizer  2
CallbackAxisPointsAbstract.cpp
1 #include "CallbackAxisPointsAbstract.h"
2 #include "EngaugeAssert.h"
3 #include "Logger.h"
4 #include "Point.h"
5 #include <qmath.h>
6 #include "QtToString.h"
7 #include "Transformation.h"
8 
10  m_modelCoords (modelCoords),
11  m_numberAxisPoints (0),
12  m_isError (false)
13 {
14 }
15 
17  const QString pointIdentifierOverride,
18  const QPointF &posScreenOverride,
19  const QPointF &posGraphOverride) :
20  m_modelCoords (modelCoords),
21  m_pointIdentifierOverride (pointIdentifierOverride),
22  m_posScreenOverride (posScreenOverride),
23  m_posGraphOverride (posGraphOverride),
24  m_numberAxisPoints (0),
25  m_isError (false)
26 {
27 }
28 
29 bool CallbackAxisPointsAbstract::anyColumnsRepeat (double m [3] [3], int numberColumns)
30 {
31  for (int colLeft = 0; colLeft < numberColumns; colLeft++) {
32  for (int colRight = colLeft + 1; colRight < numberColumns; colRight++) {
33 
34  if ((m [0] [colLeft] == m [0] [colRight]) &&
35  (m [1] [colLeft] == m [1] [colRight]) &&
36  (m [2] [colLeft] == m [2] [colRight])) {
37 
38  // Columns colLeft and colRight repeat each other, which means matrix cannot be inverted
39  return true;
40  }
41  }
42  }
43 
44  // No columns repeat
45  return false;
46 }
47 
49  const Point &point)
50 {
52 
53  if (m_numberAxisPoints < 3) {
54 
55  QPointF posScreen = point.posScreen ();
56  QPointF posGraph = point.posGraph ();
57 
58  if (m_pointIdentifierOverride == point.identifier ()) {
59 
60  // Override the old point coordinates with its new (if all tests are passed) coordinates
61  posScreen = m_posScreenOverride;
62  posGraph = m_posGraphOverride;
63  }
64 
65  // Update range variables
66  if ((m_numberAxisPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
67  if ((m_numberAxisPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
68  if ((m_numberAxisPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
69  if ((m_numberAxisPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
70 
71  // Append one new column to each of the screen and graph coordinate matrices. Since QTransform::setTransform
72  // deals with an entire array instead of element by element, we copy the QTransform arrays here, modify them,
73  // and then copy them back. The local arrays are also handy for error checking
74 
75  double sm [3] [3] = {
76  {m_screenInputs.m11 (), m_screenInputs.m12 (), m_screenInputs.m13 ()},
77  {m_screenInputs.m21 (), m_screenInputs.m22 (), m_screenInputs.m23 ()},
78  {m_screenInputs.m31 (), m_screenInputs.m32 (), m_screenInputs.m33 ()}};
79  double gm [3] [3] = {
80  {m_graphOutputs.m11 (), m_graphOutputs.m12 (), m_graphOutputs.m13 ()},
81  {m_graphOutputs.m21 (), m_graphOutputs.m22 (), m_graphOutputs.m23 ()},
82  {m_graphOutputs.m31 (), m_graphOutputs.m32 (), m_graphOutputs.m33 ()}};
83 
84  // Screen coordinates
85  sm [0] [m_numberAxisPoints] = posScreen.x ();
86  sm [1] [m_numberAxisPoints] = posScreen.y ();
87  sm [2] [m_numberAxisPoints] = 1.0;
88 
89  // Graph coordinates
90  gm [0] [m_numberAxisPoints] = posGraph.x ();
91  gm [1] [m_numberAxisPoints] = posGraph.y ();
92  gm [2] [m_numberAxisPoints] = 1.0;
93 
94  // Save screen matrix
95  m_screenInputs.setMatrix (sm [0] [0], sm [0] [1], sm [0] [2],
96  sm [1] [0], sm [1] [1], sm [1] [2],
97  sm [2] [0], sm [2] [1], sm [2] [2]);
98 
99  // Save graph matrix. These are the raw graph coordinates, which means they may be polar coordinates
100  // and/or have log scaling, since Transformation converts raw to linear cartesian cooordinates
101  m_graphOutputs.setMatrix (gm [0] [0], gm [0] [1], gm [0] [2],
102  gm [1] [0], gm [1] [1], gm [1] [2],
103  gm [2] [0], gm [2] [1], gm [2] [2]);
104 
105  ++m_numberAxisPoints; // Update this number before calling anyColumnsRepeat and threePointsAreCollinear
106 
107  // Error checking
108  if (anyColumnsRepeat (sm, m_numberAxisPoints)) {
109 
110  m_isError = true;
111  m_errorMessage = "New axis point cannot be at the same screen position as an exisiting axis point";
113 
114  } else if (anyColumnsRepeat (gm, m_numberAxisPoints)) {
115 
116  m_isError = true;
117  m_errorMessage = "New axis point cannot have the same graph coordinates as an existing axis point";
119 
120  } else if (threePointsAreCollinear (sm, m_numberAxisPoints)) {
121 
122  m_isError = true;
123  m_errorMessage = "No more than two axis points can lie along the same line on the screen";
125 
126  } else if (threePointsAreCollinear (gm, m_numberAxisPoints)) {
127 
128  m_isError = true;
129  m_errorMessage = "No more than two axis points can lie along the same line in graph coordinates";
131 
132  }
133  }
134 
135  if (m_numberAxisPoints > 2) {
136 
137  // There are enough axis points
139 
140  }
141 
142  return rtn;
143 }
144 
146 {
147  return m_graphOutputs;
148 }
149 
151 {
152  return m_screenInputs;
153 }
154 
155 bool CallbackAxisPointsAbstract::threePointsAreCollinear (double m [3] [3], int numberColumns)
156 {
157  if (numberColumns == 3) {
158 
159  // Compute determinant to determine if the three points are collinear
160  QTransform t (
161  m [0] [0], m [0] [1], m [0] [2],
162  m [1] [0], m [1] [1], m [1] [2],
163  m [2] [0], m [2] [1], m [2] [2]);
164 
165  return (t.determinant() == 0);
166  }
167 
168  return false;
169 }
QPointF posGraph(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Accessor for graph position. Skip check if copying one instance to another.
Definition: Point.cpp:333
QTransform matrixGraph() const
Returns graph coordinates matrix after transformIsDefined has already indicated success.
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition: Point.h:17
QPointF posScreen() const
Accessor for screen position.
Definition: Point.cpp:342
CallbackSearchReturn
Return values for search callback methods.
QString identifier() const
Unique identifier for a specific Point.
Definition: Point.cpp:218
Continue normal execution of the search.
CallbackAxisPointsAbstract(const DocumentModelCoords &modelCoords)
Constructor for when all of the existing axis points are to be processed as is.
Model for DlgSettingsCoords and CmdSettingsCoords.
Immediately terminate the current search.
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
QTransform matrixScreen() const
Returns screen coordinates matrix after transformIsDefined has already indicated success.