Skip to content
Permalink
Browse files
choose system of measurement for scalebar or position
  • Loading branch information
PeterPetrik committed Jun 25, 2018
1 parent 54a5059 commit caed3a9
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 37 deletions.
@@ -26,6 +26,14 @@ Helper functions for various unit types.
static const QMetaObject staticMetaObject;

public:
enum SystemOfMeasurement
{
UnknownSystem,
MetricSystem,
ImperialSystem,
USCSSystem
};

enum DistanceUnit
{
DistanceMeters,
@@ -39,6 +39,14 @@ class CORE_EXPORT QgsUnitTypes
Q_GADGET

public:
enum SystemOfMeasurement
{
UnknownSystem = 0, //!< Unknown system of measurement
MetricSystem, //!< International System of Units (SI)
ImperialSystem, //!< British Imperial
USCSSystem //!< United States customary system
};

//! Units of distance
enum DistanceUnit
{
@@ -61,6 +61,7 @@ void QgsQuickPlugin::registerTypes( const char *uri )
qRegisterMetaType< QgsPoint >( "QgsPoint" );
qRegisterMetaType< QgsPointXY >( "QgsPointXY" );
qRegisterMetaType< QgsQuickFeatureLayerPair >( "QgsQuickFeatureLayerPair" );
qRegisterMetaType< QgsUnitTypes::SystemOfMeasurement >( "QgsUnitTypes::SystemOfMeasurement" );
qRegisterMetaType< QgsUnitTypes::DistanceUnit >( "QgsUnitTypes::DistanceUnit" );
qRegisterMetaType< QgsCoordinateFormatter::FormatFlags >( "QgsCoordinateFormatter::FormatFlags" );
qRegisterMetaType< QgsCoordinateFormatter::Format >( "QgsCoordinateFormatter::Format" );
@@ -32,6 +32,10 @@ Item {
* representation
*/
property alias preferredWidth: scaleBarKit.preferredWidth
/**
* Preferred system of measurement for the resulting distance. Default is metric system
*/
property alias systemOfMeasurement: scaleBarKit.systemOfMeasurement
/**
* Kit for all calculation of width and text of the scalebar
*
@@ -162,7 +162,7 @@ class QUICK_EXPORT QgsQuickPositionKit : public QObject
/**
* Coordinate reference system of position - WGS84 (constant)
*/
QgsCoordinateReferenceSystem positionCRS() const;
Q_INVOKABLE QgsCoordinateReferenceSystem positionCRS() const;

/**
* Use simulated GPS source.
@@ -82,16 +82,14 @@ void QgsQuickScaleBarKit::updateScaleBar()
if ( !mMapSettings )
return;

double dist = QgsQuickUtils().screenUnitsToMeters( mMapSettings, mPreferredWidth ); // meters
if ( dist > 1000.0 )
{
dist = dist / 1000.0; // meters to kilometers
mUnits = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceKilometers );
}
else
{
mUnits = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters );
}
double distInMeters = QgsQuickUtils().screenUnitsToMeters( mMapSettings, mPreferredWidth ); // meters
double dist;
QgsUnitTypes::DistanceUnit distUnits;
QgsQuickUtils().humanReadableDistance( distInMeters, QgsUnitTypes::DistanceMeters,
mSystemOfMeasurement,
dist, distUnits );

mUnits = QgsUnitTypes::toAbbreviatedString( distUnits );

// we want to show nice round distances e.g. 200 km instead of e.g. 273 km
// so we determine which "nice" number to use and also update the scale bar
@@ -37,6 +37,9 @@ class QgsQuickMapSettings;
* distance in meters or kilometers (int) rounded to "nice" number (e.g. 72.4 to 100)
* and units text (e.g. km)
*
* System of measurement for result could be set too, so for example the resulting scalebar
* can show results in the imperial units.
*
* \note QML Type: ScaleBarKit
*
* \since QGIS 3.2
@@ -56,12 +59,19 @@ class QUICK_EXPORT QgsQuickScaleBarKit : public QObject
Q_PROPERTY( int preferredWidth MEMBER mPreferredWidth NOTIFY preferredWidthChanged )

/**
* Units of distance (e.g. km or m) Read-only (result).
* Preferred system of measurement for the result
*/
Q_PROPERTY( QgsUnitTypes::SystemOfMeasurement systemOfMeasurement MEMBER mSystemOfMeasurement NOTIFY systemOfMeasurementChanged )

/**
* Units of distance (e.g. km or m) of result in desired systemOfMeasurement Read-only (result).
*/
Q_PROPERTY( QString units READ units NOTIFY scaleBarChanged )

/**
* Distance rounded to "nice" number (e.g. 100, 20) corresponding to width. To be used with units property for labels. Read-only (result).
* Distance rounded to "nice" number (e.g. 100, 20) corresponding to width and system of measurement
*
* To be used with units property for labels. Read-only (result).
*/
Q_PROPERTY( int distance READ distance NOTIFY scaleBarChanged )

@@ -107,6 +117,9 @@ class QUICK_EXPORT QgsQuickScaleBarKit : public QObject
//! \copydoc QgsQuickScaleBarKit::preferredWidth
void preferredWidthChanged();

//! \copydoc QgsQuickScaleBarKit::systemOfMeasurement
void systemOfMeasurementChanged();

public slots:
//! recalculate width, distance and units.
void updateScaleBar();
@@ -116,7 +129,8 @@ class QUICK_EXPORT QgsQuickScaleBarKit : public QObject
int mPreferredWidth; // pixels
int mWidth; // pixels
int mDistance; // in meters or kilometers, rounded
QString mUnits; // km or m
QString mUnits; // e.g. km or m
QgsUnitTypes::SystemOfMeasurement mSystemOfMeasurement = QgsUnitTypes::MetricSystem;
};


@@ -94,12 +94,27 @@ QgsQuickFeatureLayerPair QgsQuickUtils::featureFactory( const QgsFeature &featur
return QgsQuickFeatureLayerPair( feature, layer );
}

QUrl QgsQuickUtils::getThemeIcon( const QString &name )
const QUrl QgsQuickUtils::getThemeIcon( const QString &name ) const
{
QString path = QStringLiteral( "qrc:/%1.svg" ).arg( name );
QgsDebugMsg( QStringLiteral( "Using icon %1 from %2" ).arg( name, path ) );
return QUrl( path );
}

QgsUnitTypes::SystemOfMeasurement QgsQuickUtils::systemOfMeasurementFactory( const QString &type )
{
if ( type == QStringLiteral( "Metric" ) )
return QgsUnitTypes::MetricSystem;

if ( type == QStringLiteral( "Imperial" ) )
return QgsUnitTypes::ImperialSystem;

if ( type == QStringLiteral( "USCS" ) )
return QgsUnitTypes::USCSSystem;

return QgsUnitTypes::UnknownSystem;
}

QString QgsQuickUtils::formatPoint(
const QgsPoint &point,
QgsCoordinateFormatter::Format format,
@@ -109,30 +124,151 @@ QString QgsQuickUtils::formatPoint(
return QgsCoordinateFormatter::format( point, format, decimals, flags );
}

QString QgsQuickUtils::formatDistance( double distance, QgsUnitTypes::DistanceUnit units, int decimals )
QString QgsQuickUtils::formatDistance( double distance,
QgsUnitTypes::DistanceUnit units,
int decimals,
QgsUnitTypes::SystemOfMeasurement destSystem )
{
double dist = distance * QgsUnitTypes::fromUnitToUnitFactor( units, QgsUnitTypes::DistanceMeters );
double destDistance;
QgsUnitTypes::DistanceUnit destUnits;

humanReadableDistance( distance, units, destSystem, destDistance, destUnits );

return QStringLiteral( "%1 %2" )
.arg( QString::number( destDistance, 'f', decimals ) )
.arg( QgsUnitTypes::toAbbreviatedString( destUnits ) );
}


void QgsQuickUtils::humanReadableDistance( double srcDistance, QgsUnitTypes::DistanceUnit srcUnits,
QgsUnitTypes::SystemOfMeasurement destSystem,
double &destDistance, QgsUnitTypes::DistanceUnit &destUnits )
{
if ( ( destSystem == QgsUnitTypes::MetricSystem ) || ( destSystem == QgsUnitTypes::UnknownSystem ) )
{
return formatToMetricDistance( srcDistance, srcUnits, destDistance, destUnits );
}
else if ( destSystem == QgsUnitTypes::ImperialSystem )
{
return formatToImperialDistance( srcDistance, srcUnits, destDistance, destUnits );
}
else if ( destSystem == QgsUnitTypes::USCSSystem )
{
return formatToUSCSDistance( srcDistance, srcUnits, destDistance, destUnits );
}
else
{
Q_ASSERT( false ); //should never happen
}
}

void QgsQuickUtils::formatToMetricDistance( double srcDistance,
QgsUnitTypes::DistanceUnit srcUnits,
double &destDistance,
QgsUnitTypes::DistanceUnit &destUnits )
{
double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceMillimeters );
if ( dist < 0 )
{
return QStringLiteral( "0 %1" ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters ) );
destDistance = 0;
destUnits = QgsUnitTypes::DistanceMillimeters;
return;
}

if ( dist > 1000 )
double mmToKm = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceKilometers, QgsUnitTypes::DistanceMillimeters );
if ( dist > mmToKm )
{
return QStringLiteral( "%1 %2" ).arg( QString::number( dist / 1000.0, 'f', decimals ) ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceKilometers ) );
destDistance = dist / mmToKm;
destUnits = QgsUnitTypes::DistanceKilometers;
return;
}
else

double mmToM = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, QgsUnitTypes::DistanceMillimeters );
if ( dist > mmToM )
{
destDistance = dist / mmToM;
destUnits = QgsUnitTypes::DistanceMeters;
return;
}

double mmToCm = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceCentimeters, QgsUnitTypes::DistanceMillimeters );
if ( dist > mmToCm )
{
destDistance = dist / mmToCm;
destUnits = QgsUnitTypes::DistanceCentimeters;
return;
}

destDistance = dist;
destUnits = QgsUnitTypes::DistanceMillimeters;
}

void QgsQuickUtils::formatToImperialDistance( double srcDistance,
QgsUnitTypes::DistanceUnit srcUnits,
double &destDistance,
QgsUnitTypes::DistanceUnit &destUnits )
{
double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceFeet );
if ( dist < 0 )
{
destDistance = 0;
destUnits = QgsUnitTypes::DistanceFeet;
return;
}

double feetToMile = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMiles, QgsUnitTypes::DistanceFeet );
if ( dist > feetToMile )
{
destDistance = dist / feetToMile;
destUnits = QgsUnitTypes::DistanceMiles;
return;
}

double feetToYard = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceYards, QgsUnitTypes::DistanceFeet );
if ( dist > feetToYard )
{
if ( dist > 1 )
{
return QStringLiteral( "%1 %2" ).arg( QString::number( dist, 'f', decimals ) ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters ) );
}
else
{
return QStringLiteral( "%1 %2" ).arg( QString::number( dist * 1000, 'f', decimals ) ).arg( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMillimeters ) );
}
destDistance = dist / feetToYard;
destUnits = QgsUnitTypes::DistanceYards;
return;
}

destDistance = dist;
destUnits = QgsUnitTypes::DistanceFeet;
return;
}

void QgsQuickUtils::formatToUSCSDistance( double srcDistance,
QgsUnitTypes::DistanceUnit srcUnits,
double &destDistance,
QgsUnitTypes::DistanceUnit &destUnits )
{
double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceFeet );
if ( dist < 0 )
{
destDistance = 0;
destUnits = QgsUnitTypes::DistanceFeet;
return;
}

double feetToMile = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceNauticalMiles, QgsUnitTypes::DistanceFeet );
if ( dist > feetToMile )
{
destDistance = dist / feetToMile;
destUnits = QgsUnitTypes::DistanceNauticalMiles;
return;
}

double feetToYard = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceYards, QgsUnitTypes::DistanceFeet );
if ( dist > feetToYard )
{
destDistance = dist / feetToYard;
destUnits = QgsUnitTypes::DistanceYards;
return;
}

destDistance = dist;
destUnits = QgsUnitTypes::DistanceFeet;
return;
}

QString QgsQuickUtils::dumpScreenInfo() const

0 comments on commit caed3a9

Please sign in to comment.