27 formatter( QChar thousands,
bool showThousands, QChar decimal )
48 return QStringLiteral(
"geographiccoordinate" );
53 return QObject::tr(
"Geographic Coordinate" );
69 std::basic_stringstream<wchar_t> os;
77 return formatLatitude( value, os, context );
81 return formatLongitude( value, os, context );
93 std::unique_ptr< QgsGeographicCoordinateNumericFormat > res = std::make_unique< QgsGeographicCoordinateNumericFormat >();
96 res->mShowLeadingZeros =
configuration.value( QStringLiteral(
"show_leading_zeros" ),
false ).toBool();
97 res->mShowLeadingDegreeZeros =
configuration.value( QStringLiteral(
"show_leading_degree_zeros" ),
false ).toBool();
98 res->mUseSuffix =
configuration.value( QStringLiteral(
"show_suffix" ),
false ).toBool();
105 res.insert( QStringLiteral(
"angle_format" ),
qgsEnumValueToKey( mAngleFormat ) );
106 res.insert( QStringLiteral(
"show_leading_zeros" ), mShowLeadingZeros );
107 res.insert( QStringLiteral(
"show_leading_degree_zeros" ), mShowLeadingDegreeZeros );
108 res.insert( QStringLiteral(
"show_suffix" ), mUseSuffix );
119 mAngleFormat = format;
126 mShowLeadingZeros =
configuration.value( QStringLiteral(
"show_leading_zeros" ),
false ).toBool();
127 mShowLeadingDegreeZeros =
configuration.value( QStringLiteral(
"show_leading_degree_zeros" ),
false ).toBool();
128 mUseSuffix =
configuration.value( QStringLiteral(
"show_suffix" ),
false ).toBool();
133 return mShowLeadingZeros;
138 mShowLeadingZeros = newShowLeadingZeros;
143 return mShowLeadingDegreeZeros;
148 mShowLeadingDegreeZeros = show;
161QString QgsGeographicCoordinateNumericFormat::formatLongitude(
double value, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
163 switch ( mAngleFormat )
166 return formatLongitudeAsDegreesMinutesSeconds( value, ss, context );
168 return formatLongitudeAsDegreesMinutes( value, ss, context );
170 return formatLongitudeAsDegrees( value, ss, context );
175QString QgsGeographicCoordinateNumericFormat::formatLatitude(
double value, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
177 switch ( mAngleFormat )
180 return formatLatitudeAsDegreesMinutesSeconds( value, ss, context );
182 return formatLatitudeAsDegreesMinutes( value, ss, context );
184 return formatLatitudeAsDegrees( value, ss, context );
189QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutesSeconds(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
192 double wrappedY = std::fmod( val, 180.0 );
194 if ( wrappedY > 90.0 )
196 wrappedY = wrappedY - 180.0;
198 else if ( wrappedY < -90.0 )
200 wrappedY = wrappedY + 180.0;
205 int degreesY = int( std::fabs( wrappedY ) );
206 const double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
207 int intMinutesY = int( floatMinutesY );
208 double secondsY = ( floatMinutesY - intMinutesY ) * 60.0;
211 if ( std::round( secondsY * precisionMultiplier ) >= 60 * precisionMultiplier )
213 secondsY = std::max( secondsY - 60, 0.0 );
215 if ( intMinutesY >= 60 )
226 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
237 if ( degreesY == 0 && intMinutesY == 0 && std::round( secondsY * precisionMultiplier ) == 0 )
246 ss << std::fixed << std::setprecision( 0 );
249 strMinutesY = QString::fromStdWString( ss.str() );
250 ss.str( std::wstring() );
254 strSecondsY = QString::fromStdWString( ss.str() );
255 ss.str( std::wstring() );
257 trimTrailingZeros( strSecondsY, context );
260 if ( mShowLeadingZeros && intMinutesY < 10 )
261 strMinutesY =
'0' + strMinutesY;
263 if ( mShowLeadingZeros && secondsY < 10 )
264 strSecondsY =
'0' + strSecondsY;
266 ss << std::fixed << std::setprecision( 0 );
268 QString degreesYStr = QString::fromStdWString( ss.str() );
269 ss.str( std::wstring() );
271 if ( mShowLeadingDegreeZeros )
272 degreesYStr = QString( QStringLiteral(
"00" ) + degreesYStr ).right( 2 );
274 return sign + degreesYStr + QChar( 176 ) +
275 strMinutesY + QChar( 0x2032 ) +
276 strSecondsY + QChar( 0x2033 ) +
280QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutesSeconds(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
283 double wrappedX = std::fmod( val, 360.0 );
285 if ( wrappedX > 180.0 )
287 wrappedX = wrappedX - 360.0;
289 else if ( wrappedX < -180.0 )
291 wrappedX = wrappedX + 360.0;
296 int degreesX = int( std::fabs( wrappedX ) );
297 const double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
298 int intMinutesX = int( floatMinutesX );
299 double secondsX = ( floatMinutesX - intMinutesX ) * 60.0;
302 if ( std::round( secondsX * precisionMultiplier ) >= 60 * precisionMultiplier )
304 secondsX = std::max( secondsX - 60, 0.0 );
306 if ( intMinutesX >= 60 )
317 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
328 if ( degreesX == 0 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
335 if ( degreesX == 180 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
343 ss << std::fixed << std::setprecision( 0 );
346 minutesX = QString::fromStdWString( ss.str() );
347 ss.str( std::wstring() );
351 strSecondsX = QString::fromStdWString( ss.str() );
352 ss.str( std::wstring() );
354 trimTrailingZeros( strSecondsX, context );
357 if ( mShowLeadingZeros && intMinutesX < 10 )
358 minutesX =
'0' + minutesX;
360 if ( mShowLeadingZeros && secondsX < 10 )
361 strSecondsX =
'0' + strSecondsX;
363 ss << std::fixed << std::setprecision( 0 );
365 QString degreesXStr = QString::fromStdWString( ss.str() );
366 ss.str( std::wstring() );
368 if ( mShowLeadingDegreeZeros )
369 degreesXStr = QString( QStringLiteral(
"000" ) + degreesXStr ).right( 3 );
371 return sign + degreesXStr + QChar( 176 ) +
372 minutesX + QChar( 0x2032 ) +
373 strSecondsX + QChar( 0x2033 ) +
377QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutes(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
380 double wrappedY = std::fmod( val, 180.0 );
382 if ( wrappedY > 90.0 )
384 wrappedY = wrappedY - 180.0;
386 else if ( wrappedY < -90.0 )
388 wrappedY = wrappedY + 180.0;
391 int degreesY = int( std::fabs( wrappedY ) );
392 double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
397 if ( std::round( floatMinutesY * precisionMultiplier ) >= 60 * precisionMultiplier )
399 floatMinutesY = std::max( floatMinutesY - 60, 0.0 );
407 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
418 if ( degreesY == 0 && std::round( floatMinutesY * precisionMultiplier ) == 0 )
426 QString strMinutesY = QString::fromStdWString( ss.str() );
427 ss.str( std::wstring() );
429 trimTrailingZeros( strMinutesY, context );
432 if ( mShowLeadingZeros && floatMinutesY < 10 )
433 strMinutesY =
'0' + strMinutesY;
435 ss << std::fixed << std::setprecision( 0 );
437 QString degreesYStr = QString::fromStdWString( ss.str() );
438 ss.str( std::wstring() );
440 if ( mShowLeadingDegreeZeros )
441 degreesYStr = QString( QStringLiteral(
"00" ) + degreesYStr ).right( 2 );
443 return sign + degreesYStr + QChar( 176 ) +
444 strMinutesY + QChar( 0x2032 ) +
448QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutes(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
451 double wrappedX = std::fmod( val, 360.0 );
453 if ( wrappedX > 180.0 )
455 wrappedX = wrappedX - 360.0;
457 else if ( wrappedX < -180.0 )
459 wrappedX = wrappedX + 360.0;
462 int degreesX = int( std::fabs( wrappedX ) );
463 double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
468 if ( std::round( floatMinutesX * precisionMultiplier ) >= 60 * precisionMultiplier )
470 floatMinutesX = std::max( floatMinutesX - 60, 0.0 );
478 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
489 if ( degreesX == 0 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
496 if ( degreesX == 180 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
503 QString strMinutesX = QString::fromStdWString( ss.str() );
504 ss.str( std::wstring() );
506 trimTrailingZeros( strMinutesX, context );
509 if ( mShowLeadingZeros && floatMinutesX < 10 )
510 strMinutesX =
'0' + strMinutesX;
512 ss << std::fixed << std::setprecision( 0 );
514 QString degreesXStr = QString::fromStdWString( ss.str() );
515 ss.str( std::wstring() );
517 if ( mShowLeadingDegreeZeros )
518 degreesXStr = QString( QStringLiteral(
"000" ) + degreesXStr ).right( 3 );
520 return sign + degreesXStr + QChar( 176 ) +
521 strMinutesX + QChar( 0x2032 ) +
525QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegrees(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
528 double wrappedY = std::fmod( val, 180.0 );
530 if ( wrappedY > 90.0 )
532 wrappedY = wrappedY - 180.0;
534 else if ( wrappedY < -90.0 )
536 wrappedY = wrappedY + 180.0;
539 const double absY = std::fabs( wrappedY );
547 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
558 if ( std::round( absY * precisionMultiplier ) == 0 )
566 QString strDegreesY = QString::fromStdWString( ss.str() );
567 ss.str( std::wstring() );
569 trimTrailingZeros( strDegreesY, context );
571 if ( mShowLeadingDegreeZeros && absY < 10 )
572 strDegreesY =
'0' + strDegreesY;
574 return sign + strDegreesY + QChar( 176 ) + hemisphere;
577QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegrees(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
580 double wrappedX = std::fmod( val, 360.0 );
582 if ( wrappedX > 180.0 )
584 wrappedX = wrappedX - 360.0;
586 else if ( wrappedX < -180.0 )
588 wrappedX = wrappedX + 360.0;
591 const double absX = std::fabs( wrappedX );
599 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
610 if ( std::round( absX * precisionMultiplier ) == 0 )
617 if ( std::round( absX * precisionMultiplier ) == 180 * precisionMultiplier )
625 QString strDegreesX = QString::fromStdWString( ss.str() );
626 ss.str( std::wstring() );
628 trimTrailingZeros( strDegreesX, context );
630 if ( mShowLeadingDegreeZeros && absX < 100 )
631 strDegreesX =
'0' + strDegreesX;
632 if ( mShowLeadingDegreeZeros && absX < 10 )
633 strDegreesX =
'0' + strDegreesX;
635 return sign + strDegreesX + QChar( 176 ) + hemisphere;
638void QgsGeographicCoordinateNumericFormat::trimTrailingZeros( QString &input,
const QgsNumericFormatContext &context )
const
643 int trimPoint = input.length() - 1;
645 while ( input.at( trimPoint ) == context.
zeroDigit() )
648 if ( input.at( trimPoint ) == decimal )
651 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