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;
161 QString 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 );
175 QString 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 );
189 QString 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 ) +
280 QString 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 ) +
377 QString 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 ) +
448 QString 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 ) +
525 QString 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;
577 QString 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;
638 void 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 );