Read/write 3D renderers of map layers to project files

This commit is contained in:
Martin Dobias 2017-07-29 12:16:07 +02:00
parent 04b00aad6e
commit 6df6681326
15 changed files with 131 additions and 38 deletions

View File

@ -453,6 +453,12 @@ Invoked by QgsProject.read().
:rtype: bool
%End
virtual void resolveReferences( QgsProject *project );
%Docstring
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
.. versionadded:: 3.0
%End
QStringList customPropertyKeys() const;
%Docstring
Returns list of all keys within custom properties. Properties are stored in a map and saved in project file.
@ -1091,7 +1097,6 @@ Set whether layer is valid or not - should be used in constructor.
:rtype: bool
%End
void readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith = QString() );
%Docstring
Read custom properties from project file.

View File

@ -711,7 +711,7 @@ Return the provider type for this layer
:rtype: bool
%End
void resolveReferences( QgsProject *project );
virtual void resolveReferences( QgsProject *project );
%Docstring
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
.. versionadded:: 3.0

View File

@ -16,8 +16,10 @@ Abstract3DSymbol *Polygon3DSymbol::clone() const
return new Polygon3DSymbol( *this );
}
void Polygon3DSymbol::writeXml( QDomElement &elem ) const
void Polygon3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
Q_UNUSED( context );
QDomDocument doc = elem.ownerDocument();
QDomElement elemDataProperties = doc.createElement( "data" );
@ -32,8 +34,10 @@ void Polygon3DSymbol::writeXml( QDomElement &elem ) const
elem.appendChild( elemMaterial );
}
void Polygon3DSymbol::readXml( const QDomElement &elem )
void Polygon3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context );
QDomElement elemDataProperties = elem.firstChildElement( "data" );
altClamping = Utils::altClampingFromString( elemDataProperties.attribute( "alt-clamping" ) );
altBinding = Utils::altBindingFromString( elemDataProperties.attribute( "alt-binding" ) );
@ -56,8 +60,10 @@ Abstract3DSymbol *Point3DSymbol::clone() const
return new Point3DSymbol( *this );
}
void Point3DSymbol::writeXml( QDomElement &elem ) const
void Point3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
Q_UNUSED( context );
QDomDocument doc = elem.ownerDocument();
QDomElement elemMaterial = doc.createElement( "material" );
@ -73,8 +79,10 @@ void Point3DSymbol::writeXml( QDomElement &elem ) const
elem.appendChild( elemTransform );
}
void Point3DSymbol::readXml( const QDomElement &elem )
void Point3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context );
QDomElement elemMaterial = elem.firstChildElement( "material" );
material.readXml( elemMaterial );
@ -103,8 +111,10 @@ Abstract3DSymbol *Line3DSymbol::clone() const
return new Line3DSymbol( *this );
}
void Line3DSymbol::writeXml( QDomElement &elem ) const
void Line3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
Q_UNUSED( context );
QDomDocument doc = elem.ownerDocument();
QDomElement elemDataProperties = doc.createElement( "data" );
@ -120,8 +130,10 @@ void Line3DSymbol::writeXml( QDomElement &elem ) const
elem.appendChild( elemMaterial );
}
void Line3DSymbol::readXml( const QDomElement &elem )
void Line3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context );
QDomElement elemDataProperties = elem.firstChildElement( "data" );
altClamping = Utils::altClampingFromString( elemDataProperties.attribute( "alt-clamping" ) );
altBinding = Utils::altBindingFromString( elemDataProperties.attribute( "alt-binding" ) );

View File

@ -16,8 +16,8 @@ class _3D_EXPORT Abstract3DSymbol
virtual QString type() const = 0;
virtual Abstract3DSymbol *clone() const = 0;
virtual void writeXml( QDomElement &elem ) const = 0;
virtual void readXml( const QDomElement &elem ) = 0;
virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const = 0;
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) = 0;
};
@ -30,8 +30,8 @@ class _3D_EXPORT Polygon3DSymbol : public Abstract3DSymbol
QString type() const override { return "polygon"; }
Abstract3DSymbol *clone() const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
AltitudeClamping altClamping; //! how to handle altitude of vector features
AltitudeBinding altBinding; //! how to handle clamping of vertices of individual features
@ -51,8 +51,8 @@ class _3D_EXPORT Point3DSymbol : public Abstract3DSymbol
QString type() const override { return "point"; }
Abstract3DSymbol *clone() const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
PhongMaterialSettings material; //!< Defines appearance of objects
QVariantMap shapeProperties; //!< What kind of shape to use and what
@ -69,8 +69,8 @@ class _3D_EXPORT Line3DSymbol : public Abstract3DSymbol
QString type() const override { return "line"; }
Abstract3DSymbol *clone() const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
AltitudeClamping altClamping; //! how to handle altitude of vector features
AltitudeBinding altBinding; //! how to handle clamping of vertices of individual features

View File

@ -57,8 +57,6 @@ Map3D::~Map3D()
void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context );
QDomElement elemOrigin = elem.firstChildElement( "origin" );
originX = elemOrigin.attribute( "x" ).toDouble();
originY = elemOrigin.attribute( "y" ).toDouble();
@ -117,7 +115,7 @@ void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context
if ( renderer )
{
renderer->readXml( elemRenderer );
renderer->readXml( elemRenderer, context );
renderers.append( renderer );
}
elemRenderer = elemRenderer.nextSiblingElement( "renderer" );
@ -135,7 +133,6 @@ void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context
QDomElement Map3D::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
{
Q_UNUSED( context );
QDomElement elem = doc.createElement( "qgis3d" );
QDomElement elemOrigin = doc.createElement( "origin" );
@ -171,7 +168,7 @@ QDomElement Map3D::writeXml( QDomDocument &doc, const QgsReadWriteContext &conte
{
QDomElement elemRenderer = doc.createElement( "renderer" );
elemRenderer.setAttribute( "type", renderer->type() );
renderer->writeXml( elemRenderer );
renderer->writeXml( elemRenderer, context );
elemRenderers.appendChild( elemRenderer );
}
elem.appendChild( elemRenderers );

View File

@ -9,6 +9,22 @@
#include "qgsxmlutils.h"
VectorLayer3DRendererMetadata::VectorLayer3DRendererMetadata()
: Qgs3DRendererAbstractMetadata( "vector" )
{
}
QgsAbstract3DRenderer *VectorLayer3DRendererMetadata::createRenderer( QDomElement &elem, const QgsReadWriteContext &context )
{
VectorLayer3DRenderer *r = new VectorLayer3DRenderer;
r->readXml( elem, context );
return r;
}
// ---------
VectorLayer3DRenderer::VectorLayer3DRenderer( Abstract3DSymbol *s )
: mSymbol( s )
{
@ -62,7 +78,7 @@ Qt3DCore::QEntity *VectorLayer3DRenderer::createEntity( const Map3D &map ) const
return nullptr;
}
void VectorLayer3DRenderer::writeXml( QDomElement &elem ) const
void VectorLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
QDomDocument doc = elem.ownerDocument();
@ -72,12 +88,12 @@ void VectorLayer3DRenderer::writeXml( QDomElement &elem ) const
if ( mSymbol )
{
elemSymbol.setAttribute( "type", mSymbol->type() );
mSymbol->writeXml( elemSymbol );
mSymbol->writeXml( elemSymbol, context );
}
elem.appendChild( elemSymbol );
}
void VectorLayer3DRenderer::readXml( const QDomElement &elem )
void VectorLayer3DRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
layerRef = QgsMapLayerRef( elem.attribute( "layer" ) );
@ -92,7 +108,7 @@ void VectorLayer3DRenderer::readXml( const QDomElement &elem )
symbol = new Line3DSymbol;
if ( symbol )
symbol->readXml( elemSymbol );
symbol->readXml( elemSymbol, context );
mSymbol.reset( symbol );
}

View File

@ -3,6 +3,7 @@
#include "qgis_3d.h"
#include "qgs3drendererregistry.h"
#include "qgsabstract3drenderer.h"
#include "phongmaterialsettings.h"
@ -16,6 +17,17 @@ class QgsVectorLayer;
class Abstract3DSymbol;
//! Metadata for vector layer 3D renderer to allow creation of its instances from XML
class _3D_EXPORT VectorLayer3DRendererMetadata : public Qgs3DRendererAbstractMetadata
{
public:
VectorLayer3DRendererMetadata();
virtual QgsAbstract3DRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) override;
};
/** 3D renderer that renders all features of a vector layer with the same 3D symbol.
* The appearance is completely defined by the symbol.
*/
@ -37,8 +49,8 @@ class _3D_EXPORT VectorLayer3DRenderer : public QgsAbstract3DRenderer
VectorLayer3DRenderer *clone() const override;
Qt3DCore::QEntity *createEntity( const Map3D &map ) const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
void resolveReferences( const QgsProject &project ) override;
private:

View File

@ -80,6 +80,15 @@
#include "qgsziputils.h"
#include "qgsbrowsermodel.h"
#ifdef HAVE_3D
#include "qgsabstract3drenderer.h"
#include "qgs3dmapcanvasdockwidget.h"
#include "qgs3drendererregistry.h"
#include "map3d.h"
#include "flatterraingenerator.h"
#include "vectorlayer3drenderer.h"
#endif
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QAuthenticator>
@ -800,6 +809,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
functionProfile( &QgisApp::updateRecentProjectPaths, this, QStringLiteral( "Update recent project paths" ) );
functionProfile( &QgisApp::updateProjectFromTemplates, this, QStringLiteral( "Update project from templates" ) );
functionProfile( &QgisApp::legendLayerSelectionChanged, this, QStringLiteral( "Legend layer selection changed" ) );
functionProfile( &QgisApp::init3D, this, QStringLiteral( "Initialize 3D support" ) );
QgsApplication::annotationRegistry()->addAnnotationType( QgsAnnotationMetadata( QStringLiteral( "FormAnnotationItem" ), &QgsFormAnnotation::create ) );
connect( QgsProject::instance()->annotationManager(), &QgsAnnotationManager::annotationAdded, this, &QgisApp::annotationCreated );
@ -9879,13 +9889,19 @@ void QgisApp::newMapCanvas()
}
}
#include "qgsabstract3drenderer.h"
#include "qgs3dmapcanvasdockwidget.h"
#include "map3d.h"
#include "flatterraingenerator.h"
void QgisApp::init3D()
{
#ifdef HAVE_3D
// register 3D renderers
QgsApplication::instance()->renderer3DRegistry()->addRenderer( new VectorLayer3DRendererMetadata );
#else
mActionNew3DMapCanvas->setVisible( false );
#endif
}
void QgisApp::new3DMapCanvas()
{
#ifdef HAVE_3D
// initialize from project
QgsProject *prj = QgsProject::instance();
QgsRectangle fullExtent = mMapCanvas->fullExtent();
@ -9910,6 +9926,7 @@ void QgisApp::new3DMapCanvas()
map3DWidget->setMap( map );
map3DWidget->setMainCanvas( mMapCanvas );
addDockWidget( Qt::BottomDockWidgetArea, map3DWidget );
#endif
}
void QgisApp::setExtent( const QgsRectangle &rect )

View File

@ -1700,6 +1700,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void createCanvasTools();
void createMapTips();
void createDecorations();
void init3D();
/**
* Refresh the user profile menu.

View File

@ -7,6 +7,7 @@
class QDomElement;
class QgsProject;
class QgsReadWriteContext;
class Map3D;
namespace Qt3DCore
@ -25,8 +26,8 @@ class CORE_EXPORT QgsAbstract3DRenderer //: public QObject
virtual QgsAbstract3DRenderer *clone() const = 0;
virtual Qt3DCore::QEntity *createEntity( const Map3D &map ) const = 0;
virtual void writeXml( QDomElement &elem ) const = 0;
virtual void readXml( const QDomElement &elem ) = 0;
virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const = 0;
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) = 0;
virtual void resolveReferences( const QgsProject &project );
};

View File

@ -28,6 +28,7 @@
#include <sqlite3.h>
#include "qgs3drendererregistry.h"
#include "qgsabstract3drenderer.h"
#include "qgsapplication.h"
#include "qgscoordinatereferencesystem.h"
@ -550,6 +551,19 @@ bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, const QgsReadWr
QDomElement metadataElem = layerElement.firstChildElement( QStringLiteral( "resourceMetadata" ) );
mMetadata.readMetadataXml( metadataElem );
QgsAbstract3DRenderer *r3D = nullptr;
QDomElement renderer3DElem = layerElement.firstChildElement( QStringLiteral( "renderer-3d" ) );
if ( !renderer3DElem.isNull() )
{
QString type3D = renderer3DElem.attribute( QStringLiteral( "type" ) );
Qgs3DRendererAbstractMetadata *meta3D = QgsApplication::renderer3DRegistry()->rendererMetadata( type3D );
if ( meta3D )
{
r3D = meta3D->createRenderer( renderer3DElem, context );
}
}
setRenderer3D( r3D );
return true;
} // bool QgsMapLayer::readLayerXML
@ -819,6 +833,14 @@ bool QgsMapLayer::writeLayerXml( QDomElement &layerElement, QDomDocument &docume
mMetadata.writeMetadataXml( myMetadataElem, document );
layerElement.appendChild( myMetadataElem );
if ( m3DRenderer )
{
QDomElement renderer3DElem = document.createElement( QStringLiteral( "renderer-3d" ) );
renderer3DElem.setAttribute( QStringLiteral( "type" ), m3DRenderer->type() );
m3DRenderer->writeXml( renderer3DElem, context );
layerElement.appendChild( renderer3DElem );
}
// now append layer node to map layer node
writeCustomProperties( layerElement, document );
@ -838,6 +860,12 @@ bool QgsMapLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const
return true;
} // void QgsMapLayer::writeXml
void QgsMapLayer::resolveReferences( QgsProject *project )
{
if ( m3DRenderer )
m3DRenderer->resolveReferences( *project );
}
void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
{

View File

@ -431,6 +431,11 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
bool writeLayerXml( QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context ) const;
/** Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
* \since QGIS 3.0
*/
virtual void resolveReferences( QgsProject *project );
/** Returns list of all keys within custom properties. Properties are stored in a map and saved in project file.
* \see customProperty()
* \since QGIS 3.0
@ -976,7 +981,6 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
virtual bool writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const;
/** Read custom properties from project file.
\param layerNode note to read from
\param keyStartsWith reads only properties starting with the specified string (or all if the string is empty)*/

View File

@ -942,13 +942,12 @@ bool QgsProject::readProjectFile( const QString &filename )
mBadLayerHandler->handleBadLayers( brokenNodes );
}
// Resolve references to other vector layers
// Resolve references to other layers
// Needs to be done here once all dependent layers are loaded
QMap<QString, QgsMapLayer *> layers = mLayerStore->mapLayers();
for ( QMap<QString, QgsMapLayer *>::iterator it = layers.begin(); it != layers.end(); it++ )
{
if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() ) )
vl->resolveReferences( this );
it.value()->resolveReferences( this );
}
mLayerTreeRegistryBridge->setEnabled( true );

View File

@ -1654,6 +1654,7 @@ bool QgsVectorLayer::writeXml( QDomNode &layer_node,
void QgsVectorLayer::resolveReferences( QgsProject *project )
{
QgsMapLayer::resolveReferences( project );
mJoinBuffer->resolveReferences( project );
}

View File

@ -709,7 +709,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
/** Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
* \since QGIS 3.0
*/
void resolveReferences( QgsProject *project );
virtual void resolveReferences( QgsProject *project ) override;
/**
* Save named and sld style of the layer to the style table in the db.