@@ -134,46 +134,188 @@ QString QgsPoint::toString( int thePrecision ) const
134
134
return QString ( " %1,%2" ).arg ( x ).arg ( y );
135
135
}
136
136
137
- QString QgsPoint::toDegreesMinutesSeconds ( int thePrecision ) const
137
+ QString QgsPoint::toDegreesMinutesSeconds ( int thePrecision, const bool useSuffix, const bool padded ) const
138
138
{
139
- int myDegreesX = int ( qAbs ( m_x ) );
140
- float myFloatMinutesX = float (( qAbs ( m_x ) - myDegreesX ) * 60 );
139
+ // first, limit longitude to -360 to 360 degree range
140
+ double myWrappedX = fmod ( m_x, 360.0 );
141
+ // next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
142
+ if ( myWrappedX > 180.0 )
143
+ {
144
+ myWrappedX = myWrappedX - 360.0 ;
145
+ }
146
+ else if ( myWrappedX < -180.0 )
147
+ {
148
+ myWrappedX = myWrappedX + 360.0 ;
149
+ }
150
+
151
+ int myDegreesX = int ( qAbs ( myWrappedX ) );
152
+ double myFloatMinutesX = double (( qAbs ( myWrappedX ) - myDegreesX ) * 60 );
141
153
int myIntMinutesX = int ( myFloatMinutesX );
142
- float mySecondsX = float ( myFloatMinutesX - myIntMinutesX ) * 60 ;
154
+ double mySecondsX = double ( myFloatMinutesX - myIntMinutesX ) * 60 ;
143
155
144
156
int myDegreesY = int ( qAbs ( m_y ) );
145
- float myFloatMinutesY = float (( qAbs ( m_y ) - myDegreesY ) * 60 );
157
+ double myFloatMinutesY = double (( qAbs ( m_y ) - myDegreesY ) * 60 );
146
158
int myIntMinutesY = int ( myFloatMinutesY );
147
- float mySecondsY = float ( myFloatMinutesY - myIntMinutesY ) * 60 ;
159
+ double mySecondsY = double ( myFloatMinutesY - myIntMinutesY ) * 60 ;
148
160
149
- QString myXHemisphere = m_x < 0 ? QObject::tr ( " W" ) : QObject::tr ( " E" );
150
- QString myYHemisphere = m_y < 0 ? QObject::tr ( " S" ) : QObject::tr ( " N" );
151
- QString rep = QString::number ( myDegreesX ) + QChar ( 176 ) +
152
- QString::number ( myIntMinutesX ) + QString ( " '" ) +
153
- QString::number ( mySecondsX, ' f' , thePrecision ) + QString ( " \" " ) +
161
+ // make sure rounding to specified precision doesn't create seconds >= 60
162
+ if ( qRound ( mySecondsX * pow ( 10 , thePrecision ) ) >= 60 * pow ( 10 , thePrecision ) )
163
+ {
164
+ mySecondsX = qMax ( mySecondsX - 60 , 0.0 );
165
+ myIntMinutesX++;
166
+ if ( myIntMinutesX >= 60 )
167
+ {
168
+ myIntMinutesX -= 60 ;
169
+ myDegreesX++;
170
+ }
171
+ }
172
+ if ( qRound ( mySecondsY * pow ( 10 , thePrecision ) ) >= 60 * pow ( 10 , thePrecision ) )
173
+ {
174
+ mySecondsY = qMax ( mySecondsY - 60 , 0.0 );
175
+ myIntMinutesY++;
176
+ if ( myIntMinutesY >= 60 )
177
+ {
178
+ myIntMinutesY -= 60 ;
179
+ myDegreesY++;
180
+ }
181
+ }
182
+
183
+ QString myXHemisphere;
184
+ QString myYHemisphere;
185
+ QString myXSign;
186
+ QString myYSign;
187
+ if ( useSuffix )
188
+ {
189
+ myXHemisphere = myWrappedX < 0 ? QObject::tr ( " W" ) : QObject::tr ( " E" );
190
+ myYHemisphere = m_y < 0 ? QObject::tr ( " S" ) : QObject::tr ( " N" );
191
+ }
192
+ else
193
+ {
194
+ if ( myWrappedX < 0 )
195
+ {
196
+ myXSign = QObject::tr ( " -" );
197
+ }
198
+ if ( m_y < 0 )
199
+ {
200
+ myYSign = QObject::tr ( " -" );
201
+ }
202
+ }
203
+ // check if coordinate is all zeros for the specified precision, and if so,
204
+ // remove the sign and hemisphere strings
205
+ if ( myDegreesX == 0 && myIntMinutesX == 0 && qRound ( mySecondsX * pow ( 10 , thePrecision ) ) == 0 )
206
+ {
207
+ myXSign = QString ();
208
+ myXHemisphere = QString ();
209
+ }
210
+ if ( myDegreesY == 0 && myIntMinutesY == 0 && qRound ( mySecondsY * pow ( 10 , thePrecision ) ) == 0 )
211
+ {
212
+ myYSign = QString ();
213
+ myYHemisphere = QString ();
214
+ }
215
+ // also remove directional prefix from 180 degree longitudes
216
+ if ( myDegreesX == 180 && myIntMinutesX == 0 && qRound ( mySecondsX * pow ( 10 , thePrecision ) ) == 0 )
217
+ {
218
+ myXHemisphere = QString ();
219
+ }
220
+ // pad minutes with leading digits if required
221
+ QString myMinutesX = padded ? QString ( " %1" ).arg ( myIntMinutesX, 2 , 10 , QChar ( ' 0' ) ) : QString::number ( myIntMinutesX );
222
+ QString myMinutesY = padded ? QString ( " %1" ).arg ( myIntMinutesY, 2 , 10 , QChar ( ' 0' ) ) : QString::number ( myIntMinutesY );
223
+ // pad seconds with leading digits if required
224
+ int digits = 2 + ( thePrecision == 0 ? 0 : 1 + thePrecision ); // 1 for decimal place if required
225
+ QString myStrSecondsX = padded ? QString ( " %1" ).arg ( mySecondsX, digits, ' f' , thePrecision, QChar ( ' 0' ) ) : QString::number ( mySecondsX, ' f' , thePrecision );
226
+ QString myStrSecondsY = padded ? QString ( " %1" ).arg ( mySecondsY, digits, ' f' , thePrecision, QChar ( ' 0' ) ) : QString::number ( mySecondsY, ' f' , thePrecision );
227
+
228
+ QString rep = myXSign + QString::number ( myDegreesX ) + QChar ( 176 ) +
229
+ myMinutesX + QString ( " '" ) +
230
+ myStrSecondsX + QString ( " \" " ) +
154
231
myXHemisphere + QString ( " ," ) +
155
- QString::number ( myDegreesY ) + QChar ( 176 ) +
156
- QString::number ( myIntMinutesY ) + QString ( " '" ) +
157
- QString::number ( mySecondsY, ' f ' , thePrecision ) + QString ( " \" " ) +
232
+ myYSign + QString::number ( myDegreesY ) + QChar ( 176 ) +
233
+ myMinutesY + QString ( " '" ) +
234
+ myStrSecondsY + QString ( " \" " ) +
158
235
myYHemisphere;
159
236
return rep;
160
237
}
161
238
162
- QString QgsPoint::toDegreesMinutes ( int thePrecision ) const
239
+ QString QgsPoint::toDegreesMinutes ( int thePrecision, const bool useSuffix, const bool padded ) const
163
240
{
164
- int myDegreesX = int ( qAbs ( m_x ) );
165
- float myFloatMinutesX = float (( qAbs ( m_x ) - myDegreesX ) * 60 );
241
+ // first, limit longitude to -360 to 360 degree range
242
+ double myWrappedX = fmod ( m_x, 360.0 );
243
+ // next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
244
+ if ( myWrappedX > 180.0 )
245
+ {
246
+ myWrappedX = myWrappedX - 360.0 ;
247
+ }
248
+ else if ( myWrappedX < -180.0 )
249
+ {
250
+ myWrappedX = myWrappedX + 360.0 ;
251
+ }
252
+
253
+ int myDegreesX = int ( qAbs ( myWrappedX ) );
254
+ double myFloatMinutesX = double (( qAbs ( myWrappedX ) - myDegreesX ) * 60 );
166
255
167
256
int myDegreesY = int ( qAbs ( m_y ) );
168
- float myFloatMinutesY = float (( qAbs ( m_y ) - myDegreesY ) * 60 );
257
+ double myFloatMinutesY = double (( qAbs ( m_y ) - myDegreesY ) * 60 );
258
+
259
+ // make sure rounding to specified precision doesn't create minutes >= 60
260
+ if ( qRound ( myFloatMinutesX * pow ( 10 , thePrecision ) ) >= 60 * pow ( 10 , thePrecision ) )
261
+ {
262
+ myFloatMinutesX = qMax ( myFloatMinutesX - 60 , 0.0 );
263
+ myDegreesX++;
264
+ }
265
+ if ( qRound ( myFloatMinutesY * pow ( 10 , thePrecision ) ) >= 60 * pow ( 10 , thePrecision ) )
266
+ {
267
+ myFloatMinutesY = qMax ( myFloatMinutesY - 60 , 0.0 );
268
+ myDegreesY++;
269
+ }
270
+
271
+ QString myXHemisphere;
272
+ QString myYHemisphere;
273
+ QString myXSign;
274
+ QString myYSign;
275
+ if ( useSuffix )
276
+ {
277
+ myXHemisphere = myWrappedX < 0 ? QObject::tr ( " W" ) : QObject::tr ( " E" );
278
+ myYHemisphere = m_y < 0 ? QObject::tr ( " S" ) : QObject::tr ( " N" );
279
+ }
280
+ else
281
+ {
282
+ if ( myWrappedX < 0 )
283
+ {
284
+ myXSign = QObject::tr ( " -" );
285
+ }
286
+ if ( m_y < 0 )
287
+ {
288
+ myYSign = QObject::tr ( " -" );
289
+ }
290
+ }
291
+ // check if coordinate is all zeros for the specified precision, and if so,
292
+ // remove the sign and hemisphere strings
293
+ if ( myDegreesX == 0 && qRound ( myFloatMinutesX * pow ( 10 , thePrecision ) ) == 0 )
294
+ {
295
+ myXSign = QString ();
296
+ myXHemisphere = QString ();
297
+ }
298
+ if ( myDegreesY == 0 && qRound ( myFloatMinutesY * pow ( 10 , thePrecision ) ) == 0 )
299
+ {
300
+ myYSign = QString ();
301
+ myYHemisphere = QString ();
302
+ }
303
+ // also remove directional prefix from 180 degree longitudes
304
+ if ( myDegreesX == 180 && qRound ( myFloatMinutesX * pow ( 10 , thePrecision ) ) == 0 )
305
+ {
306
+ myXHemisphere = QString ();
307
+ }
308
+
309
+ // pad minutes with leading digits if required
310
+ int digits = 2 + ( thePrecision == 0 ? 0 : 1 + thePrecision ); // 1 for decimal place if required
311
+ QString myStrMinutesX = padded ? QString ( " %1" ).arg ( myFloatMinutesX, digits, ' f' , thePrecision, QChar ( ' 0' ) ) : QString::number ( myFloatMinutesX, ' f' , thePrecision );
312
+ QString myStrMinutesY = padded ? QString ( " %1" ).arg ( myFloatMinutesY, digits, ' f' , thePrecision, QChar ( ' 0' ) ) : QString::number ( myFloatMinutesY, ' f' , thePrecision );
169
313
170
- QString myXHemisphere = m_x < 0 ? QObject::tr ( " W" ) : QObject::tr ( " E" );
171
- QString myYHemisphere = m_y < 0 ? QObject::tr ( " S" ) : QObject::tr ( " N" );
172
- QString rep = QString::number ( myDegreesX ) + QChar ( 176 ) +
173
- QString::number ( myFloatMinutesX, ' f' , thePrecision ) + QString ( " '" ) +
314
+ QString rep = myXSign + QString::number ( myDegreesX ) + QChar ( 176 ) +
315
+ myStrMinutesX + QString ( " '" ) +
174
316
myXHemisphere + QString ( " ," ) +
175
- QString::number ( myDegreesY ) + QChar ( 176 ) +
176
- QString::number ( myFloatMinutesY, ' f ' , thePrecision ) + QString ( " '" ) +
317
+ myYSign + QString::number ( myDegreesY ) + QChar ( 176 ) +
318
+ myStrMinutesY + QString ( " '" ) +
177
319
myYHemisphere;
178
320
return rep;
179
321
}
0 commit comments