26 m_modelCoords (modelCoords),
33 const QString pointIdentifierOverride,
34 const QPointF &posScreenOverride,
35 const QPointF &posGraphOverride,
37 m_modelCoords (modelCoords),
38 m_pointIdentifierOverride (pointIdentifierOverride),
39 m_posScreenOverride (posScreenOverride),
40 m_posGraphOverride (posGraphOverride),
46bool CallbackAxisPointsAbstract::anyPointsRepeatPair (
const CoordPairVector &vector,
49 for (
int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
50 for (
int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
52 if (qAbs (vector.at(pointLeft).x() - vector.at(pointRight).x()) <= epsilon &&
53 qAbs (vector.at(pointLeft).y() - vector.at(pointRight).y()) <= epsilon) {
65bool CallbackAxisPointsAbstract::anyPointsRepeatSingle (
const CoordSingleVector &vector,
68 for (
int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
69 for (
int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
71 if (qAbs (vector.at(pointLeft) - vector.at(pointRight)) <= epsilon) {
87 QPointF posGraph = point.
posGraph ();
89 if (m_pointIdentifierOverride == point.
identifier ()) {
92 posScreen = m_posScreenOverride;
93 posGraph = m_posGraphOverride;
98 return callbackRequire2AxisPoints (posScreen,
101 return callbackRequire3AxisPoints (posScreen,
104 return callbackRequire4AxisPoints (point.
isXOnly(),
110CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire2AxisPoints (
const QPointF &posScreen,
111 const QPointF &posGraph)
118 m_xGraphHigh = posGraph.x();
119 m_yGraphHigh = posGraph.x();
121 int numberPoints = m_screenInputs.count();
122 if (numberPoints < 2) {
125 m_screenInputs.push_back (posScreen);
126 m_graphOutputs.push_back (posGraph);
127 numberPoints = m_screenInputs.count();
129 if (numberPoints == 2) {
134 if (anyPointsRepeatPair (m_screenInputs,
138 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
144 if (m_screenInputs.count() > 1) {
154CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (
const QPointF &posScreen,
155 const QPointF &posGraph)
160 int numberPoints = m_screenInputs.count();
161 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
162 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
163 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
164 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
166 if (numberPoints < 3) {
169 m_screenInputs.push_back (posScreen);
170 m_graphOutputs.push_back (posGraph);
171 numberPoints = m_screenInputs.count();
173 if (numberPoints == 3) {
180 anyPointsRepeatPair (m_screenInputs,
ONE_PIXEL)) {
183 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
191 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
194 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform,
199 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
202 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform,
207 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
213 if (m_screenInputs.count() > 2) {
224 const QPointF &posScreen,
225 const QPointF &posGraph)
230 int numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
231 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
232 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
233 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
234 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
236 if (numberPoints < 4) {
241 m_screenInputsX.push_back (posScreen);
242 m_graphOutputsX.push_back (posGraph.x());
246 m_screenInputsY.push_back (posScreen);
247 m_graphOutputsY.push_back (posGraph.y());
251 numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
252 if (numberPoints == 4) {
257 if (m_screenInputsX.count() > 2) {
260 m_errorMessage = QObject::tr (
"Too many x axis points. There should only be two");
263 }
else if (m_screenInputsY.count() > 2) {
266 m_errorMessage = QObject::tr (
"Too many y axis points. There should only be two");
271 if ((m_screenInputsX.count() == 2) &&
272 (m_screenInputsY.count() == 2)) {
279 if (anyPointsRepeatPair (m_screenInputsX,
281 anyPointsRepeatPair (m_screenInputsY,
285 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
288 }
else if (anyPointsRepeatSingle (m_graphOutputsX,
290 anyPointsRepeatSingle (m_graphOutputsY,
294 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
297 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform,
302 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
305 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform,
310 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
321 return m_documentAxesPointsRequired;
324void CallbackAxisPointsAbstract::loadTransforms2 ()
331 double d0To1ScreenX = m_screenInputs.at (1).x () - m_screenInputs.at (0).x ();
332 double d0To1ScreenY = m_screenInputs.at (1).y () - m_screenInputs.at (0).y ();
333 double d0To1ScreenZ = 0;
334 double d0To1GraphX = m_graphOutputs.at (1).x () - m_graphOutputs.at (0).x ();
335 double d0To1GraphY = m_graphOutputs.at (1).y () - m_graphOutputs.at (0).y ();
336 double d0To1GraphZ = 0;
338 double unitNormalX = 0;
339 double unitNormalY = 0;
340 double unitNormalZ = 1;
342 double d0To2ScreenX = unitNormalY * d0To1ScreenZ - unitNormalZ * d0To1ScreenY;
343 double d0To2ScreenY = unitNormalZ * d0To1ScreenX - unitNormalX * d0To1ScreenZ;
344 double d0To2GraphX = unitNormalY * d0To1GraphZ - unitNormalZ * d0To1GraphY;
345 double d0To2GraphY = unitNormalZ * d0To1GraphX - unitNormalX * d0To1GraphZ;
349 const double FLIP_Y_SCREEN = -1.0;
351 double screenX2 = m_screenInputs.at (0).x () + FLIP_Y_SCREEN * d0To2ScreenX;
352 double screenY2 = m_screenInputs.at (0).y () + FLIP_Y_SCREEN * d0To2ScreenY;
353 double graphX2 = m_graphOutputs.at (0).x () + d0To2GraphX;
354 double graphY2 = m_graphOutputs.at (0).y () + d0To2GraphY;
357 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), screenX2,
358 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), screenY2,
362 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), graphX2,
363 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), graphY2,
367void CallbackAxisPointsAbstract::loadTransforms3 ()
370 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), m_screenInputs.at(2).x(),
371 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), m_screenInputs.at(2).y(),
375 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), m_graphOutputs.at(2).x(),
376 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), m_graphOutputs.at(2).y(),
380void CallbackAxisPointsAbstract::loadTransforms4 ()
382 double x1Screen = m_screenInputsX.at(0).x();
383 double y1Screen = m_screenInputsX.at(0).y();
384 double x2Screen = m_screenInputsX.at(1).x();
385 double y2Screen = m_screenInputsX.at(1).y();
386 double x3Screen = m_screenInputsY.at(0).x();
387 double y3Screen = m_screenInputsY.at(0).y();
388 double x4Screen = m_screenInputsY.at(1).x();
389 double y4Screen = m_screenInputsY.at(1).y();
392 double x1Graph = m_graphOutputsX.at(0);
393 double x2Graph = m_graphOutputsX.at(1);
394 double y3Graph = m_graphOutputsY.at(0);
395 double y4Graph = m_graphOutputsY.at(1);
406 double A00 = x1Screen - x2Screen;
407 double A01 = x4Screen - x3Screen;
408 double A10 = y1Screen - y2Screen;
409 double A11 = y4Screen - y3Screen;
410 double b0 = x1Screen - x3Screen;
411 double b1 = y1Screen - y3Screen;
412 double numeratorx = (b0 * A11 - A01 * b1);
413 double numeratory = (A00 * b1 - b0 * A10);
414 double denominator = (A00 * A11 - A01 * A10);
415 double sx = numeratorx / denominator;
416 double sy = numeratory / denominator;
419 double xIntScreen = (1.0 - sx) * x1Screen + sx * x2Screen;
420 double yIntScreen = (1.0 - sy) * y3Screen + sy * y4Screen;
421 double xIntGraph, yIntGraph;
423 xIntGraph = (1.0 - sx) * x1Graph + sx * x2Graph;
425 xIntGraph = qExp ((1.0 - sx) * qLn (x1Graph) + sx * qLn (x2Graph));
428 yIntGraph = (1.0 - sy) * y3Graph + sy * y4Graph;
430 yIntGraph = qExp ((1.0 - sy) * qLn (y3Graph) + sy * qLn (y4Graph));
434 double distance1 = qSqrt ((x1Screen - xIntScreen) * (x1Screen - xIntScreen) +
435 (y1Screen - yIntScreen) * (y1Screen - yIntScreen));
436 double distance2 = qSqrt ((x2Screen - xIntScreen) * (x2Screen - xIntScreen) +
437 (y2Screen - yIntScreen) * (y2Screen - yIntScreen));
438 double distance3 = qSqrt ((x3Screen - xIntScreen) * (x3Screen - xIntScreen) +
439 (y3Screen - yIntScreen) * (y3Screen - yIntScreen));
440 double distance4 = qSqrt ((x4Screen - xIntScreen) * (x4Screen - xIntScreen) +
441 (y4Screen - yIntScreen) * (y4Screen - yIntScreen));
447 double xFurthestXAxisScreen, yFurthestXAxisScreen, xFurthestYAxisScreen, yFurthestYAxisScreen;
448 double xFurthestXAxisGraph, yFurthestXAxisGraph, xFurthestYAxisGraph, yFurthestYAxisGraph;
449 if (distance1 < distance2) {
450 xFurthestXAxisScreen = x2Screen;
451 yFurthestXAxisScreen = y2Screen;
452 xFurthestXAxisGraph = x2Graph;
453 yFurthestXAxisGraph = yIntGraph;
455 xFurthestXAxisScreen = x1Screen;
456 yFurthestXAxisScreen = y1Screen;
457 xFurthestXAxisGraph = x1Graph;
458 yFurthestXAxisGraph = yIntGraph;
460 if (distance3 < distance4) {
461 xFurthestYAxisScreen = x4Screen;
462 yFurthestYAxisScreen = y4Screen;
463 xFurthestYAxisGraph = xIntGraph;
464 yFurthestYAxisGraph = y4Graph;
466 xFurthestYAxisScreen = x3Screen;
467 yFurthestYAxisScreen = y3Screen;
468 xFurthestYAxisGraph = xIntGraph;
469 yFurthestYAxisGraph = y3Graph;
473 m_screenInputsTransform = QTransform (xIntScreen , xFurthestXAxisScreen, xFurthestYAxisScreen,
474 yIntScreen , yFurthestXAxisScreen, yFurthestYAxisScreen,
478 m_graphOutputsTransform = QTransform (xIntGraph, xFurthestXAxisGraph, xFurthestYAxisGraph,
479 yIntGraph, yFurthestXAxisGraph, yFurthestYAxisGraph,
483CallbackAxisPointsAbstract::LinearOrLog CallbackAxisPointsAbstract::logXGraph ()
const
485 return m_modelCoords.coordScaleXTheta() ==
COORD_SCALE_LOG ? COORD_IS_LOG : COORD_IS_LINEAR;
488CallbackAxisPointsAbstract::LinearOrLog CallbackAxisPointsAbstract::logYGraph ()
const
490 return m_modelCoords.coordScaleYRadius() ==
COORD_SCALE_LOG ? COORD_IS_LOG : COORD_IS_LINEAR;
495 return m_graphOutputsTransform;
500 return m_screenInputsTransform;
506 return unsigned (m_screenInputs.count());
508 return unsigned (m_screenInputs.count());
510 return unsigned (m_screenInputsX.count() + m_screenInputsY.count());
514bool CallbackAxisPointsAbstract::threePointsAreCollinear (
const QTransform &transformIn,
516 LinearOrLog logY)
const
518 double m11 = (logX == COORD_IS_LOG) ? qLn (transformIn.m11()) : transformIn.m11();
519 double m12 = (logX == COORD_IS_LOG) ? qLn (transformIn.m12()) : transformIn.m12();
520 double m13 = (logX == COORD_IS_LOG) ? qLn (transformIn.m13()) : transformIn.m13();
521 double m21 = (logY == COORD_IS_LOG) ? qLn (transformIn.m21()) : transformIn.m21();
522 double m22 = (logY == COORD_IS_LOG) ? qLn (transformIn.m22()) : transformIn.m22();
523 double m23 = (logY == COORD_IS_LOG) ? qLn (transformIn.m23()) : transformIn.m23();
524 double m31 = transformIn.m31();
525 double m32 = transformIn.m32();
526 double m33 = transformIn.m33();
528 QTransform transform (m11, m12, m13,
532 return !transform.isInvertible ();
const double AFFINE_BOTTOM_ROW_NONUNITY
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.
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.