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_3) {
87 return callbackRequire3AxisPoints (posScreen,
90 return callbackRequire4AxisPoints (point.
isXOnly(),
96 CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (
const QPointF &posScreen,
97 const QPointF &posGraph)
102 int numberPoints = m_screenInputs.count();
103 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
104 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
105 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
106 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
108 if (numberPoints < 3) {
111 m_screenInputs.push_back (posScreen);
112 m_graphOutputs.push_back (posGraph);
113 numberPoints = m_screenInputs.count();
115 if (numberPoints == 3) {
120 if (anyPointsRepeatPair (m_screenInputs)) {
123 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
126 }
else if (anyPointsRepeatPair (m_graphOutputs)) {
129 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
132 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform)) {
135 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
138 }
else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform)) {
141 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
147 if (m_screenInputs.count() > 2) {
158 const QPointF &posScreen,
159 const QPointF &posGraph)
164 int numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
165 if ((numberPoints == 0) || (posGraph.x () < m_xGraphLow)) { m_xGraphLow = posGraph.x (); }
166 if ((numberPoints == 0) || (posGraph.y () < m_yGraphLow)) { m_yGraphLow = posGraph.y (); }
167 if ((numberPoints == 0) || (posGraph.x () > m_xGraphHigh)) { m_xGraphHigh = posGraph.x (); }
168 if ((numberPoints == 0) || (posGraph.y () > m_yGraphHigh)) { m_yGraphHigh = posGraph.y (); }
170 if (numberPoints < 4) {
175 m_screenInputsX.push_back (posScreen);
176 m_graphOutputsX.push_back (posGraph.x());
180 m_screenInputsY.push_back (posScreen);
181 m_graphOutputsY.push_back (posGraph.y());
185 numberPoints = m_screenInputsX.count() + m_screenInputsY.count();
186 if (numberPoints == 4) {
191 if (m_screenInputsX.count() > 2) {
194 m_errorMessage = QObject::tr (
"Too many x axis points. There should only be two");
197 }
else if (m_screenInputsY.count() > 2) {
200 m_errorMessage = QObject::tr (
"Too many y axis points. There should only be two");
205 if ((m_screenInputsX.count() == 2) &&
206 (m_screenInputsY.count() == 2)) {
213 if (anyPointsRepeatPair (m_screenInputsX) ||
214 anyPointsRepeatPair (m_screenInputsY)) {
217 m_errorMessage = QObject::tr (
"New axis point cannot be at the same screen position as an existing axis point");
220 }
else if (anyPointsRepeatSingle (m_graphOutputsX) ||
221 anyPointsRepeatSingle (m_graphOutputsY)) {
224 m_errorMessage = QObject::tr (
"New axis point cannot have the same graph coordinates as an existing axis point");
227 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform)) {
230 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line on the screen");
233 }
else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform)) {
236 m_errorMessage = QObject::tr (
"No more than two axis points can lie along the same line in graph coordinates");
247 return m_documentAxesPointsRequired;
250 void CallbackAxisPointsAbstract::loadTransforms3 ()
253 m_screenInputsTransform = QTransform (m_screenInputs.at(0).x(), m_screenInputs.at(1).x(), m_screenInputs.at(2).x(),
254 m_screenInputs.at(0).y(), m_screenInputs.at(1).y(), m_screenInputs.at(2).y(),
258 m_graphOutputsTransform = QTransform (m_graphOutputs.at(0).x(), m_graphOutputs.at(1).x(), m_graphOutputs.at(2).x(),
259 m_graphOutputs.at(0).y(), m_graphOutputs.at(1).y(), m_graphOutputs.at(2).y(),
263 void CallbackAxisPointsAbstract::loadTransforms4 ()
265 double x1Screen = m_screenInputsX.at(0).x();
266 double y1Screen = m_screenInputsX.at(0).y();
267 double x2Screen = m_screenInputsX.at(1).x();
268 double y2Screen = m_screenInputsX.at(1).y();
269 double x3Screen = m_screenInputsY.at(0).x();
270 double y3Screen = m_screenInputsY.at(0).y();
271 double x4Screen = m_screenInputsY.at(1).x();
272 double y4Screen = m_screenInputsY.at(1).y();
275 double x1Graph = m_graphOutputsX.at(0);
276 double x2Graph = m_graphOutputsX.at(1);
277 double y3Graph = m_graphOutputsY.at(0);
278 double y4Graph = m_graphOutputsY.at(1);
289 double A00 = x1Screen - x2Screen;
290 double A01 = x4Screen - x3Screen;
291 double A10 = y1Screen - y2Screen;
292 double A11 = y4Screen - y3Screen;
293 double b0 = x1Screen - x3Screen;
294 double b1 = y1Screen - y3Screen;
295 double numeratorx = (b0 * A11 - A01 * b1);
296 double numeratory = (A00 * b1 - b0 * A10);
297 double denominator = (A00 * A11 - A01 * A10);
298 double sx = numeratorx / denominator;
299 double sy = numeratory / denominator;
302 double xIntScreen = (1.0 - sx) * x1Screen + sx * x2Screen;
303 double yIntScreen = (1.0 - sy) * y3Screen + sy * y4Screen;
304 double xIntGraph, yIntGraph;
306 xIntGraph = (1.0 - sx) * x1Graph + sx * x2Graph;
308 xIntGraph = qExp ((1.0 - sx) * qLn (x1Graph) + sx * qLn (x2Graph));
311 yIntGraph = (1.0 - sy) * y3Graph + sy * y4Graph;
313 yIntGraph = qExp ((1.0 - sy) * qLn (y3Graph) + sy * qLn (y4Graph));
317 double distance1 = qSqrt ((x1Screen - xIntScreen) * (x1Screen - xIntScreen) +
318 (y1Screen - yIntScreen) * (y1Screen - yIntScreen));
319 double distance2 = qSqrt ((x2Screen - xIntScreen) * (x2Screen - xIntScreen) +
320 (y2Screen - yIntScreen) * (y2Screen - yIntScreen));
321 double distance3 = qSqrt ((x3Screen - xIntScreen) * (x3Screen - xIntScreen) +
322 (y3Screen - yIntScreen) * (y3Screen - yIntScreen));
323 double distance4 = qSqrt ((x4Screen - xIntScreen) * (x4Screen - xIntScreen) +
324 (y4Screen - yIntScreen) * (y4Screen - yIntScreen));
330 double xFurthestXAxisScreen, yFurthestXAxisScreen, xFurthestYAxisScreen, yFurthestYAxisScreen;
331 double xFurthestXAxisGraph, yFurthestXAxisGraph, xFurthestYAxisGraph, yFurthestYAxisGraph;
332 if (distance1 < distance2) {
333 xFurthestXAxisScreen = x2Screen;
334 yFurthestXAxisScreen = y2Screen;
335 xFurthestXAxisGraph = x2Graph;
336 yFurthestXAxisGraph = yIntGraph;
338 xFurthestXAxisScreen = x1Screen;
339 yFurthestXAxisScreen = y1Screen;
340 xFurthestXAxisGraph = x1Graph;
341 yFurthestXAxisGraph = yIntGraph;
343 if (distance3 < distance4) {
344 xFurthestYAxisScreen = x4Screen;
345 yFurthestYAxisScreen = y4Screen;
346 xFurthestYAxisGraph = xIntGraph;
347 yFurthestYAxisGraph = y4Graph;
349 xFurthestYAxisScreen = x3Screen;
350 yFurthestYAxisScreen = y3Screen;
351 xFurthestYAxisGraph = xIntGraph;
352 yFurthestYAxisGraph = y3Graph;
356 m_screenInputsTransform = QTransform (xIntScreen, xFurthestXAxisScreen, xFurthestYAxisScreen,
357 yIntScreen, yFurthestXAxisScreen, yFurthestYAxisScreen,
361 m_graphOutputsTransform = QTransform (xIntGraph, xFurthestXAxisGraph, xFurthestYAxisGraph,
362 yIntGraph, yFurthestXAxisGraph, yFurthestYAxisGraph,
368 return m_graphOutputsTransform;
373 return m_screenInputsTransform;
378 if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) {
379 return m_screenInputs.count();
381 return m_screenInputsX.count() + m_screenInputsY.count();
385 bool CallbackAxisPointsAbstract::threePointsAreCollinear (
const QTransform &transform)
387 return (transform.determinant() == 0);
QPointF posGraph(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Accessor for graph position. Skip check if copying one instance to another.
QTransform matrixGraph() const
Returns graph coordinates matrix after transformIsDefined has already indicated success.
DocumentAxesPointsRequired documentAxesPointsRequired() const
Number of axes points required for the transformation.
CoordScale coordScaleYRadius() const
Get method for linear/log scale on y/radius.
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.
QString identifier() const
Unique identifier for a specific Point.
Continue normal execution of the search.
CoordScale coordScaleXTheta() const
Get method for linear/log scale on x/theta.
bool isXOnly() const
In DOCUMENT_AXES_POINTS_REQUIRED_4 modes, this is true/false if y/x coordinate is undefined...
Model for DlgSettingsCoords and CmdSettingsCoords.
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.
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.