QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgspoint3dsymbol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspoint3dsymbol.cpp
3  --------------------------------------
4  Date : July 2017
5  Copyright : (C) 2017 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgspoint3dsymbol.h"
17 
18 #include "qgs3dutils.h"
19 #include "qgsreadwritecontext.h"
20 #include "qgsxmlutils.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgs3d.h"
23 #include "qgsmaterialregistry.h"
24 #include "qgs3dexportobject.h"
25 #include "qgs3dsceneexporter.h"
26 
28 {
29  return new QgsPoint3DSymbol( *this );
30 }
31 
33 {
34  return new QgsPoint3DSymbol();
35 }
36 
38  : mMaterial( qgis::make_unique< QgsPhongMaterialSettings >() )
39 {
41 }
42 
44  : mAltClamping( other.altitudeClamping() )
45  , mMaterial( other.material() ? other.material()->clone() : nullptr )
46  , mShape( other.shape() )
47  , mShapeProperties( other.shapeProperties() )
48  , mTransform( other.transform() )
49  , mBillboardSymbol( other.billboardSymbol() ? other.billboardSymbol()->clone() : nullptr )
50 {
51  setDataDefinedProperties( other.dataDefinedProperties() );
52 }
53 
54 void QgsPoint3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
55 {
56  QDomDocument doc = elem.ownerDocument();
57 
58  QDomElement elemDataProperties = doc.createElement( QStringLiteral( "data" ) );
59  elemDataProperties.setAttribute( QStringLiteral( "alt-clamping" ), Qgs3DUtils::altClampingToString( mAltClamping ) );
60  elem.appendChild( elemDataProperties );
61 
62  elem.setAttribute( QStringLiteral( "material_type" ), mMaterial->type() );
63  QDomElement elemMaterial = doc.createElement( QStringLiteral( "material" ) );
64  mMaterial->writeXml( elemMaterial, context );
65  elem.appendChild( elemMaterial );
66 
67  elem.setAttribute( QStringLiteral( "shape" ), shapeToString( mShape ) );
68 
69  QVariantMap shapePropertiesCopy( mShapeProperties );
70  shapePropertiesCopy[QStringLiteral( "model" )] = QVariant( context.pathResolver().writePath( shapePropertiesCopy[QStringLiteral( "model" )].toString() ) );
71 
72  QDomElement elemShapeProperties = doc.createElement( QStringLiteral( "shape-properties" ) );
73  elemShapeProperties.appendChild( QgsXmlUtils::writeVariant( shapePropertiesCopy, doc ) );
74  elem.appendChild( elemShapeProperties );
75 
76  QDomElement elemTransform = doc.createElement( QStringLiteral( "transform" ) );
77  elemTransform.setAttribute( QStringLiteral( "matrix" ), Qgs3DUtils::matrix4x4toString( mTransform ) );
78  elem.appendChild( elemTransform );
79 
80  if ( billboardSymbol() )
81  {
82  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "symbol" ), billboardSymbol(), doc, context );
83 
84  elem.appendChild( symbolElem );
85  }
86 }
87 
88 void QgsPoint3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
89 {
90  QDomElement elemDataProperties = elem.firstChildElement( QStringLiteral( "data" ) );
91  mAltClamping = Qgs3DUtils::altClampingFromString( elemDataProperties.attribute( QStringLiteral( "alt-clamping" ) ) );
92 
93  QDomElement elemMaterial = elem.firstChildElement( QStringLiteral( "material" ) );
94  const QString materialType = elem.attribute( QStringLiteral( "material_type" ), QStringLiteral( "phong" ) );
95  mMaterial.reset( Qgs3D::materialRegistry()->createMaterialSettings( materialType ) );
96  if ( !mMaterial )
97  mMaterial.reset( Qgs3D::materialRegistry()->createMaterialSettings( QStringLiteral( "phong" ) ) );
98  mMaterial->readXml( elemMaterial, context );
99 
100  mShape = shapeFromString( elem.attribute( QStringLiteral( "shape" ) ) );
101 
102  QDomElement elemShapeProperties = elem.firstChildElement( QStringLiteral( "shape-properties" ) );
103  mShapeProperties = QgsXmlUtils::readVariant( elemShapeProperties.firstChildElement() ).toMap();
104  mShapeProperties[QStringLiteral( "model" )] = QVariant( context.pathResolver().readPath( mShapeProperties[QStringLiteral( "model" )].toString() ) );
105 
106  QDomElement elemTransform = elem.firstChildElement( QStringLiteral( "transform" ) );
107  mTransform = Qgs3DUtils::stringToMatrix4x4( elemTransform.attribute( QStringLiteral( "matrix" ) ) );
108 
109  QDomElement symbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
110 
111  setBillboardSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElem, context ) );
112 }
113 
114 QList<QgsWkbTypes::GeometryType> QgsPoint3DSymbol::compatibleGeometryTypes() const
115 {
116  return QList< QgsWkbTypes::GeometryType >() << QgsWkbTypes::PointGeometry;
117 }
118 
120 {
121  if ( shape == QStringLiteral( "sphere" ) )
122  return Sphere;
123  else if ( shape == QLatin1String( "cone" ) )
124  return Cone;
125  else if ( shape == QLatin1String( "cube" ) )
126  return Cube;
127  else if ( shape == QLatin1String( "torus" ) )
128  return Torus;
129  else if ( shape == QLatin1String( "plane" ) )
130  return Plane;
131  else if ( shape == QLatin1String( "extruded-text" ) )
132  return ExtrudedText;
133  else if ( shape == QLatin1String( "model" ) )
134  return Model;
135  else if ( shape == QLatin1String( "billboard" ) )
136  return Billboard;
137  else // "cylinder" (default)
138  return Cylinder;
139 }
140 
142 {
143  switch ( shape )
144  {
145  case Cylinder: return QStringLiteral( "cylinder" );
146  case Sphere: return QStringLiteral( "sphere" );
147  case Cone: return QStringLiteral( "cone" );
148  case Cube: return QStringLiteral( "cube" );
149  case Torus: return QStringLiteral( "torus" );
150  case Plane: return QStringLiteral( "plane" );
151  case ExtrudedText: return QStringLiteral( "extruded-text" );
152  case Model: return QStringLiteral( "model" );
153  case Billboard: return QStringLiteral( "billboard" );
154  default: Q_ASSERT( false ); return QString();
155  }
156 }
157 
159 {
160  QMatrix4x4 billboardTransformMatrix;
161  billboardTransformMatrix.translate( QVector3D( 0, mTransform.data()[13], 0 ) );
162 
163  return billboardTransformMatrix;
164 }
165 
167 {
168  return mMaterial.get();
169 }
170 
172 {
173  if ( material == mMaterial.get() )
174  return;
175 
176  mMaterial.reset( material );
177 }
178 
179 bool QgsPoint3DSymbol::exportGeometries( Qgs3DSceneExporter *exporter, Qt3DCore::QEntity *entity, const QString &objectNamePrefix ) const
180 {
181  if ( shape() == QgsPoint3DSymbol::Model )
182  {
183  Qt3DRender::QSceneLoader *sceneLoader = entity->findChild<Qt3DRender::QSceneLoader *>();
184  if ( sceneLoader != nullptr )
185  {
186  QVector<Qgs3DExportObject *> objects = exporter->processSceneLoaderGeometries( sceneLoader, objectNamePrefix );
187  for ( Qgs3DExportObject *obj : objects )
188  {
189  obj->setSmoothEdges( exporter->smoothEdges() );
190  obj->setupMaterial( material() );
191  }
192  exporter->mObjects << objects;
193  }
194  else
195  {
196  QList<Qt3DRender::QMesh *> meshes = entity->findChildren<Qt3DRender::QMesh *>();
197  for ( Qt3DRender::QMesh *mesh : meshes )
198  {
199  Qgs3DExportObject *object = exporter->processGeometryRenderer( mesh, objectNamePrefix );
200  if ( object == nullptr ) continue;
201  object->setSmoothEdges( exporter->smoothEdges() );
202  object->setupMaterial( material() );
203  exporter->mObjects << object;
204  }
205  }
206  return true;
207  }
208  else if ( shape() == QgsPoint3DSymbol::Billboard )
209  {
210  Qgs3DExportObject *obj = exporter->processPoints( entity, objectNamePrefix );
211  if ( obj != nullptr ) exporter->mObjects << obj;
212  if ( obj != nullptr ) return true;
213  }
214  else
215  {
216  QVector<Qgs3DExportObject *> objects = exporter->processInstancedPointGeometry( entity, objectNamePrefix );
217  for ( Qgs3DExportObject *obj : objects )
218  {
219  obj->setupMaterial( material() );
220  exporter->mObjects << obj;
221  }
222  return true;
223  }
224  return false;
225 }
Manages the data of each object of the scene (positions, normals, texture coordinates ....
void setSmoothEdges(bool smoothEdges)
Sets whether triangles edges will look smooth.
Entity that handles the exporting of 3D scene.
bool smoothEdges() const
Returns whether the triangles will look smooth.
static QString altClampingToString(Qgs3DTypes::AltitudeClamping altClamp)
Converts a value from AltitudeClamping enum to a string.
Definition: qgs3dutils.cpp:180
static QString matrix4x4toString(const QMatrix4x4 &m)
Converts a 4x4 transform matrix to a string.
Definition: qgs3dutils.cpp:322
static Qgs3DTypes::AltitudeClamping altClampingFromString(const QString &str)
Converts a string to a value from AltitudeClamping enum.
Definition: qgs3dutils.cpp:192
static QMatrix4x4 stringToMatrix4x4(const QString &str)
Convert a string to a 4x4 transform matrix.
Definition: qgs3dutils.cpp:332
static QgsMaterialRegistry * materialRegistry()
Returns the material registry, used for managing 3D materials.
Definition: qgs3d.cpp:90
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:1004
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Shape
3D shape types supported by the symbol
@ ExtrudedText
Supported in Qt 5.9+.
QgsAbstractMaterialSettings * material() const
Returns material used for shading of the symbol.
QMatrix4x4 billboardTransform() const
Returns transform for billboards.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
QgsPoint3DSymbol()
Constructor for QgsPoint3DSymbol with default QgsMarkerSymbol as the billboardSymbol.
bool exportGeometries(Qgs3DSceneExporter *exporter, Qt3DCore::QEntity *entity, const QString &objectNamePrefix) const override SIP_SKIP
Exports the geometries contained within the hierarchy of entity.
void setMaterial(QgsAbstractMaterialSettings *material SIP_TRANSFER)
Sets the material settings used for shading of the symbol.
QgsAbstract3DSymbol * clone() const override SIP_FACTORY
Shape shape() const
Returns 3D shape for points.
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
void setBillboardSymbol(QgsMarkerSymbol *symbol)
Set symbol for billboard and the ownership is transferred.
static QString shapeToString(Shape shape)
Returns string from a shape enum value.
static QgsAbstract3DSymbol * create() SIP_FACTORY
Creates a new QgsPoint3DSymbol.
static Shape shapeFromString(const QString &shape)
Returns shape enum value from a string.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const override
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:346
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.