Engauge Digitizer 2
Loading...
Searching...
No Matches
GuidelineProjectorConstantT.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5 ******************************************************************************************************/
6
7#include <algorithm>
9#include <QList>
10#include <qmath.h>
11#include <QRectF>
12#include "Transformation.h"
13
17
21
23 const QRectF &sceneRect,
24 double thetaGraphDegrees)
25{
27 calculateCorners (transformation,
28 sceneRect,
33
34 // These containers would be QVector2D to emphasize we are not working with x and y valuees, but
35 // QVector2D would give double/float conversion errors
37 qMax (posGraphBL.x(), posGraphTL.x()));
39 qMax (posGraphTL.x(), posGraphTR.x()));
41 qMax (posGraphTR.x(), posGraphBR.x()));
43 qMax (posGraphBR.x(), posGraphBL.x()));
44
45 // Fix any side that crosses over the discontinuous transition
46 if (qAbs (anglesLeft.y() - anglesLeft.x()) > 180.0) {
47 double temp = anglesLeft.x();
48 anglesLeft.setX (anglesLeft.y());
49 anglesLeft.setY (temp + 360.0);
50 }
51 if (qAbs (anglesTop.y() - anglesTop.x()) > 180.0) {
52 double temp = anglesTop.x();
53 anglesTop.setX (anglesTop.y());
54 anglesTop.setY (temp + 360.0);
55 }
56 if (qAbs (anglesRight.y() - anglesRight.x()) > 180.0) {
57 double temp = anglesRight.x();
58 anglesRight.setX (anglesRight.y());
59 anglesRight.setY (temp + 360.0);
60 }
61 if (qAbs (anglesBottom.y() - anglesBottom.x()) > 180.0) {
62 double temp = anglesBottom.x();
63 anglesBottom.setX (anglesBottom.y());
64 anglesBottom.setY (temp + 360.0);
65 }
66
67 // Which side matches theta?
69 double thetaGraphPlus = thetaGraphDegrees + 360.0;
72
73 // Left side
74 line = intersect (transformation,
78
79 } else if ((anglesTop.x() <= thetaGraphDegrees && thetaGraphDegrees <= anglesTop.y()) ||
81
82 // Top side
83 line = intersect (transformation,
87
88 } else if ((anglesRight.x() <= thetaGraphDegrees && thetaGraphDegrees <= anglesRight.y()) ||
90
91 // Right side
92 line = intersect (transformation,
96
97 } else {
98
99 // Bottom side
100 line = intersect (transformation,
103 posGraphBL);
104
105 }
106
107 return line;
108}
109
111 const QRectF &sceneRect,
112 const QPointF &posScreen)
113{
114 QPointF posGraph;
115 transformation.transformScreenToRawGraph (posScreen, posGraph);
116
117 return fromCoordinateT (transformation,
118 sceneRect,
119 posGraph.x());
120}
121
122QLineF GuidelineProjectorConstantT::intersect (const Transformation &transformation,
123 double thetaGraphDegrees,
124 const QPointF &posPolar1,
125 const QPointF &posPolar2) const
126{
127 QPointF p1, p2; // Cartesian coordinates
129 p1);
131 p2);
132
133 // Intersect y = x tan (theta) = slope * x
134 // (x - x0) / (x1 - x0) = (y - y0) / (y1 - y0)
135 // with divide by zero errors prevented by treating the second equation as either
136 // OPTION 1 (x - x0) = [(x1 - x0) / (y1 - y0)] * (y - y0)
137 // or
138 // OPTION 2 (y - y0) = [(y1 - y0) / (x1 - x0)] * (x - x0)
139
140 double deltaX = p2.x() - p1.x();
141 double deltaY = p2.y() - p1.y();
142
143 double x, y;
144 if (qAbs (deltaX) < qAbs (deltaY)) {
145
146 // Safe to compute since mostly horizontal
148
149 // Use OPTION 1 with x - x0 = fraction * (y - y0)
150 // substituting y = slope * x
151 // we get x * (1 - fraction * slope) = x0 - fraction * y0
152 // since line is mostly vertical (deltaX<deltaY) we know the line y=slope*x
153 // that intersects it is mostly horizontal so it cannot have infinite slope
154 // so the following code has no way to overflow (by inspection)
155 double fraction = deltaX / deltaY;
156 x = (p1.x () - fraction * p1.y ()) / (1.0 - fraction * slope);
157 y = slope * x;
158
159 } else {
160
161 // Safe to compute since mostly vertical. Derived from tan(theta)=y/x and tan(90-theta)=x/y
163
164 // Use OPTION 2 with y - y0 = fraction * (x - x0)
165 // substituting x = y / slope
166 // we get y * (1 - fraction / slope) = y0 - fraction * x0
167 // since line is mostly horizontal (deltaY<deltaX) we know the line y=slope*x
168 // that intersects it is mostly vertical so it cannot have zero slope
169 // so the following code has no way to overflow (by inspection)
170 double fraction = deltaY / deltaX;
171 y = (p1.y () - fraction * p1.x ()) / (1.0 - fraction * slopeInverse);
172 x = slopeInverse * y;
173 }
174
175 // Convert graph coordinate points into screen coordinate line
177 transformation.transformLinearCartesianGraphToScreen (QPointF (0, 0),
179 transformation.transformLinearCartesianGraphToScreen (QPointF (x, y),
181
182 return QLineF (posSceneCenter,
184}
const int INNER_RADIUS_MIN
void calculateCorners(const Transformation &transformation, const QRectF &sceneRect, QPointF &posGraphBL, QPointF &posGraphTL, QPointF &posGraphTR, QPointF &posGraphBR) const
Conpute four corners of scene in graph coordinates.
QLineF fromPosScreen(const Transformation &transformation, const QRectF &sceneRect, const QPointF &posScreen)
Return line through point in screen coordinates.
QLineF fromCoordinateT(const Transformation &transformation, const QRectF &sceneRect, double tGraph)
Return line through theta in graph coordinates.
Affine transformation between screen and graph coordinates, based on digitized axis points.
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
void transformRawGraphToLinearCartesianGraph(const QPointF &pointRaw, QPointF &pointLinearCartesian) const
Convert graph coordinates (linear or log, cartesian or polar) to linear cartesian coordinates.
void transformLinearCartesianGraphToScreen(const QPointF &coordGraph, QPointF &coordScreen) const
Transform from linear cartesian graph coordinates to cartesian pixel screen coordinates.