17#include "moc_qgscoordinatenumericformat.cpp"
29 formatter( QChar thousands,
bool showThousands, QChar decimal )
50 return QStringLiteral(
"geographiccoordinate" );
55 return QObject::tr(
"Geographic Coordinate" );
71 std::basic_stringstream<wchar_t> os;
79 return formatLatitude( value, os, context );
83 return formatLongitude( value, os, context );
95 std::unique_ptr< QgsGeographicCoordinateNumericFormat > res = std::make_unique< QgsGeographicCoordinateNumericFormat >();
98 res->mShowLeadingZeros =
configuration.value( QStringLiteral(
"show_leading_zeros" ),
false ).toBool();
99 res->mShowLeadingDegreeZeros =
configuration.value( QStringLiteral(
"show_leading_degree_zeros" ),
false ).toBool();
100 res->mUseSuffix =
configuration.value( QStringLiteral(
"show_suffix" ),
false ).toBool();
101 return res.release();
107 res.insert( QStringLiteral(
"angle_format" ),
qgsEnumValueToKey( mAngleFormat ) );
108 res.insert( QStringLiteral(
"show_leading_zeros" ), mShowLeadingZeros );
109 res.insert( QStringLiteral(
"show_leading_degree_zeros" ), mShowLeadingDegreeZeros );
110 res.insert( QStringLiteral(
"show_suffix" ), mUseSuffix );
121 mAngleFormat = format;
128 mShowLeadingZeros =
configuration.value( QStringLiteral(
"show_leading_zeros" ),
false ).toBool();
129 mShowLeadingDegreeZeros =
configuration.value( QStringLiteral(
"show_leading_degree_zeros" ),
false ).toBool();
130 mUseSuffix =
configuration.value( QStringLiteral(
"show_suffix" ),
false ).toBool();
135 return mShowLeadingZeros;
140 mShowLeadingZeros = newShowLeadingZeros;
145 return mShowLeadingDegreeZeros;
150 mShowLeadingDegreeZeros = show;
163QString QgsGeographicCoordinateNumericFormat::formatLongitude(
double value, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
165 switch ( mAngleFormat )
168 return formatLongitudeAsDegreesMinutesSeconds( value, ss, context );
170 return formatLongitudeAsDegreesMinutes( value, ss, context );
172 return formatLongitudeAsDegrees( value, ss, context );
177QString QgsGeographicCoordinateNumericFormat::formatLatitude(
double value, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
179 switch ( mAngleFormat )
182 return formatLatitudeAsDegreesMinutesSeconds( value, ss, context );
184 return formatLatitudeAsDegreesMinutes( value, ss, context );
186 return formatLatitudeAsDegrees( value, ss, context );
191QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutesSeconds(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
194 double wrappedY = std::fmod( val, 180.0 );
196 if ( wrappedY > 90.0 )
198 wrappedY = wrappedY - 180.0;
200 else if ( wrappedY < -90.0 )
202 wrappedY = wrappedY + 180.0;
207 int degreesY = int( std::fabs( wrappedY ) );
208 const double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
209 int intMinutesY = int( floatMinutesY );
210 double secondsY = ( floatMinutesY - intMinutesY ) * 60.0;
213 if ( std::round( secondsY * precisionMultiplier ) >= 60 * precisionMultiplier )
215 secondsY = std::max( secondsY - 60, 0.0 );
217 if ( intMinutesY >= 60 )
228 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
239 if ( degreesY == 0 && intMinutesY == 0 && std::round( secondsY * precisionMultiplier ) == 0 )
248 ss << std::fixed << std::setprecision( 0 );
251 strMinutesY = QString::fromStdWString( ss.str() );
252 ss.str( std::wstring() );
256 strSecondsY = QString::fromStdWString( ss.str() );
257 ss.str( std::wstring() );
259 trimTrailingZeros( strSecondsY, context );
262 if ( mShowLeadingZeros && intMinutesY < 10 )
263 strMinutesY =
'0' + strMinutesY;
265 if ( mShowLeadingZeros && secondsY < 10 )
266 strSecondsY =
'0' + strSecondsY;
268 ss << std::fixed << std::setprecision( 0 );
270 QString degreesYStr = QString::fromStdWString( ss.str() );
271 ss.str( std::wstring() );
273 if ( mShowLeadingDegreeZeros )
274 degreesYStr = QString( QStringLiteral(
"00" ) + degreesYStr ).right( 2 );
276 return sign + degreesYStr + QChar( 176 ) +
277 strMinutesY + QChar( 0x2032 ) +
278 strSecondsY + QChar( 0x2033 ) +
282QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutesSeconds(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
285 double wrappedX = std::fmod( val, 360.0 );
287 if ( wrappedX > 180.0 )
289 wrappedX = wrappedX - 360.0;
291 else if ( wrappedX < -180.0 )
293 wrappedX = wrappedX + 360.0;
298 int degreesX = int( std::fabs( wrappedX ) );
299 const double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
300 int intMinutesX = int( floatMinutesX );
301 double secondsX = ( floatMinutesX - intMinutesX ) * 60.0;
304 if ( std::round( secondsX * precisionMultiplier ) >= 60 * precisionMultiplier )
306 secondsX = std::max( secondsX - 60, 0.0 );
308 if ( intMinutesX >= 60 )
319 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
330 if ( degreesX == 0 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
337 if ( degreesX == 180 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
345 ss << std::fixed << std::setprecision( 0 );
348 minutesX = QString::fromStdWString( ss.str() );
349 ss.str( std::wstring() );
353 strSecondsX = QString::fromStdWString( ss.str() );
354 ss.str( std::wstring() );
356 trimTrailingZeros( strSecondsX, context );
359 if ( mShowLeadingZeros && intMinutesX < 10 )
360 minutesX =
'0' + minutesX;
362 if ( mShowLeadingZeros && secondsX < 10 )
363 strSecondsX =
'0' + strSecondsX;
365 ss << std::fixed << std::setprecision( 0 );
367 QString degreesXStr = QString::fromStdWString( ss.str() );
368 ss.str( std::wstring() );
370 if ( mShowLeadingDegreeZeros )
371 degreesXStr = QString( QStringLiteral(
"000" ) + degreesXStr ).right( 3 );
373 return sign + degreesXStr + QChar( 176 ) +
374 minutesX + QChar( 0x2032 ) +
375 strSecondsX + QChar( 0x2033 ) +
379QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutes(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
382 double wrappedY = std::fmod( val, 180.0 );
384 if ( wrappedY > 90.0 )
386 wrappedY = wrappedY - 180.0;
388 else if ( wrappedY < -90.0 )
390 wrappedY = wrappedY + 180.0;
393 int degreesY = int( std::fabs( wrappedY ) );
394 double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
399 if ( std::round( floatMinutesY * precisionMultiplier ) >= 60 * precisionMultiplier )
401 floatMinutesY = std::max( floatMinutesY - 60, 0.0 );
409 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
420 if ( degreesY == 0 && std::round( floatMinutesY * precisionMultiplier ) == 0 )
428 QString strMinutesY = QString::fromStdWString( ss.str() );
429 ss.str( std::wstring() );
431 trimTrailingZeros( strMinutesY, context );
434 if ( mShowLeadingZeros && floatMinutesY < 10 )
435 strMinutesY =
'0' + strMinutesY;
437 ss << std::fixed << std::setprecision( 0 );
439 QString degreesYStr = QString::fromStdWString( ss.str() );
440 ss.str( std::wstring() );
442 if ( mShowLeadingDegreeZeros )
443 degreesYStr = QString( QStringLiteral(
"00" ) + degreesYStr ).right( 2 );
445 return sign + degreesYStr + QChar( 176 ) +
446 strMinutesY + QChar( 0x2032 ) +
450QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutes(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
453 double wrappedX = std::fmod( val, 360.0 );
455 if ( wrappedX > 180.0 )
457 wrappedX = wrappedX - 360.0;
459 else if ( wrappedX < -180.0 )
461 wrappedX = wrappedX + 360.0;
464 int degreesX = int( std::fabs( wrappedX ) );
465 double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
470 if ( std::round( floatMinutesX * precisionMultiplier ) >= 60 * precisionMultiplier )
472 floatMinutesX = std::max( floatMinutesX - 60, 0.0 );
480 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
491 if ( degreesX == 0 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
498 if ( degreesX == 180 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
505 QString strMinutesX = QString::fromStdWString( ss.str() );
506 ss.str( std::wstring() );
508 trimTrailingZeros( strMinutesX, context );
511 if ( mShowLeadingZeros && floatMinutesX < 10 )
512 strMinutesX =
'0' + strMinutesX;
514 ss << std::fixed << std::setprecision( 0 );
516 QString degreesXStr = QString::fromStdWString( ss.str() );
517 ss.str( std::wstring() );
519 if ( mShowLeadingDegreeZeros )
520 degreesXStr = QString( QStringLiteral(
"000" ) + degreesXStr ).right( 3 );
522 return sign + degreesXStr + QChar( 176 ) +
523 strMinutesX + QChar( 0x2032 ) +
527QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegrees(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
530 double wrappedY = std::fmod( val, 180.0 );
532 if ( wrappedY > 90.0 )
534 wrappedY = wrappedY - 180.0;
536 else if ( wrappedY < -90.0 )
538 wrappedY = wrappedY + 180.0;
541 const double absY = std::fabs( wrappedY );
549 hemisphere = wrappedY < 0 ? QObject::tr(
"S" ) : QObject::tr(
"N" );
560 if ( std::round( absY * precisionMultiplier ) == 0 )
568 QString strDegreesY = QString::fromStdWString( ss.str() );
569 ss.str( std::wstring() );
571 trimTrailingZeros( strDegreesY, context );
573 if ( mShowLeadingDegreeZeros && absY < 10 )
574 strDegreesY =
'0' + strDegreesY;
576 return sign + strDegreesY + QChar( 176 ) + hemisphere;
579QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegrees(
double val, std::basic_stringstream<wchar_t> &ss,
const QgsNumericFormatContext &context )
const
582 double wrappedX = std::fmod( val, 360.0 );
584 if ( wrappedX > 180.0 )
586 wrappedX = wrappedX - 360.0;
588 else if ( wrappedX < -180.0 )
590 wrappedX = wrappedX + 360.0;
593 const double absX = std::fabs( wrappedX );
601 hemisphere = wrappedX < 0 ? QObject::tr(
"W" ) : QObject::tr(
"E" );
612 if ( std::round( absX * precisionMultiplier ) == 0 )
619 if ( std::round( absX * precisionMultiplier ) == 180 * precisionMultiplier )
627 QString strDegreesX = QString::fromStdWString( ss.str() );
628 ss.str( std::wstring() );
630 trimTrailingZeros( strDegreesX, context );
632 if ( mShowLeadingDegreeZeros && absX < 100 )
633 strDegreesX =
'0' + strDegreesX;
634 if ( mShowLeadingDegreeZeros && absX < 10 )
635 strDegreesX =
'0' + strDegreesX;
637 return sign + strDegreesX + QChar( 176 ) + hemisphere;
640void QgsGeographicCoordinateNumericFormat::trimTrailingZeros( QString &input,
const QgsNumericFormatContext &context )
const
645 int trimPoint = input.length() - 1;
647 while ( input.at( trimPoint ) == context.
zeroDigit() )
650 if ( input.at( trimPoint ) == decimal )
653 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