diff --git a/python/core/auto_generated/tiledmesh/qgscesiumutils.sip.in b/python/core/auto_generated/tiledmesh/qgscesiumutils.sip.in index 5eff7905c1db..53e2ad5e8cf1 100644 --- a/python/core/auto_generated/tiledmesh/qgscesiumutils.sip.in +++ b/python/core/auto_generated/tiledmesh/qgscesiumutils.sip.in @@ -9,6 +9,7 @@ + class QgsCesiumUtils { %Docstring(signature="appended") @@ -22,6 +23,7 @@ Contains utilities for working with Cesium data. %End public: + static QgsBox3d parseRegion( const QVariantList ®ion ); %Docstring Parses a ``region`` object from a Cesium JSON document to a 3D box. diff --git a/src/core/tiledmesh/qgscesiumtilesdataprovider.cpp b/src/core/tiledmesh/qgscesiumtilesdataprovider.cpp index 01a44e65ed42..92e903e27beb 100644 --- a/src/core/tiledmesh/qgscesiumtilesdataprovider.cpp +++ b/src/core/tiledmesh/qgscesiumtilesdataprovider.cpp @@ -42,20 +42,21 @@ QgsCesiumTilesDataProviderSharedData::QgsCesiumTilesDataProviderSharedData() = default; -void QgsCesiumTilesDataProviderSharedData::setTilesetContent( const QVariantMap &tileset ) +void QgsCesiumTilesDataProviderSharedData::setTilesetContent( const QString &tileset ) { - mTileset = tileset; + mTileset = json::parse( tileset.toStdString() ); + mCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4979" ) ); // parse root { - const QVariantMap root = tileset.value( QStringLiteral( "root" ) ).toMap(); + const auto &root = mTileset[ "root" ]; // parse root bounding volume { - const QVariantMap rootBoundingVolume = root.value( QStringLiteral( "boundingVolume" ) ).toMap(); - if ( rootBoundingVolume.contains( QStringLiteral( "region" ) ) ) + const auto &rootBoundingVolume = root[ "boundingVolume" ]; + if ( rootBoundingVolume.contains( "region" ) ) { - const QgsBox3d rootRegion = QgsCesiumUtils::parseRegion( rootBoundingVolume.value( QStringLiteral( "region" ) ).toList() ); + const QgsBox3d rootRegion = QgsCesiumUtils::parseRegion( rootBoundingVolume[ "region" ] ); if ( !rootRegion.isNull() ) { mZRange = QgsDoubleRange( rootRegion.zMinimum(), rootRegion.zMaximum() ); @@ -142,16 +143,7 @@ bool QgsCesiumTilesDataProvider::init() } const QgsNetworkReplyContent content = networkRequest.reply(); - const QByteArray raw = content.content(); - - // Parse data - QJsonParseError err; - const QJsonDocument doc = QJsonDocument::fromJson( raw, &err ); - if ( doc.isNull() ) - { - return false; - } - mShared->setTilesetContent( doc.object().toVariantMap() ); + mShared->setTilesetContent( content.content() ); } else { @@ -162,14 +154,7 @@ bool QgsCesiumTilesDataProvider::init() if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { const QByteArray raw = file.readAll(); - // Parse data - QJsonParseError err; - const QJsonDocument doc = QJsonDocument::fromJson( raw, &err ); - if ( doc.isNull() ) - { - return false; - } - mShared->setTilesetContent( doc.object().toVariantMap() ); + mShared->setTilesetContent( raw ); } else { @@ -226,19 +211,26 @@ QString QgsCesiumTilesDataProvider::htmlMetadata() const QString metadata; + if ( mShared->mTileset.contains( "asset" ) ) { - const QVariantMap asset = mShared->mTileset.value( QStringLiteral( "asset" ) ).toMap(); - const QString version = asset.value( QStringLiteral( "version" ) ).toString(); - if ( !version.isEmpty() ) + const auto &asset = mShared->mTileset[ "asset" ]; + if ( asset.contains( "version" ) ) + { + const QString version = QString::fromStdString( asset["version"].get() ); metadata += QStringLiteral( "" ) % tr( "3D Tiles Version" ) % QStringLiteral( "%1" ).arg( version ) % QStringLiteral( "\n" ); + } - const QString tilesetVersion = asset.value( QStringLiteral( "tilesetVersion" ) ).toString(); - if ( !tilesetVersion.isEmpty() ) + if ( asset.contains( "tilesetVersion" ) ) + { + const QString tilesetVersion = QString::fromStdString( asset["tilesetVersion"].get() ); metadata += QStringLiteral( "" ) % tr( "Tileset Version" ) % QStringLiteral( "%1" ).arg( tilesetVersion ) % QStringLiteral( "\n" ); + } - const QString generator = asset.value( QStringLiteral( "generator" ) ).toString(); - if ( !generator.isEmpty() ) + if ( asset.contains( "generator" ) ) + { + const QString generator = QString::fromStdString( asset["generator"].get() ); metadata += QStringLiteral( "" ) % tr( "Tileset Generator" ) % QStringLiteral( "%1" ).arg( generator ) % QStringLiteral( "\n" ); + } } if ( !mShared->mZRange.isInfinite() ) diff --git a/src/core/tiledmesh/qgscesiumtilesdataprovider.h b/src/core/tiledmesh/qgscesiumtilesdataprovider.h index 8404f346782f..4e18f0582583 100644 --- a/src/core/tiledmesh/qgscesiumtilesdataprovider.h +++ b/src/core/tiledmesh/qgscesiumtilesdataprovider.h @@ -24,6 +24,8 @@ #include "qgis.h" #include "qgsprovidermetadata.h" #include "qgsrange.h" +#include "nlohmann/json.hpp" + #define SIP_NO_FILE ///@cond PRIVATE @@ -32,11 +34,11 @@ class QgsCesiumTilesDataProviderSharedData { public: QgsCesiumTilesDataProviderSharedData(); - void setTilesetContent( const QVariantMap &tileset ); + void setTilesetContent( const QString &tileset ); QgsCoordinateReferenceSystem mCrs; QgsRectangle mExtent; - QVariantMap mTileset; + nlohmann::json mTileset; QgsDoubleRange mZRange; QReadWriteLock mMutex; diff --git a/src/core/tiledmesh/qgscesiumutils.cpp b/src/core/tiledmesh/qgscesiumutils.cpp index bcb2d2fdb247..e858780ce5bf 100644 --- a/src/core/tiledmesh/qgscesiumutils.cpp +++ b/src/core/tiledmesh/qgscesiumutils.cpp @@ -17,33 +17,31 @@ ***************************************************************************/ #include "qgscesiumutils.h" +#include "nlohmann/json.hpp" +#include "qgsjsonutils.h" -QgsBox3d QgsCesiumUtils::parseRegion( const QVariantList ®ion ) +QgsBox3d QgsCesiumUtils::parseRegion( const json ®ion ) { - if ( region.size() != 6 ) + try + { + const double west = region[0].get(); + const double south = region[1].get(); + const double east = region[2].get(); + const double north = region[3].get(); + double minHeight = region[4].get(); + double maxHeight = region[5].get(); + return QgsBox3d( west, south, minHeight, east, north, maxHeight ); + } + catch ( nlohmann::json::exception & ) + { return QgsBox3d(); + } +} - // The region property is an array of six numbers that define the bounding geographic region with - // latitude, longitude, and height coordinates with the order [west, south, east, north, minimum height, maximum height]. - bool ok = false; - const double west = region.at( 0 ).toDouble( &ok ); - if ( !ok ) - return QgsBox3d(); - const double south = region.at( 1 ).toDouble( &ok ); - if ( !ok ) - return QgsBox3d(); - const double east = region.at( 2 ).toDouble( &ok ); - if ( !ok ) - return QgsBox3d(); - const double north = region.at( 3 ).toDouble( &ok ); - if ( !ok ) - return QgsBox3d(); - const double minHeight = region.at( 4 ).toDouble( &ok ); - if ( !ok ) - return QgsBox3d(); - const double maxHeight = region.at( 5 ).toDouble( &ok ); - if ( !ok ) +QgsBox3d QgsCesiumUtils::parseRegion( const QVariantList ®ion ) +{ + if ( region.size() != 6 ) return QgsBox3d(); - return QgsBox3d( west, south, minHeight, east, north, maxHeight ); + return parseRegion( QgsJsonUtils::jsonFromVariant( region ) ); } diff --git a/src/core/tiledmesh/qgscesiumutils.h b/src/core/tiledmesh/qgscesiumutils.h index 12482b00146d..e87eaad4d0b4 100644 --- a/src/core/tiledmesh/qgscesiumutils.h +++ b/src/core/tiledmesh/qgscesiumutils.h @@ -21,6 +21,11 @@ #include "qgis_core.h" #include "qgsbox3d.h" +#include "nlohmann/json_fwd.hpp" + +#ifndef SIP_RUN +using namespace nlohmann; +#endif /** * \brief Contains utilities for working with Cesium data. @@ -33,6 +38,16 @@ class CORE_EXPORT QgsCesiumUtils { public: +#ifndef SIP_RUN + + /** + * Parses a \a region object from a Cesium JSON object to a 3D box. + * + * \note Not available in Python bindings. + */ + static QgsBox3d parseRegion( const json ®ion ); +#endif + /** * Parses a \a region object from a Cesium JSON document to a 3D box. */ diff --git a/tests/src/python/test_qgscesiumutils.py b/tests/src/python/test_qgscesiumutils.py index 407ffc029638..fe3e7648b496 100644 --- a/tests/src/python/test_qgscesiumutils.py +++ b/tests/src/python/test_qgscesiumutils.py @@ -37,7 +37,7 @@ def test_parse_region(self): QgsCesiumUtils.parseRegion([1, 'a', 3, 4, 5, 6]).isNull()) # valid - box = QgsCesiumUtils.parseRegion(['1.2', '2', 3, '4.6', 5.5, 6]) + box = QgsCesiumUtils.parseRegion([1.2, 2, 3, 4.6, 5.5, 6]) self.assertEqual(box.xMinimum(), 1.2) self.assertEqual(box.xMaximum(), 3.0) self.assertEqual(box.yMinimum(), 2.0)