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)
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");
132 if (m_screenInputs.count() > 1) {
142 CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (
const QPointF &posScreen,
143 const QPointF &posGraph)
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 (anyPointsRepeatPair (m_screenInputs)) {
169 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
172 }
else if (anyPointsRepeatPair (m_graphOutputs)) {
175 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
178 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform)) {
181 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
184 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform)) {
187 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
193 if (m_screenInputs.count() > 2) {
204 const QPointF &posScreen,
205 const QPointF &posGraph)
210 int numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
211 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
212 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
213 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
214 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
216 if (numberPoints < 4) {
221 m_screenInputsX.push_back (posScreen);
222 m_graphOutputsX.push_back (posGraph.x());
226 m_screenInputsY.push_back (posScreen);
227 m_graphOutputsY.push_back (posGraph.y());
231 numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
232 if (numberPoints == 4) {
237 if (m_screenInputsX.count() > 2) {
240 m_errorMessage = QObject::tr (
"Too many x axis points. There should only be two");
243 }
else if (m_screenInputsY.count() > 2) {
246 m_errorMessage = QObject::tr (
"Too many y axis points. There should only be two");
251 if ((m_screenInputsX.count() == 2) &&
252 (m_screenInputsY.count() == 2)) {
259 if (anyPointsRepeatPair (m_screenInputsX) ||
260 anyPointsRepeatPair (m_screenInputsY)) {
263 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
266 }
else if (anyPointsRepeatSingle (m_graphOutputsX) ||
267 anyPointsRepeatSingle (m_graphOutputsY)) {
270 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
273 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform)) {
276 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
279 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform)) {
282 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
293 return m_documentAxesPointsRequired;
296 void CallbackAxisPointsAbstract::loadTransforms2 ()
303 double d0To1ScreenX = m_screenInputs.at (1).x () - m_screenInputs.at (0).x ();
304 double d0To1ScreenY = m_screenInputs.at (1).y () - m_screenInputs.at (0).y ();
305 double d0To1ScreenZ = 0;
306 double d0To1GraphX = m_graphOutputs.at (1).x () - m_graphOutputs.at (0).x ();
307 double d0To1GraphY = m_graphOutputs.at (1).y () - m_graphOutputs.at (0).y ();
308 double d0To1GraphZ = 0;
310 double unitNormalX = 0;
311 double unitNormalY = 0;
312 double unitNormalZ = 1;
314 double d0To2ScreenX = unitNormalY * d0To1ScreenZ - unitNormalZ * d0To1ScreenY;
315 double d0To2ScreenY = unitNormalZ * d0To1ScreenX - unitNormalX * d0To1ScreenZ;
316 double d0To2GraphX = unitNormalY * d0To1GraphZ - unitNormalZ * d0To1GraphY;
317 double d0To2GraphY = unitNormalZ * d0To1GraphX - unitNormalX * d0To1GraphZ;
321 const double FLIP_Y_SCREEN = -1.0;
323 double screenX2 = m_screenInputs.at (0).x () + FLIP_Y_SCREEN * d0To2ScreenX;
324 double screenY2 = m_screenInputs.at (0).y () + FLIP_Y_SCREEN * d0To2ScreenY;
325 double graphX2 = m_graphOutputs.at (0).x () + d0To2GraphX;
326 double graphY2 = m_graphOutputs.at (0).y () + d0To2GraphY;
329 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), screenX2,
330 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), screenY2,
334 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), graphX2,
335 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), graphY2,
339 void CallbackAxisPointsAbstract::loadTransforms3 ()
342 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), m_screenInputs.at(2).x(),
343 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), m_screenInputs.at(2).y(),
347 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), m_graphOutputs.at(2).x(),
348 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), m_graphOutputs.at(2).y(),
352 void CallbackAxisPointsAbstract::loadTransforms4 ()
354 double x1Screen = m_screenInputsX.at(0).x();
355 double y1Screen = m_screenInputsX.at(0).y();
356 double x2Screen = m_screenInputsX.at(1).x();
357 double y2Screen = m_screenInputsX.at(1).y();
358 double x3Screen = m_screenInputsY.at(0).x();
359 double y3Screen = m_screenInputsY.at(0).y();
360 double x4Screen = m_screenInputsY.at(1).x();
361 double y4Screen = m_screenInputsY.at(1).y();
364 double x1Graph = m_graphOutputsX.at(0);
365 double x2Graph = m_graphOutputsX.at(1);
366 double y3Graph = m_graphOutputsY.at(0);
367 double y4Graph = m_graphOutputsY.at(1);
378 double A00 = x1Screen - x2Screen;
379 double A01 = x4Screen - x3Screen;
380 double A10 = y1Screen - y2Screen;
381 double A11 = y4Screen - y3Screen;
382 double b0 = x1Screen - x3Screen;
383 double b1 = y1Screen - y3Screen;
384 double numeratorx = (b0 * A11 - A01 * b1);
385 double numeratory = (A00 * b1 - b0 * A10);
386 double denominator = (A00 * A11 - A01 * A10);
387 double sx = numeratorx / denominator;
388 double sy = numeratory / denominator;
391 double xIntScreen = (1.0 - sx) * x1Screen + sx * x2Screen;
392 double yIntScreen = (1.0 - sy) * y3Screen + sy * y4Screen;
393 double xIntGraph, yIntGraph;
395 xIntGraph = (1.0 - sx) * x1Graph + sx * x2Graph;
397 xIntGraph = qExp ((1.0 - sx) * qLn (x1Graph) + sx * qLn (x2Graph));
400 yIntGraph = (1.0 - sy) * y3Graph + sy * y4Graph;
402 yIntGraph = qExp ((1.0 - sy) * qLn (y3Graph) + sy * qLn (y4Graph));
406 double distance1 = qSqrt ((x1Screen - xIntScreen) * (x1Screen - xIntScreen) +
407 (y1Screen - yIntScreen) * (y1Screen - yIntScreen));
408 double distance2 = qSqrt ((x2Screen - xIntScreen) * (x2Screen - xIntScreen) +
409 (y2Screen - yIntScreen) * (y2Screen - yIntScreen));
410 double distance3 = qSqrt ((x3Screen - xIntScreen) * (x3Screen - xIntScreen) +
411 (y3Screen - yIntScreen) * (y3Screen - yIntScreen));
412 double distance4 = qSqrt ((x4Screen - xIntScreen) * (x4Screen - xIntScreen) +
413 (y4Screen - yIntScreen) * (y4Screen - yIntScreen));
419 double xFurthestXAxisScreen, yFurthestXAxisScreen, xFurthestYAxisScreen, yFurthestYAxisScreen;
420 double xFurthestXAxisGraph, yFurthestXAxisGraph, xFurthestYAxisGraph, yFurthestYAxisGraph;
421 if (distance1 < distance2) {
422 xFurthestXAxisScreen = x2Screen;
423 yFurthestXAxisScreen = y2Screen;
424 xFurthestXAxisGraph = x2Graph;
425 yFurthestXAxisGraph = yIntGraph;
427 xFurthestXAxisScreen = x1Screen;
428 yFurthestXAxisScreen = y1Screen;
429 xFurthestXAxisGraph = x1Graph;
430 yFurthestXAxisGraph = yIntGraph;
432 if (distance3 < distance4) {
433 xFurthestYAxisScreen = x4Screen;
434 yFurthestYAxisScreen = y4Screen;
435 xFurthestYAxisGraph = xIntGraph;
436 yFurthestYAxisGraph = y4Graph;
438 xFurthestYAxisScreen = x3Screen;
439 yFurthestYAxisScreen = y3Screen;
440 xFurthestYAxisGraph = xIntGraph;
441 yFurthestYAxisGraph = y3Graph;
445 m_screenInputsTransform = QTransform (xIntScreen, xFurthestXAxisScreen, xFurthestYAxisScreen,
446 yIntScreen, yFurthestXAxisScreen, yFurthestYAxisScreen,
450 m_graphOutputsTransform = QTransform (xIntGraph, xFurthestXAxisGraph, xFurthestYAxisGraph,
451 yIntGraph, yFurthestXAxisGraph, yFurthestYAxisGraph,
457 return m_graphOutputsTransform;
462 return m_screenInputsTransform;
467 if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2) {
468 return m_screenInputs.count();
469 }
else if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) {
470 return m_screenInputs.count();
472 return m_screenInputsX.count() + m_screenInputsY.count();
476 bool CallbackAxisPointsAbstract::threePointsAreCollinear (
const QTransform &transform)
478 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.
CallbackSearchReturn
Return values for search callback methods.
Continue normal execution of the search.
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.
Immediately terminate the current search.
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.