21 m_modelCoords (modelCoords),
23 m_documentAxesPointsRequired (documentAxesPointsRequired)
28 const QString pointIdentifierOverride,
29 const QPointF &posScreenOverride,
30 const QPointF &posGraphOverride,
32 m_modelCoords (modelCoords),
33 m_pointIdentifierOverride (pointIdentifierOverride),
34 m_posScreenOverride (posScreenOverride),
35 m_posGraphOverride (posGraphOverride),
37 m_documentAxesPointsRequired (documentAxesPointsRequired)
41bool CallbackAxisPointsAbstract::anyPointsRepeatPair (
const CoordPairVector &vector,
44 for (
int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
45 for (
int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
47 if (qAbs (vector.at(pointLeft).x() - vector.at(pointRight).x()) <= epsilon &&
48 qAbs (vector.at(pointLeft).y() - vector.at(pointRight).y()) <= epsilon) {
60bool CallbackAxisPointsAbstract::anyPointsRepeatSingle (
const CoordSingleVector &vector,
63 for (
int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
64 for (
int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
66 if (qAbs (vector.at(pointLeft) - vector.at(pointRight)) <= epsilon) {
82 QPointF posGraph = point.
posGraph ();
84 if (m_pointIdentifierOverride == point.
identifier ()) {
87 posScreen = m_posScreenOverride;
88 posGraph = m_posGraphOverride;
93 return callbackRequire2AxisPoints (posScreen,
96 return callbackRequire3AxisPoints (posScreen,
99 return callbackRequire4AxisPoints (point.
isXOnly(),
105CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire2AxisPoints (
const QPointF &posScreen,
106 const QPointF &posGraph)
113 m_xGraphHigh = posGraph.x();
114 m_yGraphHigh = posGraph.x();
116 int numberPoints = m_screenInputs.count();
117 if (numberPoints < 2) {
120 m_screenInputs.push_back (posScreen);
121 m_graphOutputs.push_back (posGraph);
122 numberPoints = m_screenInputs.count();
124 if (numberPoints == 2) {
129 if (anyPointsRepeatPair (m_screenInputs,
133 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
139 if (m_screenInputs.count() > 1) {
149CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (
const QPointF &posScreen,
150 const QPointF &posGraph)
155 int numberPoints = m_screenInputs.count();
156 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
157 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
158 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
159 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
161 if (numberPoints < 3) {
164 m_screenInputs.push_back (posScreen);
165 m_graphOutputs.push_back (posGraph);
166 numberPoints = m_screenInputs.count();
168 if (numberPoints == 3) {
175 anyPointsRepeatPair (m_screenInputs,
ONE_PIXEL)) {
178 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
186 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
189 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform,
194 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
197 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform,
202 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
208 if (m_screenInputs.count() > 2) {
219 const QPointF &posScreen,
220 const QPointF &posGraph)
225 int numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
226 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
227 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
228 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
229 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
231 if (numberPoints < 4) {
236 m_screenInputsX.push_back (posScreen);
237 m_graphOutputsX.push_back (posGraph.x());
241 m_screenInputsY.push_back (posScreen);
242 m_graphOutputsY.push_back (posGraph.y());
246 numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
247 if (numberPoints == 4) {
252 if (m_screenInputsX.count() > 2) {
255 m_errorMessage = QObject::tr (
"Too many x axis points. There should only be two");
258 }
else if (m_screenInputsY.count() > 2) {
261 m_errorMessage = QObject::tr (
"Too many y axis points. There should only be two");
266 if ((m_screenInputsX.count() == 2) &&
267 (m_screenInputsY.count() == 2)) {
274 if (anyPointsRepeatPair (m_screenInputsX,
276 anyPointsRepeatPair (m_screenInputsY,
280 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
283 }
else if (anyPointsRepeatSingle (m_graphOutputsX,
285 anyPointsRepeatSingle (m_graphOutputsY,
289 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
292 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform,
297 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
300 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform,
305 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
316 return m_documentAxesPointsRequired;
319void CallbackAxisPointsAbstract::loadTransforms2 ()
326 double d0To1ScreenX = m_screenInputs.at (1).x () - m_screenInputs.at (0).x ();
327 double d0To1ScreenY = m_screenInputs.at (1).y () - m_screenInputs.at (0).y ();
328 double d0To1ScreenZ = 0;
329 double d0To1GraphX = m_graphOutputs.at (1).x () - m_graphOutputs.at (0).x ();
330 double d0To1GraphY = m_graphOutputs.at (1).y () - m_graphOutputs.at (0).y ();
331 double d0To1GraphZ = 0;
333 double unitNormalX = 0;
334 double unitNormalY = 0;
335 double unitNormalZ = 1;
337 double d0To2ScreenX = unitNormalY * d0To1ScreenZ - unitNormalZ * d0To1ScreenY;
338 double d0To2ScreenY = unitNormalZ * d0To1ScreenX - unitNormalX * d0To1ScreenZ;
339 double d0To2GraphX = unitNormalY * d0To1GraphZ - unitNormalZ * d0To1GraphY;
340 double d0To2GraphY = unitNormalZ * d0To1GraphX - unitNormalX * d0To1GraphZ;
344 const double FLIP_Y_SCREEN = -1.0;
346 double screenX2 = m_screenInputs.at (0).x () + FLIP_Y_SCREEN * d0To2ScreenX;
347 double screenY2 = m_screenInputs.at (0).y () + FLIP_Y_SCREEN * d0To2ScreenY;
348 double graphX2 = m_graphOutputs.at (0).x () + d0To2GraphX;
349 double graphY2 = m_graphOutputs.at (0).y () + d0To2GraphY;
352 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), screenX2,
353 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), screenY2,
357 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), graphX2,
358 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), graphY2,
362void CallbackAxisPointsAbstract::loadTransforms3 ()
365 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), m_screenInputs.at(2).x(),
366 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), m_screenInputs.at(2).y(),
370 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), m_graphOutputs.at(2).x(),
371 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), m_graphOutputs.at(2).y(),
375void CallbackAxisPointsAbstract::loadTransforms4 ()
377 double x1Screen = m_screenInputsX.at(0).x();
378 double y1Screen = m_screenInputsX.at(0).y();
379 double x2Screen = m_screenInputsX.at(1).x();
380 double y2Screen = m_screenInputsX.at(1).y();
381 double x3Screen = m_screenInputsY.at(0).x();
382 double y3Screen = m_screenInputsY.at(0).y();
383 double x4Screen = m_screenInputsY.at(1).x();
384 double y4Screen = m_screenInputsY.at(1).y();
387 double x1Graph = m_graphOutputsX.at(0);
388 double x2Graph = m_graphOutputsX.at(1);
389 double y3Graph = m_graphOutputsY.at(0);
390 double y4Graph = m_graphOutputsY.at(1);
401 double A00 = x1Screen - x2Screen;
402 double A01 = x4Screen - x3Screen;
403 double A10 = y1Screen - y2Screen;
404 double A11 = y4Screen - y3Screen;
405 double b0 = x1Screen - x3Screen;
406 double b1 = y1Screen - y3Screen;
407 double numeratorx = (b0 * A11 - A01 * b1);
408 double numeratory = (A00 * b1 - b0 * A10);
409 double denominator = (A00 * A11 - A01 * A10);
410 double sx = numeratorx / denominator;
411 double sy = numeratory / denominator;
414 double xIntScreen = (1.0 - sx) * x1Screen + sx * x2Screen;
415 double yIntScreen = (1.0 - sy) * y3Screen + sy * y4Screen;
416 double xIntGraph, yIntGraph;
418 xIntGraph = (1.0 - sx) * x1Graph + sx * x2Graph;
420 xIntGraph = qExp ((1.0 - sx) * qLn (x1Graph) + sx * qLn (x2Graph));
423 yIntGraph = (1.0 - sy) * y3Graph + sy * y4Graph;
425 yIntGraph = qExp ((1.0 - sy) * qLn (y3Graph) + sy * qLn (y4Graph));
429 double distance1 = qSqrt ((x1Screen - xIntScreen) * (x1Screen - xIntScreen) +
430 (y1Screen - yIntScreen) * (y1Screen - yIntScreen));
431 double distance2 = qSqrt ((x2Screen - xIntScreen) * (x2Screen - xIntScreen) +
432 (y2Screen - yIntScreen) * (y2Screen - yIntScreen));
433 double distance3 = qSqrt ((x3Screen - xIntScreen) * (x3Screen - xIntScreen) +
434 (y3Screen - yIntScreen) * (y3Screen - yIntScreen));
435 double distance4 = qSqrt ((x4Screen - xIntScreen) * (x4Screen - xIntScreen) +
436 (y4Screen - yIntScreen) * (y4Screen - yIntScreen));
442 double xFurthestXAxisScreen, yFurthestXAxisScreen, xFurthestYAxisScreen, yFurthestYAxisScreen;
443 double xFurthestXAxisGraph, yFurthestXAxisGraph, xFurthestYAxisGraph, yFurthestYAxisGraph;
444 if (distance1 < distance2) {
445 xFurthestXAxisScreen = x2Screen;
446 yFurthestXAxisScreen = y2Screen;
447 xFurthestXAxisGraph = x2Graph;
448 yFurthestXAxisGraph = yIntGraph;
450 xFurthestXAxisScreen = x1Screen;
451 yFurthestXAxisScreen = y1Screen;
452 xFurthestXAxisGraph = x1Graph;
453 yFurthestXAxisGraph = yIntGraph;
455 if (distance3 < distance4) {
456 xFurthestYAxisScreen = x4Screen;
457 yFurthestYAxisScreen = y4Screen;
458 xFurthestYAxisGraph = xIntGraph;
459 yFurthestYAxisGraph = y4Graph;
461 xFurthestYAxisScreen = x3Screen;
462 yFurthestYAxisScreen = y3Screen;
463 xFurthestYAxisGraph = xIntGraph;
464 yFurthestYAxisGraph = y3Graph;
468 m_screenInputsTransform = QTransform (xIntScreen, xFurthestXAxisScreen, xFurthestYAxisScreen,
469 yIntScreen, yFurthestXAxisScreen, yFurthestYAxisScreen,
473 m_graphOutputsTransform = QTransform (xIntGraph, xFurthestXAxisGraph, xFurthestYAxisGraph,
474 yIntGraph, yFurthestXAxisGraph, yFurthestYAxisGraph,
478CallbackAxisPointsAbstract::LinearOrLog CallbackAxisPointsAbstract::logXGraph ()
const
483CallbackAxisPointsAbstract::LinearOrLog CallbackAxisPointsAbstract::logYGraph ()
const
490 return m_graphOutputsTransform;
495 return m_screenInputsTransform;
501 return unsigned (m_screenInputs.count());
503 return unsigned (m_screenInputs.count());
505 return unsigned (m_screenInputsX.count() + m_screenInputsY.count());
509bool CallbackAxisPointsAbstract::threePointsAreCollinear (
const QTransform &transformIn,
511 LinearOrLog logY)
const
513 double m11 = (logX == COORD_IS_LOG) ? qLn (transformIn.m11()) : transformIn.m11();
514 double m12 = (logX == COORD_IS_LOG) ? qLn (transformIn.m12()) : transformIn.m12();
515 double m13 = (logX == COORD_IS_LOG) ? qLn (transformIn.m13()) : transformIn.m13();
516 double m21 = (logY == COORD_IS_LOG) ? qLn (transformIn.m21()) : transformIn.m21();
517 double m22 = (logY == COORD_IS_LOG) ? qLn (transformIn.m22()) : transformIn.m22();
518 double m23 = (logY == COORD_IS_LOG) ? qLn (transformIn.m23()) : transformIn.m23();
519 double m31 = transformIn.m31();
520 double m32 = transformIn.m32();
521 double m33 = transformIn.m33();
523 QTransform transform (m11, m12, m13,
527 return !transform.isInvertible ();
const double ZERO_EPSILON
QList< QPointF > CoordPairVector
QList< double > CoordSingleVector
CallbackSearchReturn
Return values for search callback methods.
@ CALLBACK_SEARCH_RETURN_CONTINUE
Continue normal execution of the search.
@ CALLBACK_SEARCH_RETURN_INTERRUPT
Immediately terminate the current search.
DocumentAxesPointsRequired
@ DOCUMENT_AXES_POINTS_REQUIRED_3
@ DOCUMENT_AXES_POINTS_REQUIRED_2
DocumentAxesPointsRequired documentAxesPointsRequired() const
Number of axes points required for the transformation.
QTransform matrixGraph() const
Returns graph coordinates matrix after transformIsDefined has already indicated success.
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
CallbackAxisPointsAbstract(const DocumentModelCoords &modelCoords, DocumentAxesPointsRequired documentAxesPointsRequired)
Constructor for when all of the existing axis points are to be processed as is.
unsigned int numberAxisPoints() const
Number of axis points which is less than 3 if the axes curve is incomplete.
QTransform matrixScreen() const
Returns screen coordinates matrix after transformIsDefined has already indicated success.
Model for DlgSettingsCoords and CmdSettingsCoords.
CoordScale coordScaleYRadius() const
Get method for linear/log scale on y/radius.
CoordScale coordScaleXTheta() const
Get method for linear/log scale on x/theta.
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
QPointF posGraph(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Accessor for graph position. Skip check if copying one instance to another.
QPointF posScreen() const
Accessor for screen position.
QString identifier() const
Unique identifier for a specific Point.
bool isXOnly() const
In DOCUMENT_AXES_POINTS_REQUIRED_4 modes, this is true/false if y/x coordinate is undefined.