28 formatter( QChar thousands,
bool showThousands, QChar decimal )
49 return QStringLiteral(
"geographiccoordinate" );
54 return QObject::tr(
"Geographic Coordinate" );
70 std::basic_stringstream<wchar_t> os;
78 return formatLatitude( value, os, context );
82 return formatLongitude( value, os, context );
94 std::unique_ptr< QgsGeographicCoordinateNumericFormat > res = std::make_unique< QgsGeographicCoordinateNumericFormat >();
97 res->mShowLeadingZeros =
configuration.value( QStringLiteral(
"show_leading_zeros" ),
false ).toBool();
98 res->mShowLeadingDegreeZeros =
configuration.value( QStringLiteral(
"show_leading_degree_zeros" ),
false ).toBool();
99 res->mUseSuffix =
configuration.value( QStringLiteral(
"show_suffix" ),
false ).toBool();
100 return res.release();
106 res.insert( QStringLiteral(
"angle_format" ),
qgsEnumValueToKey( mAngleFormat ) );
107 res.insert( QStringLiteral(
"show_leading_zeros" ), mShowLeadingZeros );
108 res.insert( QStringLiteral(
"show_leading_degree_zeros" ), mShowLeadingDegreeZeros );
109 res.insert( QStringLiteral(
"show_suffix" ), mUseSuffix );
120 mAngleFormat = format;
127 mShowLeadingZeros =
configuration.value( QStringLiteral(
"show_leading_zeros" ),
false ).toBool();
128 mShowLeadingDegreeZeros =
configuration.value( QStringLiteral(
"show_leading_degree_zeros" ),
false ).toBool();
129 mUseSuffix =
configuration.value( QStringLiteral(
"show_suffix" ),
false ).toBool();
134 return mShowLeadingZeros;
139 mShowLeadingZeros = newShowLeadingZeros;
144 return mShowLeadingDegreeZeros;
149 mShowLeadingDegreeZeros = show;
162QString QgsGeographicCoordinateNumericFormat::formatLongitude(
double value, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
164 switch ( mAngleFormat )
167 return formatLongitudeAsDegreesMinutesSeconds( value, ss, context );
169 return formatLongitudeAsDegreesMinutes( value, ss, context );
171 return formatLongitudeAsDegrees( value, ss, context );
176QString QgsGeographicCoordinateNumericFormat::formatLatitude(
double value, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
178 switch ( mAngleFormat )
181 return formatLatitudeAsDegreesMinutesSeconds( value, ss, context );
183 return formatLatitudeAsDegreesMinutes( value, ss, context );
185 return formatLatitudeAsDegrees( value, ss, context );
190QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutesSeconds(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
193 double wrappedY = std::fmod( val, 180.0 );
195 if ( wrappedY > 90.0 )
197 wrappedY = wrappedY - 180.0;
199 else if ( wrappedY < -90.0 )
201 wrappedY = wrappedY + 180.0;
206 int degreesY = int( std::fabs( wrappedY ) );
207 const double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
208 int intMinutesY = int( floatMinutesY );
209 double secondsY = ( floatMinutesY - intMinutesY ) * 60.0;
212 if ( std::round( secondsY * precisionMultiplier ) >= 60 * precisionMultiplier )
214 secondsY = std::max( secondsY - 60, 0.0 );
216 if ( intMinutesY >= 60 )
227 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
238 if ( degreesY == 0 && intMinutesY == 0 && std::round( secondsY * precisionMultiplier ) == 0 )
247 ss << std::fixed << std::setprecision( 0 );
250 strMinutesY = QString::fromStdWString( ss.str() );
251 ss.str( std::wstring() );
255 strSecondsY = QString::fromStdWString( ss.str() );
256 ss.str( std::wstring() );
258 trimTrailingZeros( strSecondsY, context );
261 if ( mShowLeadingZeros && intMinutesY < 10 )
262 strMinutesY =
'0' + strMinutesY;
264 if ( mShowLeadingZeros && secondsY < 10 )
265 strSecondsY =
'0' + strSecondsY;
267 ss << std::fixed << std::setprecision( 0 );
269 QString degreesYStr = QString::fromStdWString( ss.str() );
270 ss.str( std::wstring() );
272 if ( mShowLeadingDegreeZeros )
273 degreesYStr = QString( QStringLiteral(
"00" ) + degreesYStr ).right( 2 );
275 return sign + degreesYStr + QChar( 176 ) +
276 strMinutesY + QChar( 0x2032 ) +
277 strSecondsY + QChar( 0x2033 ) +
281QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutesSeconds(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
284 double wrappedX = std::fmod( val, 360.0 );
286 if ( wrappedX > 180.0 )
288 wrappedX = wrappedX - 360.0;
290 else if ( wrappedX < -180.0 )
292 wrappedX = wrappedX + 360.0;
297 int degreesX = int( std::fabs( wrappedX ) );
298 const double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
299 int intMinutesX = int( floatMinutesX );
300 double secondsX = ( floatMinutesX - intMinutesX ) * 60.0;
303 if ( std::round( secondsX * precisionMultiplier ) >= 60 * precisionMultiplier )
305 secondsX = std::max( secondsX - 60, 0.0 );
307 if ( intMinutesX >= 60 )
318 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
329 if ( degreesX == 0 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
336 if ( degreesX == 180 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
344 ss << std::fixed << std::setprecision( 0 );
347 minutesX = QString::fromStdWString( ss.str() );
348 ss.str( std::wstring() );
352 strSecondsX = QString::fromStdWString( ss.str() );
353 ss.str( std::wstring() );
355 trimTrailingZeros( strSecondsX, context );
358 if ( mShowLeadingZeros && intMinutesX < 10 )
359 minutesX =
'0' + minutesX;
361 if ( mShowLeadingZeros && secondsX < 10 )
362 strSecondsX =
'0' + strSecondsX;
364 ss << std::fixed << std::setprecision( 0 );
366 QString degreesXStr = QString::fromStdWString( ss.str() );
367 ss.str( std::wstring() );
369 if ( mShowLeadingDegreeZeros )
370 degreesXStr = QString( QStringLiteral(
"000" ) + degreesXStr ).right( 3 );
372 return sign + degreesXStr + QChar( 176 ) +
373 minutesX + QChar( 0x2032 ) +
374 strSecondsX + QChar( 0x2033 ) +
378QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutes(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
381 double wrappedY = std::fmod( val, 180.0 );
383 if ( wrappedY > 90.0 )
385 wrappedY = wrappedY - 180.0;
387 else if ( wrappedY < -90.0 )
389 wrappedY = wrappedY + 180.0;
392 int degreesY = int( std::fabs( wrappedY ) );
393 double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
398 if ( std::round( floatMinutesY * precisionMultiplier ) >= 60 * precisionMultiplier )
400 floatMinutesY = std::max( floatMinutesY - 60, 0.0 );
408 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
419 if ( degreesY == 0 && std::round( floatMinutesY * precisionMultiplier ) == 0 )
427 QString strMinutesY = QString::fromStdWString( ss.str() );
428 ss.str( std::wstring() );
430 trimTrailingZeros( strMinutesY, context );
433 if ( mShowLeadingZeros && floatMinutesY < 10 )
434 strMinutesY =
'0' + strMinutesY;
436 ss << std::fixed << std::setprecision( 0 );
438 QString degreesYStr = QString::fromStdWString( ss.str() );
439 ss.str( std::wstring() );
441 if ( mShowLeadingDegreeZeros )
442 degreesYStr = QString( QStringLiteral(
"00" ) + degreesYStr ).right( 2 );
444 return sign + degreesYStr + QChar( 176 ) +
445 strMinutesY + QChar( 0x2032 ) +
449QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutes(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
452 double wrappedX = std::fmod( val, 360.0 );
454 if ( wrappedX > 180.0 )
456 wrappedX = wrappedX - 360.0;
458 else if ( wrappedX < -180.0 )
460 wrappedX = wrappedX + 360.0;
463 int degreesX = int( std::fabs( wrappedX ) );
464 double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
469 if ( std::round( floatMinutesX * precisionMultiplier ) >= 60 * precisionMultiplier )
471 floatMinutesX = std::max( floatMinutesX - 60, 0.0 );
479 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
490 if ( degreesX == 0 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
497 if ( degreesX == 180 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
504 QString strMinutesX = QString::fromStdWString( ss.str() );
505 ss.str( std::wstring() );
507 trimTrailingZeros( strMinutesX, context );
510 if ( mShowLeadingZeros && floatMinutesX < 10 )
511 strMinutesX =
'0' + strMinutesX;
513 ss << std::fixed << std::setprecision( 0 );
515 QString degreesXStr = QString::fromStdWString( ss.str() );
516 ss.str( std::wstring() );
518 if ( mShowLeadingDegreeZeros )
519 degreesXStr = QString( QStringLiteral(
"000" ) + degreesXStr ).right( 3 );
521 return sign + degreesXStr + QChar( 176 ) +
522 strMinutesX + QChar( 0x2032 ) +
526QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegrees(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
529 double wrappedY = std::fmod( val, 180.0 );
531 if ( wrappedY > 90.0 )
533 wrappedY = wrappedY - 180.0;
535 else if ( wrappedY < -90.0 )
537 wrappedY = wrappedY + 180.0;
540 const double absY = std::fabs( wrappedY );
548 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
559 if ( std::round( absY * precisionMultiplier ) == 0 )
567 QString strDegreesY = QString::fromStdWString( ss.str() );
568 ss.str( std::wstring() );
570 trimTrailingZeros( strDegreesY, context );
572 if ( mShowLeadingDegreeZeros && absY < 10 )
573 strDegreesY =
'0' + strDegreesY;
575 return sign + strDegreesY + QChar( 176 ) + hemisphere;
578QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegrees(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
581 double wrappedX = std::fmod( val, 360.0 );
583 if ( wrappedX > 180.0 )
585 wrappedX = wrappedX - 360.0;
587 else if ( wrappedX < -180.0 )
589 wrappedX = wrappedX + 360.0;
592 const double absX = std::fabs( wrappedX );
600 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
611 if ( std::round( absX * precisionMultiplier ) == 0 )
618 if ( std::round( absX * precisionMultiplier ) == 180 * precisionMultiplier )
626 QString strDegreesX = QString::fromStdWString( ss.str() );
627 ss.str( std::wstring() );
629 trimTrailingZeros( strDegreesX, context );
631 if ( mShowLeadingDegreeZeros && absX < 100 )
632 strDegreesX =
'0' + strDegreesX;
633 if ( mShowLeadingDegreeZeros && absX < 10 )
634 strDegreesX =
'0' + strDegreesX;
636 return sign + strDegreesX + QChar( 176 ) + hemisphere;
639void QgsGeographicCoordinateNumericFormat::trimTrailingZeros( QString &input,
const QgsNumericFormatContext &context )
const
644 int trimPoint = input.length() - 1;
646 while ( input.at( trimPoint ) == context.
zeroDigit() )
649 if ( input.at( trimPoint ) == decimal )
652 input.truncate( trimPoint + 1 );
A context for numeric formats.
QChar negativeSign() const
Returns the negative sign character.
QChar thousandsSeparator() const
Returns the thousands separator character.
QChar zeroDigit() const
Returns the zero digit character.
Interpretation interpretation() const
Returns the interpretation of the numbers being converted.
QChar decimalSeparator() const
Returns the decimal separator character.
@ Latitude
Latitude values.
@ Longitude
Longitude values.
The class is used as a container of context for various read/write operations on other objects.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
#define BUILTIN_UNREACHABLE