From fff3288795567ccebfc8c54237aa77d58248e9e2 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 18:36:12 +0200 Subject: [PATCH 01/17] qgspoint3dsymbol_p: Fix a clang-tidy warning --- src/3d/symbols/qgspoint3dsymbol_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index 291a79118e24..c4323ab58bfc 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -277,7 +277,7 @@ Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( const QgsPoin Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const QgsPoint3DSymbol *symbol, const QVector &positions ) { const int count = positions.count(); - const int byteCount = positions.count() * sizeof( QVector3D ); + const int byteCount = static_cast( count * sizeof( QVector3D ) ); QByteArray ba; ba.resize( byteCount ); memcpy( ba.data(), positions.constData(), byteCount ); From 7d47f24128f14fd193596371b77eaf2ce38d270c Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 10:38:49 +0200 Subject: [PATCH 02/17] qgsabstract3dsymbol: Add radius symbol definition This will be used by `QgsPoint3DSymbol` in the next commit. --- python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- .../PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + python/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + src/core/3d/qgsabstract3dsymbol.cpp | 1 + src/core/3d/qgsabstract3dsymbol.h | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py index 86392a491876..1f09e288775e 100644 --- a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py @@ -8,5 +8,9 @@ QgsAbstract3DSymbol.Property.PropertyExtrusionHeight = QgsAbstract3DSymbol.Property.ExtrusionHeight QgsAbstract3DSymbol.PropertyExtrusionHeight.is_monkey_patched = True QgsAbstract3DSymbol.PropertyExtrusionHeight.__doc__ = "Extrusion height (zero means no extrusion)" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ +QgsAbstract3DSymbol.PropertyRadius = QgsAbstract3DSymbol.Property.Radius +QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius +QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ # -- diff --git a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index f24eef013177..fa3b10fb5112 100644 --- a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -65,6 +65,7 @@ Returns the list of the vector layer geometry types which are compatible with th { Height, ExtrusionHeight, + Radius, }; static const QgsPropertiesDefinition &propertyDefinitions(); diff --git a/python/core/auto_additions/qgsabstract3dsymbol.py b/python/core/auto_additions/qgsabstract3dsymbol.py index 86392a491876..1f09e288775e 100644 --- a/python/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/core/auto_additions/qgsabstract3dsymbol.py @@ -8,5 +8,9 @@ QgsAbstract3DSymbol.Property.PropertyExtrusionHeight = QgsAbstract3DSymbol.Property.ExtrusionHeight QgsAbstract3DSymbol.PropertyExtrusionHeight.is_monkey_patched = True QgsAbstract3DSymbol.PropertyExtrusionHeight.__doc__ = "Extrusion height (zero means no extrusion)" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ +QgsAbstract3DSymbol.PropertyRadius = QgsAbstract3DSymbol.Property.Radius +QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius +QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ # -- diff --git a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index 13016926f696..03751ce18d0a 100644 --- a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -65,6 +65,7 @@ Returns the list of the vector layer geometry types which are compatible with th { Height, ExtrusionHeight, + Radius, }; static const QgsPropertiesDefinition &propertyDefinitions(); diff --git a/src/core/3d/qgsabstract3dsymbol.cpp b/src/core/3d/qgsabstract3dsymbol.cpp index d3d6878b709a..cb144e8585c8 100644 --- a/src/core/3d/qgsabstract3dsymbol.cpp +++ b/src/core/3d/qgsabstract3dsymbol.cpp @@ -46,6 +46,7 @@ void QgsAbstract3DSymbol::initPropertyDefinitions() { { static_cast< int >( Property::Height ), QgsPropertyDefinition( "height", QObject::tr( "Height" ), QgsPropertyDefinition::Double, origin ) }, { static_cast< int >( Property::ExtrusionHeight ), QgsPropertyDefinition( "extrusionHeight", QObject::tr( "ExtrusionHeight" ), QgsPropertyDefinition::DoublePositive, origin ) }, + { static_cast< int >( Property::Radius ), QgsPropertyDefinition( "radius", QObject::tr( "Radius" ), QgsPropertyDefinition::DoublePositive, origin ) }, }; } diff --git a/src/core/3d/qgsabstract3dsymbol.h b/src/core/3d/qgsabstract3dsymbol.h index 16ef3fa6ea19..385665bc63d4 100644 --- a/src/core/3d/qgsabstract3dsymbol.h +++ b/src/core/3d/qgsabstract3dsymbol.h @@ -70,6 +70,7 @@ class CORE_EXPORT QgsAbstract3DSymbol { Height SIP_MONKEYPATCH_COMPAT_NAME( PropertyHeight ) = 0, //!< Height (altitude) ExtrusionHeight SIP_MONKEYPATCH_COMPAT_NAME( PropertyExtrusionHeight ), //!< Extrusion height (zero means no extrusion) + Radius SIP_MONKEYPATCH_COMPAT_NAME( PropertyRadius ), //!< Radius }; // *INDENT-ON* From df8e493ec939428fb18025a3762d5d245064b766 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 12:44:52 +0200 Subject: [PATCH 03/17] qgspoint3dsymbol: Add support for data defined radius `QgsInstancedPoint3DSymbolHandler` uses OpenGL instancing in order to draw multiple times the same entity at different locations with the same shape. In practice, this means that only two Qt3D entities are created: - one for the points which are not selected - one for the selected points Indeed, the selected points do not have the same color as the normal ones. If there isn't any selected point, only one entity is created. When a point can have a data defined radius, this logic needs to be updated. The idea is to group the points which have the same radius. This logic is handled by the `PointData` class and the `==` operator. If two different have the same state (selected or normal) and the same radius, they are grouped together in the same `PointData` instance and their respective positions are stored in `positions`. This means that if there are 3 different radii, at most 6 different entities are created: 1. Entity1: (normal, radius1) 2. Entity2: (selected, radius1) 3. Entity3: (normal, radius2) 4. Entity4: (selected, radius2) 5. Entity5: (normal, radius3) 6. Entity6: (selected, radius3) If there is only one radius, the previous case still applies. --- src/3d/symbols/qgspoint3dsymbol.cpp | 8 ++ src/3d/symbols/qgspoint3dsymbol_p.cpp | 157 ++++++++++++++++++-------- 2 files changed, 119 insertions(+), 46 deletions(-) diff --git a/src/3d/symbols/qgspoint3dsymbol.cpp b/src/3d/symbols/qgspoint3dsymbol.cpp index 47236c92b850..d7cac9f2be57 100644 --- a/src/3d/symbols/qgspoint3dsymbol.cpp +++ b/src/3d/symbols/qgspoint3dsymbol.cpp @@ -88,6 +88,10 @@ void QgsPoint3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &c elem.appendChild( symbolElem ); } + + QDomElement elemDDP = doc.createElement( QStringLiteral( "data-defined-properties" ) ); + mDataDefinedProperties.writeXml( elemDDP, propertyDefinitions() ); + elem.appendChild( elemDDP ); } void QgsPoint3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context ) @@ -114,6 +118,10 @@ void QgsPoint3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteConte const QDomElement symbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) ); setBillboardSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElem, context ) ); + + const QDomElement elemDDP = elem.firstChildElement( QStringLiteral( "data-defined-properties" ) ); + if ( !elemDDP.isNull() ) + mDataDefinedProperties.readXml( elemDDP, propertyDefinitions() ); } QList QgsPoint3DSymbol::compatibleGeometryTypes() const diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index c4323ab58bfc..283895582eca 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -85,17 +85,27 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler private: - static Qt3DRender::QMaterial *material( const QgsPoint3DSymbol *symbol, const QgsMaterialContext &materialContext ); - static Qt3DRender::QGeometryRenderer *renderer( const QgsPoint3DSymbol *symbol, const QVector &positions ); - static Qt3DQGeometry *symbolGeometry( const QgsPoint3DSymbol *symbol ); - //! temporary data we will pass to the tessellator - struct PointData + class PointData { - QVector positions; // contains triplets of float x,y,z for each point + public: + + PointData() = default; + + float radius = 0.0f; + QVector positions; + + bool operator==( const PointData &other ) const + { + return radius == other.radius; + } }; - void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected ); + static Qt3DRender::QMaterial *material( const QgsPoint3DSymbol *symbol, const QgsMaterialContext &materialContext ); + static Qt3DRender::QGeometryRenderer *renderer( const QgsPoint3DSymbol *symbol, const PointData &pointData ); + static Qt3DQGeometry *symbolGeometry( const QgsPoint3DSymbol *symbol, const PointData &pointData ); + + void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QVector &out, bool selected ); // input specific for this class std::unique_ptr< QgsPoint3DSymbol > mSymbol; @@ -103,26 +113,49 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler QgsFeatureIds mSelectedIds; // outputs - PointData outNormal; //!< Features that are not selected - PointData outSelected; //!< Features that are selected + QVector outNormal; //!< Features that are not selected + QVector outSelected; //!< Features that are selected }; - bool QgsInstancedPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet &attributeNames ) { - Q_UNUSED( context ) - Q_UNUSED( attributeNames ) + QSet attrs = mSymbol->dataDefinedProperties().referencedFields( context.expressionContext() ); + attributeNames.unite( attrs ); return true; } void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) { - PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal; + QVector &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal; if ( feature.geometry().isNull() ) return; - Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), out.positions ); + const QgsPropertyCollection &ddp = mSymbol->dataDefinedProperties(); + const bool hasDDRadius = ddp.isActive( QgsAbstract3DSymbol::Property::Radius ); + float radius = mSymbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); + if ( hasDDRadius ) + { + radius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::Radius, context.expressionContext(), radius ) ); + } + + QVector positions; + Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), positions ); + + PointData newPointData; + newPointData.radius = radius; + + PointData *existingPointData = std::find( out.begin(), out.end(), newPointData ); + if ( existingPointData == out.end() ) + { + newPointData.positions = QVector {positions[0]}; + out.append( newPointData ); + } + else + { + existingPointData->positions.append( positions[0] ); + } + mFeatureCount++; } @@ -131,8 +164,15 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons makeEntity( parent, context, outNormal, false ); makeEntity( parent, context, outSelected, true ); - updateZRangeFromPositions( outNormal.positions ); - updateZRangeFromPositions( outSelected.positions ); + for ( PointData &pointData : outNormal ) + { + updateZRangeFromPositions( pointData.positions ); + } + + for ( PointData &pointData : outSelected ) + { + updateZRangeFromPositions( pointData.positions ); + } // the elevation offset is applied in the vertex shader so let's account for it as well const float symbolOffset = mSymbol->transform().data()[13]; @@ -151,9 +191,21 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons case Qgis::Point3DShape::Sphere: { - const float radius = mSymbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); - mZMin -= radius; - mZMax += radius; + float radiusMax = 0.0; + for ( const PointData &pointData : outNormal ) + { + if ( pointData.radius > radiusMax ) + radiusMax = pointData.radius; + } + + for ( const PointData &pointData : outSelected ) + { + if ( pointData.radius > radiusMax ) + radiusMax = pointData.radius; + } + + mZMin -= radiusMax; + mZMax += radiusMax; break; } @@ -175,9 +227,21 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons case Qgis::Point3DShape::Torus: { - const float radius = mSymbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); - mZMin -= radius; - mZMax += radius; + float radiusMax = 0.0; + for ( const PointData &pointData : outNormal ) + { + if ( pointData.radius > radiusMax ) + radiusMax = pointData.radius; + } + + for ( const PointData &pointData : outSelected ) + { + if ( pointData.radius > radiusMax ) + radiusMax = pointData.radius; + } + + mZMin -= radiusMax; + mZMax += radiusMax; break; } @@ -201,7 +265,7 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons mZMax += symbolOffset; } -void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected ) +void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QVector &out, bool selected ) { // build the default material QgsMaterialContext materialContext; @@ -210,10 +274,13 @@ void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, co Qt3DRender::QMaterial *mat = material( mSymbol.get(), materialContext ); // build the entity - Qt3DCore::QEntity *entity = new Qt3DCore::QEntity; - entity->addComponent( renderer( mSymbol.get(), out.positions ) ); - entity->addComponent( mat ); - entity->setParent( parent ); + for ( const PointData *pointData = out.cbegin(), *end = out.cend(); pointData != end; ++pointData ) + { + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity; + entity->addComponent( renderer( mSymbol.get(), *pointData ) ); + entity->addComponent( mat ); + entity->setParent( parent ); + } // cppcheck wrongly believes entity will leak // cppcheck-suppress memleak @@ -274,8 +341,9 @@ Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( const QgsPoin return material; } -Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const QgsPoint3DSymbol *symbol, const QVector &positions ) +Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const QgsPoint3DSymbol *symbol, const PointData &pointData ) { + const QVector positions = pointData.positions; const int count = positions.count(); const int byteCount = static_cast( count * sizeof( QVector3D ) ); QByteArray ba; @@ -296,7 +364,7 @@ Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const instanceDataAttribute->setCount( count ); instanceDataAttribute->setByteStride( 3 * sizeof( float ) ); - Qt3DQGeometry *geometry = symbolGeometry( symbol ); + Qt3DQGeometry *geometry = symbolGeometry( symbol, pointData ); geometry->addAttribute( instanceDataAttribute ); geometry->setBoundingVolumePositionAttribute( instanceDataAttribute ); @@ -307,28 +375,26 @@ Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const return renderer; } -Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3DSymbol *symbol ) +Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3DSymbol *symbol, const PointData &pointData ) { switch ( symbol->shape() ) { case Qgis::Point3DShape::Cylinder: { - const float radius = symbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); const float length = symbol->shapeProperty( QStringLiteral( "length" ) ).toFloat(); - Qt3DExtras::QCylinderGeometry *g = new Qt3DExtras::QCylinderGeometry; - //g->setRings(2); // how many vertices vertically - //g->setSlices(8); // how many vertices on circumference - g->setRadius( radius ); - g->setLength( length ); - return g; + Qt3DExtras::QCylinderGeometry *geometry = new Qt3DExtras::QCylinderGeometry; + // geometry->setRings(2); // how many vertices vertically + // geometry->setSlices(8); // how many vertices on circumference + geometry->setRadius( pointData.radius ); + geometry->setLength( length ); + return geometry; } case Qgis::Point3DShape::Sphere: { - const float radius = symbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); - Qt3DExtras::QSphereGeometry *g = new Qt3DExtras::QSphereGeometry; - g->setRadius( radius ); - return g; + Qt3DExtras::QSphereGeometry *geometry = new Qt3DExtras::QSphereGeometry; + geometry->setRadius( pointData.radius ); + return geometry; } case Qgis::Point3DShape::Cone: @@ -358,12 +424,11 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 case Qgis::Point3DShape::Torus: { - const float radius = symbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); const float minorRadius = symbol->shapeProperty( QStringLiteral( "minorRadius" ) ).toFloat(); - Qt3DExtras::QTorusGeometry *g = new Qt3DExtras::QTorusGeometry; - g->setRadius( radius ); - g->setMinorRadius( minorRadius ); - return g; + Qt3DExtras::QTorusGeometry *geometry = new Qt3DExtras::QTorusGeometry; + geometry->setRadius( pointData.radius ); + geometry->setMinorRadius( minorRadius ); + return geometry; } case Qgis::Point3DShape::Plane: From 016e75599491145e95f82efaa095bca94ca6eb84 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 10:41:24 +0200 Subject: [PATCH 04/17] qgspoint3dsymbolwidget: Add support for data defined radius --- src/app/3d/qgspoint3dsymbolwidget.cpp | 20 ++++++++++++++++---- src/ui/3d/point3dsymbolwidget.ui | 13 +++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/app/3d/qgspoint3dsymbolwidget.cpp b/src/app/3d/qgspoint3dsymbolwidget.cpp index a600c49ba70a..a32bd501cec4 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.cpp +++ b/src/app/3d/qgspoint3dsymbolwidget.cpp @@ -78,6 +78,8 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) // Sync between billboard height and TZ connect( spinBillboardHeight, static_cast( &QDoubleSpinBox::valueChanged ), spinTZ, &QDoubleSpinBox::setValue ); connect( spinTZ, static_cast( &QDoubleSpinBox::valueChanged ), spinBillboardHeight, &QDoubleSpinBox::setValue ); + + connect( mBtnRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); } Qgs3DSymbolWidget *QgsPoint3DSymbolWidget::create( QgsVectorLayer * ) @@ -141,6 +143,11 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsAbstract3DSymbol *symbol, QgsVe break; } + // setSymbol is only called once. + // the data defined properties need to be all init to make them work if a user-interaction + // changes the shape. + mBtnRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Radius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); + widgetMaterial->setSettings( pointSymbol->materialSettings(), layer ); widgetMaterial->setTechnique( technique ); @@ -186,14 +193,17 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() QVariantMap vm; std::unique_ptr< QgsPoint3DSymbol > sym = std::make_unique< QgsPoint3DSymbol >(); sym->setBillboardSymbol( static_cast( QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) ) ); + QgsPropertyCollection ddp; switch ( cboShape->currentData().value< Qgis::Point3DShape >() ) { case Qgis::Point3DShape::Sphere: vm[QStringLiteral( "radius" )] = spinRadius->value(); + ddp.setProperty( QgsAbstract3DSymbol::Property::Radius, mBtnRadiusOverride->toProperty() ); break; case Qgis::Point3DShape::Cylinder: vm[QStringLiteral( "radius" )] = spinRadius->value(); vm[QStringLiteral( "length" )] = spinLength->value(); + ddp.setProperty( QgsAbstract3DSymbol::Property::Radius, mBtnRadiusOverride->toProperty() ); break; case Qgis::Point3DShape::Cube: vm[QStringLiteral( "size" )] = spinSize->value(); @@ -209,6 +219,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() case Qgis::Point3DShape::Torus: vm[QStringLiteral( "radius" )] = spinRadius->value(); vm[QStringLiteral( "minorRadius" )] = spinMinorRadius->value(); + ddp.setProperty( QgsAbstract3DSymbol::Property::Radius, mBtnRadiusOverride->toProperty() ); break; case Qgis::Point3DShape::Model: vm[QStringLiteral( "model" )] = lineEditModel->source(); @@ -237,6 +248,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() sym->setShapeProperties( vm ); sym->setMaterialSettings( widgetMaterial->settings() ); sym->setTransform( tr ); + sym->setDataDefinedProperties( ddp ); return sym.release(); } @@ -249,7 +261,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() { QList allWidgets; allWidgets << labelSize << spinSize - << labelRadius << spinRadius + << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius @@ -264,10 +276,10 @@ void QgsPoint3DSymbolWidget::onShapeChanged() switch ( cboShape->currentData().value< Qgis::Point3DShape >() ) { case Qgis::Point3DShape::Sphere: - activeWidgets << labelRadius << spinRadius; + activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride; break; case Qgis::Point3DShape::Cylinder: - activeWidgets << labelRadius << spinRadius << labelLength << spinLength; + activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelLength << spinLength; break; case Qgis::Point3DShape::Cube: activeWidgets << labelSize << spinSize; @@ -279,7 +291,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() activeWidgets << labelSize << spinSize; break; case Qgis::Point3DShape::Torus: - activeWidgets << labelRadius << spinRadius << labelMinorRadius << spinMinorRadius; + activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius; break; case Qgis::Point3DShape::Model: activeWidgets << labelModel << lineEditModel; diff --git a/src/ui/3d/point3dsymbolwidget.ui b/src/ui/3d/point3dsymbolwidget.ui index ba89a59c11fd..340dbd48d402 100644 --- a/src/ui/3d/point3dsymbolwidget.ui +++ b/src/ui/3d/point3dsymbolwidget.ui @@ -387,6 +387,13 @@ + + + + + + + @@ -460,10 +467,16 @@
qgscollapsiblegroupbox.h
1 + + QgsPropertyOverrideButton + QToolButton +
qgspropertyoverridebutton.h
+
cboShape spinRadius + mBtnRadiusOverride spinMinorRadius spinTopRadius spinBottomRadius From 0c0a500d9a98967fc4ffba2ff9361b090eed0fdf Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 14:03:17 +0200 Subject: [PATCH 05/17] qgsabstract3dsymbol: Add length symbol definition This will be used by `QgsPoint3DSymbol` in the next commit. --- python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- .../PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + python/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + src/core/3d/qgsabstract3dsymbol.cpp | 1 + src/core/3d/qgsabstract3dsymbol.h | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py index 1f09e288775e..acc81a0d6cf9 100644 --- a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py @@ -8,9 +8,13 @@ QgsAbstract3DSymbol.Property.PropertyExtrusionHeight = QgsAbstract3DSymbol.Property.ExtrusionHeight QgsAbstract3DSymbol.PropertyExtrusionHeight.is_monkey_patched = True QgsAbstract3DSymbol.PropertyExtrusionHeight.__doc__ = "Extrusion height (zero means no extrusion)" +QgsAbstract3DSymbol.PropertyLength = QgsAbstract3DSymbol.Property.Length +QgsAbstract3DSymbol.Property.PropertyLength = QgsAbstract3DSymbol.Property.Length +QgsAbstract3DSymbol.PropertyLength.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyLength.__doc__ = "Length" QgsAbstract3DSymbol.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ # -- diff --git a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index fa3b10fb5112..e21d19ea844c 100644 --- a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -65,6 +65,7 @@ Returns the list of the vector layer geometry types which are compatible with th { Height, ExtrusionHeight, + Length, Radius, }; diff --git a/python/core/auto_additions/qgsabstract3dsymbol.py b/python/core/auto_additions/qgsabstract3dsymbol.py index 1f09e288775e..acc81a0d6cf9 100644 --- a/python/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/core/auto_additions/qgsabstract3dsymbol.py @@ -8,9 +8,13 @@ QgsAbstract3DSymbol.Property.PropertyExtrusionHeight = QgsAbstract3DSymbol.Property.ExtrusionHeight QgsAbstract3DSymbol.PropertyExtrusionHeight.is_monkey_patched = True QgsAbstract3DSymbol.PropertyExtrusionHeight.__doc__ = "Extrusion height (zero means no extrusion)" +QgsAbstract3DSymbol.PropertyLength = QgsAbstract3DSymbol.Property.Length +QgsAbstract3DSymbol.Property.PropertyLength = QgsAbstract3DSymbol.Property.Length +QgsAbstract3DSymbol.PropertyLength.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyLength.__doc__ = "Length" QgsAbstract3DSymbol.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ # -- diff --git a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index 03751ce18d0a..fe655f717121 100644 --- a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -65,6 +65,7 @@ Returns the list of the vector layer geometry types which are compatible with th { Height, ExtrusionHeight, + Length, Radius, }; diff --git a/src/core/3d/qgsabstract3dsymbol.cpp b/src/core/3d/qgsabstract3dsymbol.cpp index cb144e8585c8..112a1a44299e 100644 --- a/src/core/3d/qgsabstract3dsymbol.cpp +++ b/src/core/3d/qgsabstract3dsymbol.cpp @@ -46,6 +46,7 @@ void QgsAbstract3DSymbol::initPropertyDefinitions() { { static_cast< int >( Property::Height ), QgsPropertyDefinition( "height", QObject::tr( "Height" ), QgsPropertyDefinition::Double, origin ) }, { static_cast< int >( Property::ExtrusionHeight ), QgsPropertyDefinition( "extrusionHeight", QObject::tr( "ExtrusionHeight" ), QgsPropertyDefinition::DoublePositive, origin ) }, + { static_cast< int >( Property::Length ), QgsPropertyDefinition( "length", QObject::tr( "Length" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Radius ), QgsPropertyDefinition( "radius", QObject::tr( "Radius" ), QgsPropertyDefinition::DoublePositive, origin ) }, }; diff --git a/src/core/3d/qgsabstract3dsymbol.h b/src/core/3d/qgsabstract3dsymbol.h index 385665bc63d4..0091cd4961db 100644 --- a/src/core/3d/qgsabstract3dsymbol.h +++ b/src/core/3d/qgsabstract3dsymbol.h @@ -70,6 +70,7 @@ class CORE_EXPORT QgsAbstract3DSymbol { Height SIP_MONKEYPATCH_COMPAT_NAME( PropertyHeight ) = 0, //!< Height (altitude) ExtrusionHeight SIP_MONKEYPATCH_COMPAT_NAME( PropertyExtrusionHeight ), //!< Extrusion height (zero means no extrusion) + Length SIP_MONKEYPATCH_COMPAT_NAME( PropertyLength ), //!< Length Radius SIP_MONKEYPATCH_COMPAT_NAME( PropertyRadius ), //!< Radius }; // *INDENT-ON* From be6e0b27a671bc0b616f954da252bc662820c3d2 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 14:37:56 +0200 Subject: [PATCH 06/17] qgspoint3dsymbol: Add support for data defined length --- src/3d/symbols/qgspoint3dsymbol_p.cpp | 65 ++++++++++++++++++++------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index 283895582eca..182810c437d7 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -92,12 +92,13 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler PointData() = default; + float length = 0.0f; float radius = 0.0f; QVector positions; bool operator==( const PointData &other ) const { - return radius == other.radius; + return length == other.length && radius == other.radius; } }; @@ -132,6 +133,13 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature return; const QgsPropertyCollection &ddp = mSymbol->dataDefinedProperties(); + const bool hasDDLength = ddp.isActive( QgsAbstract3DSymbol::Property::Length ); + float length = mSymbol->shapeProperty( QStringLiteral( "length" ) ).toFloat(); + if ( hasDDLength ) + { + length = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::Length, context.expressionContext(), length ) ); + } + const bool hasDDRadius = ddp.isActive( QgsAbstract3DSymbol::Property::Radius ); float radius = mSymbol->shapeProperty( QStringLiteral( "radius" ) ).toFloat(); if ( hasDDRadius ) @@ -143,6 +151,7 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), positions ); PointData newPointData; + newPointData.length = length; newPointData.radius = radius; PointData *existingPointData = std::find( out.begin(), out.end(), newPointData ); @@ -183,9 +192,21 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons { case Qgis::Point3DShape::Cylinder: { - const float length = mSymbol->shapeProperty( QStringLiteral( "length" ) ).toFloat(); - mZMin -= length * 0.5f; - mZMax += length * 0.5f; + float lengthMax = 0.0; + for ( const PointData &pointData : outNormal ) + { + if ( pointData.length > lengthMax ) + lengthMax = pointData.length; + } + + for ( const PointData &pointData : outSelected ) + { + if ( pointData.length > lengthMax ) + lengthMax = pointData.length; + } + + mZMin -= lengthMax * 0.5f; + mZMax += lengthMax * 0.5f; break; } @@ -211,9 +232,21 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons case Qgis::Point3DShape::Cone: { - const float length = mSymbol->shapeProperty( QStringLiteral( "length" ) ).toFloat(); - mZMin -= length * 0.5f; - mZMax += length * 0.5f; + float lengthMax = 0.0; + for ( const PointData &pointData : outNormal ) + { + if ( pointData.length > lengthMax ) + lengthMax = pointData.length; + } + + for ( const PointData &pointData : outSelected ) + { + if ( pointData.length > lengthMax ) + lengthMax = pointData.length; + } + + mZMin -= lengthMax * 0.5f; + mZMax += lengthMax * 0.5f; break; } @@ -381,12 +414,11 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 { case Qgis::Point3DShape::Cylinder: { - const float length = symbol->shapeProperty( QStringLiteral( "length" ) ).toFloat(); Qt3DExtras::QCylinderGeometry *geometry = new Qt3DExtras::QCylinderGeometry; // geometry->setRings(2); // how many vertices vertically // geometry->setSlices(8); // how many vertices on circumference geometry->setRadius( pointData.radius ); - geometry->setLength( length ); + geometry->setLength( pointData.length ); return geometry; } @@ -399,17 +431,16 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 case Qgis::Point3DShape::Cone: { - const float length = symbol->shapeProperty( QStringLiteral( "length" ) ).toFloat(); const float bottomRadius = symbol->shapeProperty( QStringLiteral( "bottomRadius" ) ).toFloat(); const float topRadius = symbol->shapeProperty( QStringLiteral( "topRadius" ) ).toFloat(); - Qt3DExtras::QConeGeometry *g = new Qt3DExtras::QConeGeometry; - g->setLength( length ); - g->setBottomRadius( bottomRadius ); - g->setTopRadius( topRadius ); - //g->setHasBottomEndcap(hasBottomEndcap); - //g->setHasTopEndcap(hasTopEndcap); - return g; + Qt3DExtras::QConeGeometry *geometry = new Qt3DExtras::QConeGeometry; + geometry->setLength( pointData.length ); + geometry->setBottomRadius( bottomRadius ); + geometry->setTopRadius( topRadius ); + // geometry->setHasBottomEndcap(hasBottomEndcap); + // geometry->setHasTopEndcap(hasTopEndcap); + return geometry; } case Qgis::Point3DShape::Cube: From 7c229b09d7ba907e8cdacc6590c8c0c03144221e Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 15:40:07 +0200 Subject: [PATCH 07/17] qgspoint3dsymbolwidget: Add support for data defined length --- src/app/3d/qgspoint3dsymbolwidget.cpp | 10 +++++++--- src/ui/3d/point3dsymbolwidget.ui | 8 ++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/app/3d/qgspoint3dsymbolwidget.cpp b/src/app/3d/qgspoint3dsymbolwidget.cpp index a32bd501cec4..bad6736e7315 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.cpp +++ b/src/app/3d/qgspoint3dsymbolwidget.cpp @@ -79,6 +79,7 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) connect( spinBillboardHeight, static_cast( &QDoubleSpinBox::valueChanged ), spinTZ, &QDoubleSpinBox::setValue ); connect( spinTZ, static_cast( &QDoubleSpinBox::valueChanged ), spinBillboardHeight, &QDoubleSpinBox::setValue ); + connect( mBtnLengthOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); } @@ -146,6 +147,7 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsAbstract3DSymbol *symbol, QgsVe // setSymbol is only called once. // the data defined properties need to be all init to make them work if a user-interaction // changes the shape. + mBtnLengthOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Length ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Radius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); widgetMaterial->setSettings( pointSymbol->materialSettings(), layer ); @@ -204,6 +206,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() vm[QStringLiteral( "radius" )] = spinRadius->value(); vm[QStringLiteral( "length" )] = spinLength->value(); ddp.setProperty( QgsAbstract3DSymbol::Property::Radius, mBtnRadiusOverride->toProperty() ); + ddp.setProperty( QgsAbstract3DSymbol::Property::Length, mBtnLengthOverride->toProperty() ); break; case Qgis::Point3DShape::Cube: vm[QStringLiteral( "size" )] = spinSize->value(); @@ -212,6 +215,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() vm[QStringLiteral( "topRadius" )] = spinTopRadius->value(); vm[QStringLiteral( "bottomRadius" )] = spinBottomRadius->value(); vm[QStringLiteral( "length" )] = spinLength->value(); + ddp.setProperty( QgsAbstract3DSymbol::Property::Length, mBtnLengthOverride->toProperty() ); break; case Qgis::Point3DShape::Plane: vm[QStringLiteral( "size" )] = spinSize->value(); @@ -265,7 +269,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() << labelMinorRadius << spinMinorRadius << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius - << labelLength << spinLength + << labelLength << spinLength << mBtnLengthOverride << labelModel << lineEditModel << labelBillboardHeight << spinBillboardHeight << labelBillboardSymbol << btnChangeSymbol; @@ -279,13 +283,13 @@ void QgsPoint3DSymbolWidget::onShapeChanged() activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride; break; case Qgis::Point3DShape::Cylinder: - activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelLength << spinLength; + activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelLength << spinLength << mBtnLengthOverride; break; case Qgis::Point3DShape::Cube: activeWidgets << labelSize << spinSize; break; case Qgis::Point3DShape::Cone: - activeWidgets << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius << labelLength << spinLength; + activeWidgets << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius << labelLength << spinLength << mBtnLengthOverride; break; case Qgis::Point3DShape::Plane: activeWidgets << labelSize << spinSize; diff --git a/src/ui/3d/point3dsymbolwidget.ui b/src/ui/3d/point3dsymbolwidget.ui index 340dbd48d402..67dd2cd1d48e 100644 --- a/src/ui/3d/point3dsymbolwidget.ui +++ b/src/ui/3d/point3dsymbolwidget.ui @@ -319,6 +319,13 @@
+ + + + + + + @@ -482,6 +489,7 @@ spinBottomRadius spinSize spinLength + mBtnLengthOverride> spinBillboardHeight btnChangeSymbol cboAltClamping From 03d2338894e11f1c2707bef79cadade802dfd48e Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 15:41:25 +0200 Subject: [PATCH 08/17] qgsabstract3dsymbol: Add size symbol definition This will be used by `QgsPoint3DSymbol` in the next commit. --- python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- .../PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + python/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + src/core/3d/qgsabstract3dsymbol.cpp | 1 + src/core/3d/qgsabstract3dsymbol.h | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py index acc81a0d6cf9..6147173c9fcf 100644 --- a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py @@ -16,5 +16,9 @@ QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ +QgsAbstract3DSymbol.PropertySize = QgsAbstract3DSymbol.Property.Size +QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.Size +QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True +QgsAbstract3DSymbol.PropertySize.__doc__ = "Size" +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ # -- diff --git a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index e21d19ea844c..bbe4762530f8 100644 --- a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -67,6 +67,7 @@ Returns the list of the vector layer geometry types which are compatible with th ExtrusionHeight, Length, Radius, + Size, }; static const QgsPropertiesDefinition &propertyDefinitions(); diff --git a/python/core/auto_additions/qgsabstract3dsymbol.py b/python/core/auto_additions/qgsabstract3dsymbol.py index acc81a0d6cf9..6147173c9fcf 100644 --- a/python/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/core/auto_additions/qgsabstract3dsymbol.py @@ -16,5 +16,9 @@ QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ +QgsAbstract3DSymbol.PropertySize = QgsAbstract3DSymbol.Property.Size +QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.Size +QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True +QgsAbstract3DSymbol.PropertySize.__doc__ = "Size" +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ # -- diff --git a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index fe655f717121..3fa2efd1a76e 100644 --- a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -67,6 +67,7 @@ Returns the list of the vector layer geometry types which are compatible with th ExtrusionHeight, Length, Radius, + Size, }; static const QgsPropertiesDefinition &propertyDefinitions(); diff --git a/src/core/3d/qgsabstract3dsymbol.cpp b/src/core/3d/qgsabstract3dsymbol.cpp index 112a1a44299e..28b54cfd333b 100644 --- a/src/core/3d/qgsabstract3dsymbol.cpp +++ b/src/core/3d/qgsabstract3dsymbol.cpp @@ -48,6 +48,7 @@ void QgsAbstract3DSymbol::initPropertyDefinitions() { static_cast< int >( Property::ExtrusionHeight ), QgsPropertyDefinition( "extrusionHeight", QObject::tr( "ExtrusionHeight" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Length ), QgsPropertyDefinition( "length", QObject::tr( "Length" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Radius ), QgsPropertyDefinition( "radius", QObject::tr( "Radius" ), QgsPropertyDefinition::DoublePositive, origin ) }, + { static_cast< int >( Property::Size ), QgsPropertyDefinition( "size", QObject::tr( "Size" ), QgsPropertyDefinition::DoublePositive, origin ) }, }; } diff --git a/src/core/3d/qgsabstract3dsymbol.h b/src/core/3d/qgsabstract3dsymbol.h index 0091cd4961db..9a9d7eee6137 100644 --- a/src/core/3d/qgsabstract3dsymbol.h +++ b/src/core/3d/qgsabstract3dsymbol.h @@ -72,6 +72,7 @@ class CORE_EXPORT QgsAbstract3DSymbol ExtrusionHeight SIP_MONKEYPATCH_COMPAT_NAME( PropertyExtrusionHeight ), //!< Extrusion height (zero means no extrusion) Length SIP_MONKEYPATCH_COMPAT_NAME( PropertyLength ), //!< Length Radius SIP_MONKEYPATCH_COMPAT_NAME( PropertyRadius ), //!< Radius + Size SIP_MONKEYPATCH_COMPAT_NAME( PropertySize ), //!< Size }; // *INDENT-ON* From 480fdc53afd2b8577f8c83a9869f1306c01917a3 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 15:49:33 +0200 Subject: [PATCH 09/17] qgspoint3dsymbol: Add support for data defined size --- src/3d/symbols/qgspoint3dsymbol_p.cpp | 67 ++++++++++++++++++++------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index 182810c437d7..b64caff28abe 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -94,11 +94,12 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler float length = 0.0f; float radius = 0.0f; + float size = 0.0f; QVector positions; bool operator==( const PointData &other ) const { - return length == other.length && radius == other.radius; + return length == other.length && radius == other.radius && size == other.size; } }; @@ -147,12 +148,20 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature radius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::Radius, context.expressionContext(), radius ) ); } + const bool hasDDSize = ddp.isActive( QgsAbstract3DSymbol::Property::Size ); + float size = mSymbol->shapeProperty( QStringLiteral( "size" ) ).toFloat(); + if ( hasDDSize ) + { + size = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::Size, context.expressionContext(), size ) ); + } + QVector positions; Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), positions ); PointData newPointData; newPointData.length = length; newPointData.radius = radius; + newPointData.size = size; PointData *existingPointData = std::find( out.begin(), out.end(), newPointData ); if ( existingPointData == out.end() ) @@ -252,9 +261,21 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons case Qgis::Point3DShape::Cube: { - const float size = mSymbol->shapeProperty( QStringLiteral( "size" ) ).toFloat(); - mZMin -= size * 0.5f; - mZMax += size * 0.5f; + float sizeMax = 0.0; + for ( const PointData &pointData : outNormal ) + { + if ( pointData.size > sizeMax ) + sizeMax = pointData.size; + } + + for ( const PointData &pointData : outSelected ) + { + if ( pointData.size > sizeMax ) + sizeMax = pointData.size; + } + + mZMin -= sizeMax * 0.5f; + mZMax += sizeMax * 0.5f; break; } @@ -282,9 +303,21 @@ void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, cons { // worst case scenario -- even though planes are usually rotated so that they are flat, // let's account for possible overridden rotation - const float size = mSymbol->shapeProperty( QStringLiteral( "size" ) ).toFloat(); - mZMin -= size * 0.5f; - mZMax += size * 0.5f; + float sizeMax = 0.0; + for ( const PointData &pointData : outNormal ) + { + if ( pointData.size > sizeMax ) + sizeMax = pointData.size; + } + + for ( const PointData &pointData : outSelected ) + { + if ( pointData.size > sizeMax ) + sizeMax = pointData.size; + } + + mZMin -= sizeMax * 0.5f; + mZMax += sizeMax * 0.5f; break; } @@ -445,12 +478,11 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 case Qgis::Point3DShape::Cube: { - const float size = symbol->shapeProperty( QStringLiteral( "size" ) ).toFloat(); - Qt3DExtras::QCuboidGeometry *g = new Qt3DExtras::QCuboidGeometry; - g->setXExtent( size ); - g->setYExtent( size ); - g->setZExtent( size ); - return g; + Qt3DExtras::QCuboidGeometry *geometry = new Qt3DExtras::QCuboidGeometry; + geometry->setXExtent( pointData.size ); + geometry->setYExtent( pointData.size ); + geometry->setZExtent( pointData.size ); + return geometry; } case Qgis::Point3DShape::Torus: @@ -464,11 +496,10 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 case Qgis::Point3DShape::Plane: { - const float size = symbol->shapeProperty( QStringLiteral( "size" ) ).toFloat(); - Qt3DExtras::QPlaneGeometry *g = new Qt3DExtras::QPlaneGeometry; - g->setWidth( size ); - g->setHeight( size ); - return g; + Qt3DExtras::QPlaneGeometry *geometry = new Qt3DExtras::QPlaneGeometry; + geometry->setWidth( pointData.size ); + geometry->setHeight( pointData.size ); + return geometry; } case Qgis::Point3DShape::ExtrudedText: From 44f7fd7c1be648ca661e79a11b3a873d1a605e83 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 15:55:34 +0200 Subject: [PATCH 10/17] qgspoint3dsymbolwidget: Add support for data defined size --- src/app/3d/qgspoint3dsymbolwidget.cpp | 10 +++++++--- src/ui/3d/point3dsymbolwidget.ui | 8 ++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/app/3d/qgspoint3dsymbolwidget.cpp b/src/app/3d/qgspoint3dsymbolwidget.cpp index bad6736e7315..968937dbdbe6 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.cpp +++ b/src/app/3d/qgspoint3dsymbolwidget.cpp @@ -81,6 +81,7 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) connect( mBtnLengthOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); + connect( mBtnSizeOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); } Qgs3DSymbolWidget *QgsPoint3DSymbolWidget::create( QgsVectorLayer * ) @@ -149,6 +150,7 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsAbstract3DSymbol *symbol, QgsVe // changes the shape. mBtnLengthOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Length ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Radius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); + mBtnSizeOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Size ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); widgetMaterial->setSettings( pointSymbol->materialSettings(), layer ); widgetMaterial->setTechnique( technique ); @@ -210,6 +212,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() break; case Qgis::Point3DShape::Cube: vm[QStringLiteral( "size" )] = spinSize->value(); + ddp.setProperty( QgsAbstract3DSymbol::Property::Size, mBtnSizeOverride->toProperty() ); break; case Qgis::Point3DShape::Cone: vm[QStringLiteral( "topRadius" )] = spinTopRadius->value(); @@ -219,6 +222,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() break; case Qgis::Point3DShape::Plane: vm[QStringLiteral( "size" )] = spinSize->value(); + ddp.setProperty( QgsAbstract3DSymbol::Property::Size, mBtnSizeOverride->toProperty() ); break; case Qgis::Point3DShape::Torus: vm[QStringLiteral( "radius" )] = spinRadius->value(); @@ -264,7 +268,7 @@ QString QgsPoint3DSymbolWidget::symbolType() const void QgsPoint3DSymbolWidget::onShapeChanged() { QList allWidgets; - allWidgets << labelSize << spinSize + allWidgets << labelSize << spinSize << mBtnSizeOverride << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius << labelTopRadius << spinTopRadius @@ -286,13 +290,13 @@ void QgsPoint3DSymbolWidget::onShapeChanged() activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelLength << spinLength << mBtnLengthOverride; break; case Qgis::Point3DShape::Cube: - activeWidgets << labelSize << spinSize; + activeWidgets << labelSize << spinSize << mBtnSizeOverride; break; case Qgis::Point3DShape::Cone: activeWidgets << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius << labelLength << spinLength << mBtnLengthOverride; break; case Qgis::Point3DShape::Plane: - activeWidgets << labelSize << spinSize; + activeWidgets << labelSize << spinSize << mBtnSizeOverride; break; case Qgis::Point3DShape::Torus: activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius; diff --git a/src/ui/3d/point3dsymbolwidget.ui b/src/ui/3d/point3dsymbolwidget.ui index 67dd2cd1d48e..692231a42a72 100644 --- a/src/ui/3d/point3dsymbolwidget.ui +++ b/src/ui/3d/point3dsymbolwidget.ui @@ -234,6 +234,13 @@ + + + + + + + @@ -488,6 +495,7 @@ spinTopRadius spinBottomRadius spinSize + mBtnSizeOverride spinLength mBtnLengthOverride> spinBillboardHeight From 3543d95659bc68f5cc8fc2a5f86f217c1420839e Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 16:40:57 +0200 Subject: [PATCH 11/17] qgsabstract3dsymbol: Add bottom/top radius symbol definition This will be used by `QgsPoint3DSymbol` in the next commit. --- .../PyQt6/core/auto_additions/qgsabstract3dsymbol.py | 10 +++++++++- .../core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 2 ++ python/core/auto_additions/qgsabstract3dsymbol.py | 10 +++++++++- .../core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 2 ++ src/core/3d/qgsabstract3dsymbol.cpp | 2 ++ src/core/3d/qgsabstract3dsymbol.h | 2 ++ 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py index 6147173c9fcf..ee01c34bda2e 100644 --- a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py @@ -16,9 +16,17 @@ QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" +QgsAbstract3DSymbol.PropertyHeight = QgsAbstract3DSymbol.Property.BottomRadius +QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.BottomRadius +QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyHeight.__doc__ = "Bottom Radius" +QgsAbstract3DSymbol.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius +QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius +QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyHeight.__doc__ = "Top Radius" QgsAbstract3DSymbol.PropertySize = QgsAbstract3DSymbol.Property.Size QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.Size QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True QgsAbstract3DSymbol.PropertySize.__doc__ = "Size" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.BottomRadius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.TopRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ # -- diff --git a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index bbe4762530f8..a315d447a616 100644 --- a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -67,6 +67,8 @@ Returns the list of the vector layer geometry types which are compatible with th ExtrusionHeight, Length, Radius, + BottomRadius, + TopRadius, Size, }; diff --git a/python/core/auto_additions/qgsabstract3dsymbol.py b/python/core/auto_additions/qgsabstract3dsymbol.py index 6147173c9fcf..ee01c34bda2e 100644 --- a/python/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/core/auto_additions/qgsabstract3dsymbol.py @@ -16,9 +16,17 @@ QgsAbstract3DSymbol.Property.PropertyRadius = QgsAbstract3DSymbol.Property.Radius QgsAbstract3DSymbol.PropertyRadius.is_monkey_patched = True QgsAbstract3DSymbol.PropertyRadius.__doc__ = "Radius" +QgsAbstract3DSymbol.PropertyHeight = QgsAbstract3DSymbol.Property.BottomRadius +QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.BottomRadius +QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyHeight.__doc__ = "Bottom Radius" +QgsAbstract3DSymbol.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius +QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius +QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True +QgsAbstract3DSymbol.PropertyHeight.__doc__ = "Top Radius" QgsAbstract3DSymbol.PropertySize = QgsAbstract3DSymbol.Property.Size QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.Size QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True QgsAbstract3DSymbol.PropertySize.__doc__ = "Size" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.BottomRadius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.TopRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ # -- diff --git a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index 3fa2efd1a76e..b1fc087d7f84 100644 --- a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -67,6 +67,8 @@ Returns the list of the vector layer geometry types which are compatible with th ExtrusionHeight, Length, Radius, + BottomRadius, + TopRadius, Size, }; diff --git a/src/core/3d/qgsabstract3dsymbol.cpp b/src/core/3d/qgsabstract3dsymbol.cpp index 28b54cfd333b..6d961185031a 100644 --- a/src/core/3d/qgsabstract3dsymbol.cpp +++ b/src/core/3d/qgsabstract3dsymbol.cpp @@ -48,6 +48,8 @@ void QgsAbstract3DSymbol::initPropertyDefinitions() { static_cast< int >( Property::ExtrusionHeight ), QgsPropertyDefinition( "extrusionHeight", QObject::tr( "ExtrusionHeight" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Length ), QgsPropertyDefinition( "length", QObject::tr( "Length" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Radius ), QgsPropertyDefinition( "radius", QObject::tr( "Radius" ), QgsPropertyDefinition::DoublePositive, origin ) }, + { static_cast< int >( Property::BottomRadius ), QgsPropertyDefinition( "bottomRadius", QObject::tr( "BottomRadius" ), QgsPropertyDefinition::DoublePositive, origin ) }, + { static_cast< int >( Property::TopRadius ), QgsPropertyDefinition( "topRadius", QObject::tr( "TopRadius" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Size ), QgsPropertyDefinition( "size", QObject::tr( "Size" ), QgsPropertyDefinition::DoublePositive, origin ) }, }; diff --git a/src/core/3d/qgsabstract3dsymbol.h b/src/core/3d/qgsabstract3dsymbol.h index 9a9d7eee6137..fd25126edb98 100644 --- a/src/core/3d/qgsabstract3dsymbol.h +++ b/src/core/3d/qgsabstract3dsymbol.h @@ -72,6 +72,8 @@ class CORE_EXPORT QgsAbstract3DSymbol ExtrusionHeight SIP_MONKEYPATCH_COMPAT_NAME( PropertyExtrusionHeight ), //!< Extrusion height (zero means no extrusion) Length SIP_MONKEYPATCH_COMPAT_NAME( PropertyLength ), //!< Length Radius SIP_MONKEYPATCH_COMPAT_NAME( PropertyRadius ), //!< Radius + BottomRadius SIP_MONKEYPATCH_COMPAT_NAME( PropertyHeight ), //!< Bottom Radius + TopRadius SIP_MONKEYPATCH_COMPAT_NAME( PropertyHeight ), //!< Top Radius Size SIP_MONKEYPATCH_COMPAT_NAME( PropertySize ), //!< Size }; // *INDENT-ON* From 8f6cdae3836e245f04c178d401cf15e740c4c632 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 16:46:34 +0200 Subject: [PATCH 12/17] qgspoint3dsymbol: Add support for data defined bottom/top radius --- src/3d/symbols/qgspoint3dsymbol_p.cpp | 29 +++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index b64caff28abe..bf00bd935020 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -94,12 +94,16 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler float length = 0.0f; float radius = 0.0f; + float bottomRadius = 0.0f; + float topRadius = 0.0f; float size = 0.0f; QVector positions; bool operator==( const PointData &other ) const { - return length == other.length && radius == other.radius && size == other.size; + return ( length == other.length && radius == other.radius + && bottomRadius == other.bottomRadius && topRadius == other.topRadius + && size == other.size ); } }; @@ -148,6 +152,20 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature radius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::Radius, context.expressionContext(), radius ) ); } + const bool hasDDBottomRadius = ddp.isActive( QgsAbstract3DSymbol::Property::BottomRadius ); + float bottomRadius = mSymbol->shapeProperty( QStringLiteral( "bottomRadius" ) ).toFloat(); + if ( hasDDBottomRadius ) + { + bottomRadius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::BottomRadius, context.expressionContext(), bottomRadius ) ); + } + + const bool hasDDTopRadius = ddp.isActive( QgsAbstract3DSymbol::Property::TopRadius ); + float topRadius = mSymbol->shapeProperty( QStringLiteral( "topRadius" ) ).toFloat(); + if ( hasDDTopRadius ) + { + topRadius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::TopRadius, context.expressionContext(), topRadius ) ); + } + const bool hasDDSize = ddp.isActive( QgsAbstract3DSymbol::Property::Size ); float size = mSymbol->shapeProperty( QStringLiteral( "size" ) ).toFloat(); if ( hasDDSize ) @@ -161,6 +179,8 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature PointData newPointData; newPointData.length = length; newPointData.radius = radius; + newPointData.bottomRadius = bottomRadius; + newPointData.topRadius = topRadius; newPointData.size = size; PointData *existingPointData = std::find( out.begin(), out.end(), newPointData ); @@ -464,13 +484,10 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 case Qgis::Point3DShape::Cone: { - const float bottomRadius = symbol->shapeProperty( QStringLiteral( "bottomRadius" ) ).toFloat(); - const float topRadius = symbol->shapeProperty( QStringLiteral( "topRadius" ) ).toFloat(); - Qt3DExtras::QConeGeometry *geometry = new Qt3DExtras::QConeGeometry; geometry->setLength( pointData.length ); - geometry->setBottomRadius( bottomRadius ); - geometry->setTopRadius( topRadius ); + geometry->setBottomRadius( pointData.bottomRadius ); + geometry->setTopRadius( pointData.topRadius ); // geometry->setHasBottomEndcap(hasBottomEndcap); // geometry->setHasTopEndcap(hasTopEndcap); return geometry; From 592244b3406b8126ef7d79ab17fdd2314c01d3a2 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 17:06:57 +0200 Subject: [PATCH 13/17] qgspoint3dsymbolwidget: Add support for data defined bottom/top radius --- src/app/3d/qgspoint3dsymbolwidget.cpp | 12 +++++++++--- src/ui/3d/point3dsymbolwidget.ui | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/app/3d/qgspoint3dsymbolwidget.cpp b/src/app/3d/qgspoint3dsymbolwidget.cpp index 968937dbdbe6..d5746a7c5662 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.cpp +++ b/src/app/3d/qgspoint3dsymbolwidget.cpp @@ -81,6 +81,8 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) connect( mBtnLengthOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); + connect( mBtnBottomRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); + connect( mBtnTopRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnSizeOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); } @@ -150,6 +152,8 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsAbstract3DSymbol *symbol, QgsVe // changes the shape. mBtnLengthOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Length ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Radius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); + mBtnBottomRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::BottomRadius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); + mBtnTopRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::TopRadius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnSizeOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Size ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); widgetMaterial->setSettings( pointSymbol->materialSettings(), layer ); @@ -219,6 +223,8 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() vm[QStringLiteral( "bottomRadius" )] = spinBottomRadius->value(); vm[QStringLiteral( "length" )] = spinLength->value(); ddp.setProperty( QgsAbstract3DSymbol::Property::Length, mBtnLengthOverride->toProperty() ); + ddp.setProperty( QgsAbstract3DSymbol::Property::TopRadius, mBtnTopRadiusOverride->toProperty() ); + ddp.setProperty( QgsAbstract3DSymbol::Property::BottomRadius, mBtnBottomRadiusOverride->toProperty() ); break; case Qgis::Point3DShape::Plane: vm[QStringLiteral( "size" )] = spinSize->value(); @@ -271,8 +277,8 @@ void QgsPoint3DSymbolWidget::onShapeChanged() allWidgets << labelSize << spinSize << mBtnSizeOverride << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius - << labelTopRadius << spinTopRadius - << labelBottomRadius << spinBottomRadius + << labelTopRadius << spinTopRadius << mBtnTopRadiusOverride + << labelBottomRadius << spinBottomRadius << mBtnBottomRadiusOverride << labelLength << spinLength << mBtnLengthOverride << labelModel << lineEditModel << labelBillboardHeight << spinBillboardHeight << labelBillboardSymbol << btnChangeSymbol; @@ -293,7 +299,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() activeWidgets << labelSize << spinSize << mBtnSizeOverride; break; case Qgis::Point3DShape::Cone: - activeWidgets << labelTopRadius << spinTopRadius << labelBottomRadius << spinBottomRadius << labelLength << spinLength << mBtnLengthOverride; + activeWidgets << labelTopRadius << spinTopRadius << mBtnTopRadiusOverride << labelBottomRadius << spinBottomRadius << mBtnBottomRadiusOverride << labelLength << spinLength << mBtnLengthOverride; break; case Qgis::Point3DShape::Plane: activeWidgets << labelSize << spinSize << mBtnSizeOverride; diff --git a/src/ui/3d/point3dsymbolwidget.ui b/src/ui/3d/point3dsymbolwidget.ui index 692231a42a72..8dc75e0eecae 100644 --- a/src/ui/3d/point3dsymbolwidget.ui +++ b/src/ui/3d/point3dsymbolwidget.ui @@ -295,6 +295,13 @@ + + + + + + + @@ -434,6 +441,13 @@ + + + + + + + @@ -493,7 +507,9 @@ mBtnRadiusOverride spinMinorRadius spinTopRadius + mBtnTopRadiusOverride spinBottomRadius + mBtnBottomRadiusOverride spinSize mBtnSizeOverride spinLength From f28c724167d711e7d80d3cfe174543610021830a Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 17:11:14 +0200 Subject: [PATCH 14/17] qgsabstract3dsymbol: Add minor radius symbol definition This will be used by `QgsPoint3DSymbol` in the next commit. --- python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- .../PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + python/core/auto_additions/qgsabstract3dsymbol.py | 6 +++++- python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in | 1 + src/core/3d/qgsabstract3dsymbol.cpp | 1 + src/core/3d/qgsabstract3dsymbol.h | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py index ee01c34bda2e..48975ee682a1 100644 --- a/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/PyQt6/core/auto_additions/qgsabstract3dsymbol.py @@ -20,6 +20,10 @@ QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.BottomRadius QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True QgsAbstract3DSymbol.PropertyHeight.__doc__ = "Bottom Radius" +QgsAbstract3DSymbol.PropertySize = QgsAbstract3DSymbol.Property.MinorRadius +QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.MinorRadius +QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True +QgsAbstract3DSymbol.PropertySize.__doc__ = "Minor Radius" QgsAbstract3DSymbol.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True @@ -28,5 +32,5 @@ QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.Size QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True QgsAbstract3DSymbol.PropertySize.__doc__ = "Size" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.BottomRadius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.TopRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.BottomRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.MinorRadius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.TopRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ # -- diff --git a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index a315d447a616..85c034b3af1a 100644 --- a/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/PyQt6/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -68,6 +68,7 @@ Returns the list of the vector layer geometry types which are compatible with th Length, Radius, BottomRadius, + MinorRadius, TopRadius, Size, }; diff --git a/python/core/auto_additions/qgsabstract3dsymbol.py b/python/core/auto_additions/qgsabstract3dsymbol.py index ee01c34bda2e..48975ee682a1 100644 --- a/python/core/auto_additions/qgsabstract3dsymbol.py +++ b/python/core/auto_additions/qgsabstract3dsymbol.py @@ -20,6 +20,10 @@ QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.BottomRadius QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True QgsAbstract3DSymbol.PropertyHeight.__doc__ = "Bottom Radius" +QgsAbstract3DSymbol.PropertySize = QgsAbstract3DSymbol.Property.MinorRadius +QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.MinorRadius +QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True +QgsAbstract3DSymbol.PropertySize.__doc__ = "Minor Radius" QgsAbstract3DSymbol.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius QgsAbstract3DSymbol.Property.PropertyHeight = QgsAbstract3DSymbol.Property.TopRadius QgsAbstract3DSymbol.PropertyHeight.is_monkey_patched = True @@ -28,5 +32,5 @@ QgsAbstract3DSymbol.Property.PropertySize = QgsAbstract3DSymbol.Property.Size QgsAbstract3DSymbol.PropertySize.is_monkey_patched = True QgsAbstract3DSymbol.PropertySize.__doc__ = "Size" -QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.BottomRadius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.TopRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ +QgsAbstract3DSymbol.Property.__doc__ = "Data definable properties.\n\n" + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.Height.__doc__ + '\n' + '* ``PropertyExtrusionHeight``: ' + QgsAbstract3DSymbol.Property.ExtrusionHeight.__doc__ + '\n' + '* ``PropertyLength``: ' + QgsAbstract3DSymbol.Property.Length.__doc__ + '\n' + '* ``PropertyRadius``: ' + QgsAbstract3DSymbol.Property.Radius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.BottomRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.MinorRadius.__doc__ + '\n' + '* ``PropertyHeight``: ' + QgsAbstract3DSymbol.Property.TopRadius.__doc__ + '\n' + '* ``PropertySize``: ' + QgsAbstract3DSymbol.Property.Size.__doc__ # -- diff --git a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in index b1fc087d7f84..4f99b2575716 100644 --- a/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in +++ b/python/core/auto_generated/3d/qgsabstract3dsymbol.sip.in @@ -68,6 +68,7 @@ Returns the list of the vector layer geometry types which are compatible with th Length, Radius, BottomRadius, + MinorRadius, TopRadius, Size, }; diff --git a/src/core/3d/qgsabstract3dsymbol.cpp b/src/core/3d/qgsabstract3dsymbol.cpp index 6d961185031a..01f3151713bc 100644 --- a/src/core/3d/qgsabstract3dsymbol.cpp +++ b/src/core/3d/qgsabstract3dsymbol.cpp @@ -49,6 +49,7 @@ void QgsAbstract3DSymbol::initPropertyDefinitions() { static_cast< int >( Property::Length ), QgsPropertyDefinition( "length", QObject::tr( "Length" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Radius ), QgsPropertyDefinition( "radius", QObject::tr( "Radius" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::BottomRadius ), QgsPropertyDefinition( "bottomRadius", QObject::tr( "BottomRadius" ), QgsPropertyDefinition::DoublePositive, origin ) }, + { static_cast< int >( Property::MinorRadius ), QgsPropertyDefinition( "minorRadius", QObject::tr( "MinorRadius" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::TopRadius ), QgsPropertyDefinition( "topRadius", QObject::tr( "TopRadius" ), QgsPropertyDefinition::DoublePositive, origin ) }, { static_cast< int >( Property::Size ), QgsPropertyDefinition( "size", QObject::tr( "Size" ), QgsPropertyDefinition::DoublePositive, origin ) }, }; diff --git a/src/core/3d/qgsabstract3dsymbol.h b/src/core/3d/qgsabstract3dsymbol.h index fd25126edb98..e6b7bf4135a2 100644 --- a/src/core/3d/qgsabstract3dsymbol.h +++ b/src/core/3d/qgsabstract3dsymbol.h @@ -73,6 +73,7 @@ class CORE_EXPORT QgsAbstract3DSymbol Length SIP_MONKEYPATCH_COMPAT_NAME( PropertyLength ), //!< Length Radius SIP_MONKEYPATCH_COMPAT_NAME( PropertyRadius ), //!< Radius BottomRadius SIP_MONKEYPATCH_COMPAT_NAME( PropertyHeight ), //!< Bottom Radius + MinorRadius SIP_MONKEYPATCH_COMPAT_NAME( PropertySize ), //!< Minor Radius TopRadius SIP_MONKEYPATCH_COMPAT_NAME( PropertyHeight ), //!< Top Radius Size SIP_MONKEYPATCH_COMPAT_NAME( PropertySize ), //!< Size }; From 2ef348a6a83d45638c143e7324b028a8afad66d6 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 17:13:33 +0200 Subject: [PATCH 15/17] qgspoint3dsymbol: Add support for data defined minor radius --- src/3d/symbols/qgspoint3dsymbol_p.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index bf00bd935020..3f89790141f0 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -95,6 +95,7 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler float length = 0.0f; float radius = 0.0f; float bottomRadius = 0.0f; + float minorRadius = 0.0f; float topRadius = 0.0f; float size = 0.0f; QVector positions; @@ -102,8 +103,8 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler bool operator==( const PointData &other ) const { return ( length == other.length && radius == other.radius - && bottomRadius == other.bottomRadius && topRadius == other.topRadius - && size == other.size ); + && bottomRadius == other.bottomRadius && minorRadius == other.minorRadius + && topRadius == other.topRadius && size == other.size ); } }; @@ -159,6 +160,13 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature bottomRadius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::BottomRadius, context.expressionContext(), bottomRadius ) ); } + const bool hasDDMinorRadius = ddp.isActive( QgsAbstract3DSymbol::Property::MinorRadius ); + float minorRadius = mSymbol->shapeProperty( QStringLiteral( "minorRadius" ) ).toFloat(); + if ( hasDDMinorRadius ) + { + minorRadius = static_cast( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::MinorRadius, context.expressionContext(), minorRadius ) ); + } + const bool hasDDTopRadius = ddp.isActive( QgsAbstract3DSymbol::Property::TopRadius ); float topRadius = mSymbol->shapeProperty( QStringLiteral( "topRadius" ) ).toFloat(); if ( hasDDTopRadius ) @@ -180,6 +188,7 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature newPointData.length = length; newPointData.radius = radius; newPointData.bottomRadius = bottomRadius; + newPointData.minorRadius = minorRadius; newPointData.topRadius = topRadius; newPointData.size = size; @@ -504,10 +513,9 @@ Qt3DQGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( const QgsPoint3 case Qgis::Point3DShape::Torus: { - const float minorRadius = symbol->shapeProperty( QStringLiteral( "minorRadius" ) ).toFloat(); Qt3DExtras::QTorusGeometry *geometry = new Qt3DExtras::QTorusGeometry; geometry->setRadius( pointData.radius ); - geometry->setMinorRadius( minorRadius ); + geometry->setMinorRadius( pointData.minorRadius ); return geometry; } From db634918a9d17d7b5ac0866a50d60471e6ece54c Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 9 Jun 2024 17:18:41 +0200 Subject: [PATCH 16/17] qgspoint3dsymbolwidget: Add support for data defined minor radius --- src/app/3d/qgspoint3dsymbolwidget.cpp | 7 +++++-- src/ui/3d/point3dsymbolwidget.ui | 8 ++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/app/3d/qgspoint3dsymbolwidget.cpp b/src/app/3d/qgspoint3dsymbolwidget.cpp index d5746a7c5662..f470731dd376 100644 --- a/src/app/3d/qgspoint3dsymbolwidget.cpp +++ b/src/app/3d/qgspoint3dsymbolwidget.cpp @@ -82,6 +82,7 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent ) connect( mBtnLengthOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnBottomRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); + connect( mBtnMinorRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnTopRadiusOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); connect( mBtnSizeOverride, &QgsPropertyOverrideButton::changed, this, &QgsPoint3DSymbolWidget::changed ); } @@ -153,6 +154,7 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsAbstract3DSymbol *symbol, QgsVe mBtnLengthOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Length ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Radius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnBottomRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::BottomRadius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); + mBtnMinorRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::MinorRadius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnTopRadiusOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::TopRadius ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); mBtnSizeOverride->init( static_cast< int >( QgsAbstract3DSymbol::Property::Size ), pointSymbol->dataDefinedProperties(), QgsAbstract3DSymbol::propertyDefinitions(), layer, true ); @@ -234,6 +236,7 @@ QgsAbstract3DSymbol *QgsPoint3DSymbolWidget::symbol() vm[QStringLiteral( "radius" )] = spinRadius->value(); vm[QStringLiteral( "minorRadius" )] = spinMinorRadius->value(); ddp.setProperty( QgsAbstract3DSymbol::Property::Radius, mBtnRadiusOverride->toProperty() ); + ddp.setProperty( QgsAbstract3DSymbol::Property::MinorRadius, mBtnMinorRadiusOverride->toProperty() ); break; case Qgis::Point3DShape::Model: vm[QStringLiteral( "model" )] = lineEditModel->source(); @@ -276,7 +279,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() QList allWidgets; allWidgets << labelSize << spinSize << mBtnSizeOverride << labelRadius << spinRadius << mBtnRadiusOverride - << labelMinorRadius << spinMinorRadius + << labelMinorRadius << spinMinorRadius << mBtnMinorRadiusOverride << labelTopRadius << spinTopRadius << mBtnTopRadiusOverride << labelBottomRadius << spinBottomRadius << mBtnBottomRadiusOverride << labelLength << spinLength << mBtnLengthOverride @@ -305,7 +308,7 @@ void QgsPoint3DSymbolWidget::onShapeChanged() activeWidgets << labelSize << spinSize << mBtnSizeOverride; break; case Qgis::Point3DShape::Torus: - activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius; + activeWidgets << labelRadius << spinRadius << mBtnRadiusOverride << labelMinorRadius << spinMinorRadius << mBtnMinorRadiusOverride; break; case Qgis::Point3DShape::Model: activeWidgets << labelModel << lineEditModel; diff --git a/src/ui/3d/point3dsymbolwidget.ui b/src/ui/3d/point3dsymbolwidget.ui index 8dc75e0eecae..b7f0c8c040f8 100644 --- a/src/ui/3d/point3dsymbolwidget.ui +++ b/src/ui/3d/point3dsymbolwidget.ui @@ -370,6 +370,13 @@ + + + + + + + @@ -506,6 +513,7 @@ spinRadius mBtnRadiusOverride spinMinorRadius + mBtnMinorRadiusOverride spinTopRadius mBtnTopRadiusOverride spinBottomRadius From c5cc462f81529521077deb4ab87acc41f76be425 Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Fri, 28 Jun 2024 16:49:42 +0200 Subject: [PATCH 17/17] qgspoint3dsymbol_p: Add comments to instanced handler functions --- src/3d/symbols/qgspoint3dsymbol_p.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/3d/symbols/qgspoint3dsymbol_p.cpp b/src/3d/symbols/qgspoint3dsymbol_p.cpp index 3f89790141f0..eac763c34e43 100644 --- a/src/3d/symbols/qgspoint3dsymbol_p.cpp +++ b/src/3d/symbols/qgspoint3dsymbol_p.cpp @@ -108,10 +108,14 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler } }; + //!< Create a material from a point symbol and context. This is call by makeEntity(). static Qt3DRender::QMaterial *material( const QgsPoint3DSymbol *symbol, const QgsMaterialContext &materialContext ); + //!< Create a geometry renderer from a point symbol, position and shape. This is call by makeEntity(). static Qt3DRender::QGeometryRenderer *renderer( const QgsPoint3DSymbol *symbol, const PointData &pointData ); + //!< Create a geometry from a point symbol and shape. This is call by renderer(). static Qt3DQGeometry *symbolGeometry( const QgsPoint3DSymbol *symbol, const PointData &pointData ); + //!< Create one entity per PointData. This is called by finalize(). void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QVector &out, bool selected ); // input specific for this class