Engauge Digitizer 2
Loading...
Searching...
No Matches
FormatDegreesMinutesSecondsBase.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2014 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 "Compatibility.h"
8#include "CoordSymbol.h"
10#include "Logger.h"
11#include <QDoubleValidator>
12#include <qmath.h>
13#include <QRegularExpression>
14#include <QStringList>
15#include <QValidator>
16
17const double DEGREES_TO_MINUTES = 60.0;
18const double MINUTES_TO_SECONDS = 60.0;
22
26
30
32{
33 //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSeconds"
34 // << " value=" << value;
35
36 // Only smallest resolution value is floating point
37 bool negative = (value < 0);
38 value = qAbs (value);
39 int degrees = qFloor (value);
40 value -= degrees;
41 int minutes = qFloor (value * DEGREES_TO_MINUTES);
42 value -= minutes * MINUTES_TO_DEGREES;
43 double seconds = value * DEGREES_TO_SECONDS;
44 degrees *= (negative ? -1.0 : 1.0);
45
46 return QString ("%1%2 %3%4 %5%6")
47 .arg (degrees)
48 .arg (QChar (COORD_SYMBOL_DEGREES))
49 .arg (minutes)
50 .arg (QChar (COORD_SYMBOL_MINUTES_PRIME))
51 .arg (seconds)
53}
54
56 bool isNsHemisphere) const
57{
58 //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSecondsNsew"
59 // << " value=" << value
60 // << " isNsHemisphere=" << (isNsHemisphere ? "true" : "false");
61
62 // Only smallest resolution value is floating point
63 bool negative = (value < 0);
64 value = qAbs (value);
65 int degrees = qFloor (value);
66 value -= degrees;
67 int minutes = qFloor (value * DEGREES_TO_MINUTES);
68 value -= minutes * MINUTES_TO_DEGREES;
69 double seconds = value * DEGREES_TO_SECONDS;
70
71 QString hemisphere;
72 if (isNsHemisphere) {
73 hemisphere = (negative ? "S" : "N");
74 } else {
75 hemisphere = (negative ? "W" : "E");
76 }
77
78 return QString ("%1%2 %3%4 %5%6 %7")
79 .arg (degrees)
80 .arg (QChar (COORD_SYMBOL_DEGREES))
81 .arg (minutes)
82 .arg (QChar (COORD_SYMBOL_MINUTES_PRIME))
83 .arg (seconds)
85 .arg (hemisphere);
86}
87
88QValidator::State FormatDegreesMinutesSecondsBase::parseInput (const QString &stringUntrimmed,
89 double &value) const
90{
91 //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::parseInput"
92 // << " string=" << stringUntrimmed.toLatin1().data();
93
94 const QString string = stringUntrimmed.trimmed ();
95
96 if (string.isEmpty()) {
97
98 return QValidator::Intermediate;
99 }
100
101 // Split on spaces
102 QStringList fields = string.split (QRegularExpression ("\\s+"),
104
105 QString field0, field1, field2; // Degrees, minutes and seconds components
106 if (fields.count() == 0) {
107 return QValidator::Invalid; // Empty
108 } else {
109 field0 = fields.at(0);
110 if (fields.count() > 1) {
111 field1 = fields.at(1);
112 if (fields.count() > 2) {
113 field2 = fields.at(2);
114 if (fields.count() > 3) {
115 return QValidator::Invalid; // Too many values
116 }
117 }
118 }
119 }
120
121 stripSymbols (field0,
122 field1,
123 field2);
124
125 int pos;
126
127 // Validators
128 QDoubleValidator valDegrees;
129 QDoubleValidator valMinutesOrSeconds;
130 valMinutesOrSeconds.setBottom (0);
131
132 double valueDegrees = 0, valueMinutes = 0, valueSeconds = 0;
133
134 // Required degrees
135 QValidator::State state = valDegrees.validate (field0,
136 pos);
137 if (state == QValidator::Acceptable) {
138
139 valueDegrees = field0.toDouble();
140
141 if (fields.count() > 1) {
142
143 // Optional minutes
144 state = valMinutesOrSeconds.validate (field1,
145 pos);
146 if (state == QValidator::Acceptable) {
147
148 valueMinutes = field1.toDouble();
149
150 if (fields.count() > 2) {
151
152 // Optional seconds
153 state = valMinutesOrSeconds.validate (field2,
154 pos);
155 if (state == QValidator::Acceptable) {
156
157 valueSeconds = field2.toDouble();
158
159 }
160 }
161 }
162 }
163 }
164
165 if (state == QValidator::Acceptable) {
166 if (valueDegrees < 0) {
167
168 // Apply the negative sign on the degrees components to minutes and seconds components also
169 value = valueDegrees - valueMinutes * MINUTES_TO_DEGREES - valueSeconds * SECONDS_TO_DEGREES;
170
171 } else {
172
173 // All components are positive
174 value = valueDegrees + valueMinutes * MINUTES_TO_DEGREES + valueSeconds * SECONDS_TO_DEGREES;
175
176 }
177 }
178
179 return state;
180}
181
182void FormatDegreesMinutesSecondsBase::stripSymbols (QString &field0,
183 QString &field1,
184 QString &field2) const
185{
186 const int FIELD_WIDTH = 0, BASE_8 = 8, BASE_16 = 16;
187
188 // Clean up degrees symbols (167 or 248 in base 10 which are 247 and 370 in base 8) and single quotes
189 QString strExpDegrees = QString (".*\\0%1$")
190 .arg (COORD_SYMBOL_DEGREES, FIELD_WIDTH, BASE_8);
191
192 QRegularExpression regExpDegrees (strExpDegrees);
193
194 if (regExpDegrees.match (field0).hasMatch()) {
195 field0 = field0.left (field0.count() - 1);
196 }
197
198 // Clean up minutes
199 QString strExpMinutes = QString (".*[\\0%1\\x%2]$")
200 .arg (COORD_SYMBOL_MINUTES_APOSTROPHE, FIELD_WIDTH, BASE_8)
201 .arg (COORD_SYMBOL_MINUTES_PRIME, FIELD_WIDTH, BASE_16);
202
203 QRegularExpression regExpMinutes (strExpMinutes);
204
205 if (regExpMinutes.match (field1).hasMatch()) {
206 field1 = field1.left (field1.count() - 1);
207 }
208
209 // Clean up seconds
210 QString strExpSeconds1Char = QString (".*[\\x%1\\x%2]$")
211 .arg (COORD_SYMBOL_SECONDS_DOUBLE_PRIME, FIELD_WIDTH, BASE_16)
212 .arg (COORD_SYMBOL_SECONDS_QUOTATIONS, FIELD_WIDTH, BASE_16);
213 QString strExpSeconds2Chars = QString (".*\\0%1\\0%2$")
214 .arg (COORD_SYMBOL_MINUTES_PRIME, FIELD_WIDTH, BASE_8)
215 .arg (COORD_SYMBOL_MINUTES_PRIME, FIELD_WIDTH, BASE_8);
216
217 QRegularExpression regExpSeconds1Char (strExpSeconds1Char), regExpSeconds2Chars (strExpSeconds2Chars);
218
219 if (regExpSeconds1Char.match (field2).hasMatch()) {
220 field2 = field2.left (field2.count() - 1);
221 }
222 if (regExpSeconds2Chars.match (field2).hasMatch()) {
223 field2 = field2.left (field2.count() - 2);
224 }
225}
const int COORD_SYMBOL_SECONDS_QUOTATIONS
const int COORD_SYMBOL_MINUTES_APOSTROPHE
const int COORD_SYMBOL_DEGREES
Mathematical symbols for degrees, minutes, seconds input/outputs from/to users.
const int COORD_SYMBOL_MINUTES_PRIME
const int COORD_SYMBOL_SECONDS_DOUBLE_PRIME
const double DEGREES_TO_MINUTES
const double DEGREES_TO_SECONDS
const double SECONDS_TO_DEGREES
const double MINUTES_TO_SECONDS
const double MINUTES_TO_DEGREES
static Qt::SplitBehavior SkipEmptyParts()
SplitBehavior.
QString formatOutputDegreesMinutesSeconds(double value) const
Format as degrees, minutes and seconds without hemisphere.
QValidator::State parseInput(const QString &stringUntrimmed, double &value) const
Parse the input string into a number value.
QString formatOutputDegreesMinutesSecondsNsew(double value, bool isNsHemisphere) const
Format as degrees, minutes and seconds with hemisphere.