7 #include "CallbackAxisPointsAbstract.h" 8 #include "EngaugeAssert.h" 12 #include "QtToString.h" 13 #include "Transformation.h" 16 DocumentAxesPointsRequired documentAxesPointsRequired) :
17 m_modelCoords (modelCoords),
19 m_documentAxesPointsRequired (documentAxesPointsRequired)
24 const QString pointIdentifierOverride,
25 const QPointF &posScreenOverride,
26 const QPointF &posGraphOverride,
28 m_modelCoords (modelCoords),
29 m_pointIdentifierOverride (pointIdentifierOverride),
30 m_posScreenOverride (posScreenOverride),
31 m_posGraphOverride (posGraphOverride),
33 m_documentAxesPointsRequired (documentAxesPointsRequired)
37 bool CallbackAxisPointsAbstract::anyPointsRepeatPair (
const CoordPairVector &vector)
const 39 for (
int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
40 for (
int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
42 if ((vector.at(pointLeft).x() == vector.at(pointRight).x()) &&
43 (vector.at(pointLeft).y() == vector.at(pointRight).y())) {
55 bool CallbackAxisPointsAbstract::anyPointsRepeatSingle (
const CoordSingleVector &vector)
const 57 for (
int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
58 for (
int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
60 if (vector.at(pointLeft) == vector.at(pointRight)) {
76 QPointF posGraph = point.
posGraph ();
78 if (m_pointIdentifierOverride == point.
identifier ()) {
81 posScreen = m_posScreenOverride;
82 posGraph = m_posGraphOverride;
86 if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2) {
87 return callbackRequire2AxisPoints (posScreen,
89 }
else if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) {
90 return callbackRequire3AxisPoints (posScreen,
93 return callbackRequire4AxisPoints (point.
isXOnly(),
99 CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire2AxisPoints (
const QPointF &posScreen,
100 const QPointF &posGraph)
102 CallbackSearchReturn rtn = CALLBACK_SEARCH_RETURN_CONTINUE;
107 m_xGraphHigh = posGraph.x();
108 m_yGraphHigh = posGraph.x();
110 int numberPoints = m_screenInputs.count();
111 if (numberPoints < 2) {
114 m_screenInputs.push_back (posScreen);
115 m_graphOutputs.push_back (posGraph);
116 numberPoints = m_screenInputs.count();
118 if (numberPoints == 2) {
123 if (anyPointsRepeatPair (m_screenInputs)) {
126 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
127 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
132 if (m_screenInputs.count() > 1) {
135 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
142 CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (
const QPointF &posScreen,
143 const QPointF &posGraph)
145 CallbackSearchReturn rtn = CALLBACK_SEARCH_RETURN_CONTINUE;
148 int numberPoints = m_screenInputs.count();
149 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
150 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
151 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
152 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
154 if (numberPoints < 3) {
157 m_screenInputs.push_back (posScreen);
158 m_graphOutputs.push_back (posGraph);
159 numberPoints = m_screenInputs.count();
161 if (numberPoints == 3) {
166 if ((m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2 ||
167 m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) &&
168 anyPointsRepeatPair (m_screenInputs)) {
171 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
172 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
174 }
else if ((m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2 ||
175 m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) &&
176 anyPointsRepeatPair (m_graphOutputs)) {
179 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
180 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
182 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform)) {
185 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
186 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
188 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform)) {
191 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
192 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
197 if (m_screenInputs.count() > 2) {
200 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
207 CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire4AxisPoints (
bool isXOnly,
208 const QPointF &posScreen,
209 const QPointF &posGraph)
211 CallbackSearchReturn rtn = CALLBACK_SEARCH_RETURN_CONTINUE;
214 int numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
215 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
216 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
217 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
218 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
220 if (numberPoints < 4) {
225 m_screenInputsX.push_back (posScreen);
226 m_graphOutputsX.push_back (posGraph.x());
230 m_screenInputsY.push_back (posScreen);
231 m_graphOutputsY.push_back (posGraph.y());
235 numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
236 if (numberPoints == 4) {
241 if (m_screenInputsX.count() > 2) {
244 m_errorMessage = QObject::tr (
"Too many x axis points. There should only be two");
245 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
247 }
else if (m_screenInputsY.count() > 2) {
250 m_errorMessage = QObject::tr (
"Too many y axis points. There should only be two");
251 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
255 if ((m_screenInputsX.count() == 2) &&
256 (m_screenInputsY.count() == 2)) {
259 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
263 if (anyPointsRepeatPair (m_screenInputsX) ||
264 anyPointsRepeatPair (m_screenInputsY)) {
267 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
268 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
270 }
else if (anyPointsRepeatSingle (m_graphOutputsX) ||
271 anyPointsRepeatSingle (m_graphOutputsY)) {
274 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
275 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
277 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform)) {
280 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
281 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
283 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform)) {
286 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
287 rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
297 return m_documentAxesPointsRequired;
300 void CallbackAxisPointsAbstract::loadTransforms2 ()
307 double d0To1ScreenX = m_screenInputs.at (1).x () - m_screenInputs.at (0).x ();
308 double d0To1ScreenY = m_screenInputs.at (1).y () - m_screenInputs.at (0).y ();
309 double d0To1ScreenZ = 0;
310 double d0To1GraphX = m_graphOutputs.at (1).x () - m_graphOutputs.at (0).x ();
311 double d0To1GraphY = m_graphOutputs.at (1).y () - m_graphOutputs.at (0).y ();
312 double d0To1GraphZ = 0;
314 double unitNormalX = 0;
315 double unitNormalY = 0;
316 double unitNormalZ = 1;
318 double d0To2ScreenX = unitNormalY * d0To1ScreenZ - unitNormalZ * d0To1ScreenY;
319 double d0To2ScreenY = unitNormalZ * d0To1ScreenX - unitNormalX * d0To1ScreenZ;
320 double d0To2GraphX = unitNormalY * d0To1GraphZ - unitNormalZ * d0To1GraphY;
321 double d0To2GraphY = unitNormalZ * d0To1GraphX - unitNormalX * d0To1GraphZ;
325 const double FLIP_Y_SCREEN = -1.0;
327 double screenX2 = m_screenInputs.at (0).x () + FLIP_Y_SCREEN * d0To2ScreenX;
328 double screenY2 = m_screenInputs.at (0).y () + FLIP_Y_SCREEN * d0To2ScreenY;
329 double graphX2 = m_graphOutputs.at (0).x () + d0To2GraphX;
330 double graphY2 = m_graphOutputs.at (0).y () + d0To2GraphY;
333 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), screenX2,
334 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), screenY2,
338 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), graphX2,
339 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), graphY2,
343 void CallbackAxisPointsAbstract::loadTransforms3 ()
346 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), m_screenInputs.at(2).x(),
347 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), m_screenInputs.at(2).y(),
351 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), m_graphOutputs.at(2).x(),
352 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), m_graphOutputs.at(2).y(),
356 void CallbackAxisPointsAbstract::loadTransforms4 ()
358 double x1Screen = m_screenInputsX.at(0).x();
359 double y1Screen = m_screenInputsX.at(0).y();
360 double x2Screen = m_screenInputsX.at(1).x();
361 double y2Screen = m_screenInputsX.at(1).y();
362 double x3Screen = m_screenInputsY.at(0).x();
363 double y3Screen = m_screenInputsY.at(0).y();
364 double x4Screen = m_screenInputsY.at(1).x();
365 double y4Screen = m_screenInputsY.at(1).y();
368 double x1Graph = m_graphOutputsX.at(0);
369 double x2Graph = m_graphOutputsX.at(1);
370 double y3Graph = m_graphOutputsY.at(0);
371 double y4Graph = m_graphOutputsY.at(1);
382 double A00 = x1Screen - x2Screen;
383 double A01 = x4Screen - x3Screen;
384 double A10 = y1Screen - y2Screen;
385 double A11 = y4Screen - y3Screen;
386 double b0 = x1Screen - x3Screen;
387 double b1 = y1Screen - y3Screen;
388 double numeratorx = (b0 * A11 - A01 * b1);
389 double numeratory = (A00 * b1 - b0 * A10);
390 double denominator = (A00 * A11 - A01 * A10);
391 double sx = numeratorx / denominator;
392 double sy = numeratory / denominator;
395 double xIntScreen = (1.0 - sx) * x1Screen + sx * x2Screen;
396 double yIntScreen = (1.0 - sy) * y3Screen + sy * y4Screen;
397 double xIntGraph, yIntGraph;
399 xIntGraph = (1.0 - sx) * x1Graph + sx * x2Graph;
401 xIntGraph = qExp ((1.0 - sx) * qLn (x1Graph) + sx * qLn (x2Graph));
404 yIntGraph = (1.0 - sy) * y3Graph + sy * y4Graph;
406 yIntGraph = qExp ((1.0 - sy) * qLn (y3Graph) + sy * qLn (y4Graph));
410 double distance1 = qSqrt ((x1Screen - xIntScreen) * (x1Screen - xIntScreen) +
411 (y1Screen - yIntScreen) * (y1Screen - yIntScreen));
412 double distance2 = qSqrt ((x2Screen - xIntScreen) * (x2Screen - xIntScreen) +
413 (y2Screen - yIntScreen) * (y2Screen - yIntScreen));
414 double distance3 = qSqrt ((x3Screen - xIntScreen) * (x3Screen - xIntScreen) +
415 (y3Screen - yIntScreen) * (y3Screen - yIntScreen));
416 double distance4 = qSqrt ((x4Screen - xIntScreen) * (x4Screen - xIntScreen) +
417 (y4Screen - yIntScreen) * (y4Screen - yIntScreen));
423 double xFurthestXAxisScreen, yFurthestXAxisScreen, xFurthestYAxisScreen, yFurthestYAxisScreen;
424 double xFurthestXAxisGraph, yFurthestXAxisGraph, xFurthestYAxisGraph, yFurthestYAxisGraph;
425 if (distance1 < distance2) {
426 xFurthestXAxisScreen = x2Screen;
427 yFurthestXAxisScreen = y2Screen;
428 xFurthestXAxisGraph = x2Graph;
429 yFurthestXAxisGraph = yIntGraph;
431 xFurthestXAxisScreen = x1Screen;
432 yFurthestXAxisScreen = y1Screen;
433 xFurthestXAxisGraph = x1Graph;
434 yFurthestXAxisGraph = yIntGraph;
436 if (distance3 < distance4) {
437 xFurthestYAxisScreen = x4Screen;
438 yFurthestYAxisScreen = y4Screen;
439 xFurthestYAxisGraph = xIntGraph;
440 yFurthestYAxisGraph = y4Graph;
442 xFurthestYAxisScreen = x3Screen;
443 yFurthestYAxisScreen = y3Screen;
444 xFurthestYAxisGraph = xIntGraph;
445 yFurthestYAxisGraph = y3Graph;
449 m_screenInputsTransform = QTransform (xIntScreen, xFurthestXAxisScreen, xFurthestYAxisScreen,
450 yIntScreen, yFurthestXAxisScreen, yFurthestYAxisScreen,
454 m_graphOutputsTransform = QTransform (xIntGraph, xFurthestXAxisGraph, xFurthestYAxisGraph,
455 yIntGraph, yFurthestXAxisGraph, yFurthestYAxisGraph,
461 return m_graphOutputsTransform;
466 return m_screenInputsTransform;
471 if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2) {
472 return m_screenInputs.count();
473 }
else if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) {
474 return m_screenInputs.count();
476 return m_screenInputsX.count() + m_screenInputsY.count();
480 bool CallbackAxisPointsAbstract::threePointsAreCollinear (
const QTransform &transform)
482 return (transform.determinant() == 0);
bool isXOnly() const
In DOCUMENT_AXES_POINTS_REQUIRED_4 modes, this is true/false if y/x coordinate is undefined...
QTransform matrixScreen() const
Returns screen coordinates matrix after transformIsDefined has already indicated success.
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
QPointF posScreen() const
Accessor for screen position.
unsigned int numberAxisPoints() const
Number of axis points which is less than 3 if the axes curve is incomplete.
QString identifier() const
Unique identifier for a specific Point.
CoordScale coordScaleXTheta() const
Get method for linear/log scale on x/theta.
QPointF posGraph(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Accessor for graph position. Skip check if copying one instance to another.
Model for DlgSettingsCoords and CmdSettingsCoords.
CoordScale coordScaleYRadius() const
Get method for linear/log scale on y/radius.
CallbackAxisPointsAbstract(const DocumentModelCoords &modelCoords, DocumentAxesPointsRequired documentAxesPointsRequired)
Constructor for when all of the existing axis points are to be processed as is.
QTransform matrixGraph() const
Returns graph coordinates matrix after transformIsDefined has already indicated success.
DocumentAxesPointsRequired documentAxesPointsRequired() const
Number of axes points required for the transformation.
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.