Engauge Digitizer 2
Loading...
Searching...
No Matches
CentipedeEndpointsCartesian.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2020 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
8#include "mmsubs.h"
9#include <qdebug.h>
10#include <qmath.h>
11#include <QPointF>
12#include "Transformation.h"
13
14const int NUM_CIRCLE_POINTS = 400; // Use many points so complicated (linear, log, high dynamic range) interpolation is not needed
15
24
28
29void CentipedeEndpointsCartesian::generatePreviousAndNextPoints (double radiusAboutClick,
30 int i,
31 QPointF &posGraphPrevious,
32 QPointF &posGraphNext,
33 QPointF &posScreenPrevious) const
34{
35 double angleBefore = 2.0 * M_PI * (double) i / (double) NUM_CIRCLE_POINTS;
36 double angleAfter = 2.0 * M_PI * (double) (i + 1) / (double) NUM_CIRCLE_POINTS;
37
38 posScreenPrevious = posClickScreen () + QPointF (radiusAboutClick * qCos (angleBefore),
39 radiusAboutClick * qSin (angleBefore));
40 QPointF posScreenNext = posClickScreen () + QPointF (radiusAboutClick * qCos (angleAfter),
41 radiusAboutClick * qSin (angleAfter));
42
43 transformation().transformScreenToRawGraph (posScreenPrevious,
44 posGraphPrevious);
46 posGraphNext);
47}
48
49QPointF CentipedeEndpointsCartesian::posScreenConstantXCommon (double radius,
50 CentipedeIntersectionType intersectionType) const
51{
52 QPointF posScreenBest;
53 double yBest = (intersectionType == CENTIPEDE_INTERSECTION_HIGH ? 999.9 : -999.9);
54
55 // Click point
56 QPointF posClickGraph;
58 posClickGraph);
59 double xClick = posClickGraph.x();
60
61 // Iterate points around the circle
62 bool isFirst = true;
63 for (int i = 0; i < NUM_CIRCLE_POINTS; i++) {
64 QPointF posGraphPrevious, posGraphNext, posScreenPrevious;
65 generatePreviousAndNextPoints (radius,
66 i,
67 posGraphPrevious,
68 posGraphNext,
69 posScreenPrevious);
70
71 double xGraphPrevious = posGraphPrevious.x();
72 double yGraphPrevious = posGraphPrevious.y();
73 double xGraphNext = posGraphNext.x();
74 double epsilon = qAbs (xGraphPrevious - xGraphNext) / 10.0; // Allow for roundoff
75
76 bool save = false;
77
78 // CENTIPEDE_INTERSECTION_HIGH or CENTIPEDE_INTERSECTION_LOW
79 bool transitionUp = (xGraphPrevious - epsilon <= xClick) && (xClick < xGraphNext + epsilon);
80 bool transitionDown = (xGraphNext - epsilon <= xClick) && (xClick < xGraphPrevious + epsilon);
81
82 if (transitionDown || transitionUp) {
83
84 // Transition occurred so save if best so far
85 if (isFirst ||
86 (intersectionType == CENTIPEDE_INTERSECTION_HIGH && yGraphPrevious > yBest) ||
87 (intersectionType == CENTIPEDE_INTERSECTION_LOW && yGraphPrevious < yBest)) {
88
89 save = true;
90 }
91 }
92
93 if (save) {
94
95 // Best so far so save
96 isFirst = false;
97 posScreenBest = posScreenPrevious;
98 yBest = yGraphPrevious;
99 }
100 }
101
102 return posScreenBest;
103}
104
106{
107 return posScreenConstantXCommon (radius,
109}
110
112{
113 return posScreenConstantXCommon (radius,
115}
116
117QPointF CentipedeEndpointsCartesian::posScreenConstantYCommon (double radius,
118 CentipedeIntersectionType intersectionType) const
119{
120 QPointF posScreenBest;
121 double xBest = 0;
122
123 // Click point
124 QPointF posClickGraph;
126 posClickGraph);
127 double yClick = posClickGraph.y();
128
129 // Iterate points around the circle
130 bool isFirst = true;
131 for (int i = 0; i < NUM_CIRCLE_POINTS; i++) {
132 QPointF posGraphPrevious, posGraphNext, posScreenPrevious;
133 generatePreviousAndNextPoints (radius,
134 i,
135 posGraphPrevious,
136 posGraphNext,
137 posScreenPrevious);
138
139 double xGraphPrevious = posGraphPrevious.x();
140 double yGraphPrevious = posGraphPrevious.y();
141 double yGraphNext = posGraphNext.y();
142 double epsilon = qAbs (yGraphPrevious - yGraphNext) / 10.0; // Allow for roundoff
143
144 bool save = false;
145
146 // CENTIPEDE_INTERSECTION_HIGH or CENTIPEDE_INTERSECTION_LOW
147 bool transitionUp = (yGraphPrevious - epsilon <= yClick) && (yClick < yGraphNext + epsilon);
148 bool transitionDown = (yGraphNext - epsilon <= yClick) && (yClick < yGraphPrevious + epsilon);
149
150 if (transitionDown || transitionUp) {
151
152 // Transition occurred so save if best so far
153 if (isFirst ||
154 (intersectionType == CENTIPEDE_INTERSECTION_HIGH && xGraphPrevious > xBest) ||
155 (intersectionType == CENTIPEDE_INTERSECTION_LOW && xGraphPrevious < xBest)) {
156
157 save = true;
158 }
159 }
160
161 if (save) {
162
163 // Best so far so save
164 isFirst = false;
165 posScreenBest = posScreenPrevious;
166 xBest = xGraphPrevious;
167 }
168 }
169
170 return posScreenBest;
171}
172
174{
175 return posScreenConstantYCommon (radius,
177}
178
180{
181 return posScreenConstantYCommon (radius,
183}
const int NUM_CIRCLE_POINTS
CentipedeIntersectionType
Intersect with one of the following XT or YT coordinates for constant YR or XT respectively.
@ CENTIPEDE_INTERSECTION_HIGH
Intersection along circle perimeter with lowest value of XT or YR.
@ CENTIPEDE_INTERSECTION_LOW
QPointF posClickScreen() const
Center of circle in screen coordinates.
const DocumentModelGuideline & modelGuideline() const
Settings.
const Transformation & transformation() const
Transformation which is static through the entire lifetime of the Centipede class instances.
CentipedeEndpointsAbstract(const DocumentModelGuideline &modelGuideline, const Transformation &transformation, const QPointF &posClickScreen)
Constructor with individual coordinates.
QPointF posScreenConstantYForLowX(double radius) const
Screen point for Y value of circle/coordinate intersection in the decreasing X direction.
QPointF posScreenConstantXForLowY(double radius) const
Screen point for X value of circle/coordinate intersection in the decreasing Y direction.
CentipedeEndpointsCartesian(const DocumentModelGuideline &modelGuideline, const Transformation &transformation, const QPointF &posClickScreen)
Constructor with individual coordinates.
QPointF posScreenConstantYForHighX(double radius) const
Screen point for Y value of circle/coordinate intersection in the increasing X direction.
QPointF posScreenConstantXForHighY(double radius) const
Screen point for X value of circle/coordinate intersection in the increasing Y direction.
Model for managing the coordinate values corresponding Guidelines.
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.