QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 #include "qgsmarkersymbol.h"
27 
29 {
30  return new QgsPoint3DSymbol( *this );
31 }
32 
34 {
35  return new QgsPoint3DSymbol();
36 }
37 
39  : mMaterial( std::make_unique< QgsPhongMaterialSettings >() )
40 {
42 }
43 
45  : mAltClamping( other.altitudeClamping() )
46  , mMaterial( other.material() ? other.material()->clone() : nullptr )
47  , mShape( other.shape() )
48  , mShapeProperties( other.shapeProperties() )
49  , mTransform( other.transform() )
50  , mBillboardSymbol( other.billboardSymbol() ? other.billboardSymbol()->clone() : nullptr )
51 {
52  setDataDefinedProperties( other.dataDefinedProperties() );
53 }
54 
56 
57 void QgsPoint3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
58 {
59  QDomDocument doc = elem.ownerDocument();
60 
61  QDomElement elemDataProperties = doc.createElement( QStringLiteral( "data" ) );
62  elemDataProperties.setAttribute( QStringLiteral( "alt-clamping" ), Qgs3DUtils::altClampingToString( mAltClamping ) );
63  elem.appendChild( elemDataProperties );
64 
65  elem.setAttribute( QStringLiteral( "material_type" ), mMaterial->type() );
66  QDomElement elemMaterial = doc.createElement( QStringLiteral( "material" ) );
67  mMaterial->writeXml( elemMaterial, context );
68  elem.appendChild( elemMaterial );
69 
70  elem.setAttribute( QStringLiteral( "shape" ), shapeToString( mShape ) );
71 
72  QVariantMap shapePropertiesCopy( mShapeProperties );
73  shapePropertiesCopy[QStringLiteral( "model" )] = QVariant( context.pathResolver().writePath( shapePropertiesCopy[QStringLiteral( "model" )].toString() ) );
74 
75  QDomElement elemShapeProperties = doc.createElement( QStringLiteral( "shape-properties" ) );
76  elemShapeProperties.appendChild( QgsXmlUtils::writeVariant( shapePropertiesCopy, doc ) );
77  elem.appendChild( elemShapeProperties );
78 
79  QDomElement elemTransform = doc.createElement( QStringLiteral( "transform" ) );
80  elemTransform.setAttribute( QStringLiteral( "matrix" ), Qgs3DUtils::matrix4x4toString( mTransform ) );
81  elem.appendChild( elemTransform );
82 
83  if ( billboardSymbol() )
84  {
85  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "symbol" ), billboardSymbol(), doc, context );
86 
87  elem.appendChild( symbolElem );
88  }
89 }
90 
91 void QgsPoint3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
92 {
93  QDomElement elemDataProperties = elem.firstChildElement( QStringLiteral( "data" ) );
94  mAltClamping = Qgs3DUtils::altClampingFromString( elemDataProperties.attribute( QStringLiteral( "alt-clamping" ) ) );
95 
96  QDomElement elemMaterial = elem.firstChildElement( QStringLiteral( "material" ) );
97  const QString materialType = elem.attribute( QStringLiteral( "material_type" ), QStringLiteral( "phong" ) );
98  mMaterial.reset( Qgs3D::materialRegistry()->createMaterialSettings( materialType ) );
99  if ( !mMaterial )
100  mMaterial.reset( Qgs3D::materialRegistry()->createMaterialSettings( QStringLiteral( "phong" ) ) );
101  mMaterial->readXml( elemMaterial, context );
102 
103  mShape = shapeFromString( elem.attribute( QStringLiteral( "shape" ) ) );
104 
105  QDomElement elemShapeProperties = elem.firstChildElement( QStringLiteral( "shape-properties" ) );
106  mShapeProperties = QgsXmlUtils::readVariant( elemShapeProperties.firstChildElement() ).toMap();
107  mShapeProperties[QStringLiteral( "model" )] = QVariant( context.pathResolver().readPath( mShapeProperties[QStringLiteral( "model" )].toString() ) );
108 
109  QDomElement elemTransform = elem.firstChildElement( QStringLiteral( "transform" ) );
110  mTransform = Qgs3DUtils::stringToMatrix4x4( elemTransform.attribute( QStringLiteral( "matrix" ) ) );
111 
112  QDomElement symbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
113 
114  setBillboardSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElem, context ) );
115 }
116 
117 QList<QgsWkbTypes::GeometryType> QgsPoint3DSymbol::compatibleGeometryTypes() const
118 {
119  return QList< QgsWkbTypes::GeometryType >() << QgsWkbTypes::PointGeometry;
120 }
121 
123 {
124  if ( shape == QStringLiteral( "sphere" ) )
125  return Sphere;
126  else if ( shape == QLatin1String( "cone" ) )
127  return Cone;
128  else if ( shape == QLatin1String( "cube" ) )
129  return Cube;
130  else if ( shape == QLatin1String( "torus" ) )
131  return Torus;
132  else if ( shape == QLatin1String( "plane" ) )
133  return Plane;
134  else if ( shape == QLatin1String( "extruded-text" ) )
135  return ExtrudedText;
136  else if ( shape == QLatin1String( "model" ) )
137  return Model;
138  else if ( shape == QLatin1String( "billboard" ) )
139  return Billboard;
140  else // "cylinder" (default)
141  return Cylinder;
142 }
143 
145 {
146  switch ( shape )
147  {
148  case Cylinder: return QStringLiteral( "cylinder" );
149  case Sphere: return QStringLiteral( "sphere" );
150  case Cone: return QStringLiteral( "cone" );
151  case Cube: return QStringLiteral( "cube" );
152  case Torus: return QStringLiteral( "torus" );
153  case Plane: return QStringLiteral( "plane" );
154  case ExtrudedText: return QStringLiteral( "extruded-text" );
155  case Model: return QStringLiteral( "model" );
156  case Billboard: return QStringLiteral( "billboard" );
157  default: Q_ASSERT( false ); return QString();
158  }
159 }
160 
162 {
163  QMatrix4x4 billboardTransformMatrix;
164  billboardTransformMatrix.translate( QVector3D( 0, mTransform.data()[13], 0 ) );
165 
166  return billboardTransformMatrix;
167 }
168 
170 {
171  return mMaterial.get();
172 }
173 
175 {
176  if ( material == mMaterial.get() )
177  return;
178 
179  mMaterial.reset( material );
180 }
181 
182 bool QgsPoint3DSymbol::exportGeometries( Qgs3DSceneExporter *exporter, Qt3DCore::QEntity *entity, const QString &objectNamePrefix ) const
183 {
184  if ( shape() == QgsPoint3DSymbol::Model )
185  {
186  Qt3DRender::QSceneLoader *sceneLoader = entity->findChild<Qt3DRender::QSceneLoader *>();
187  if ( sceneLoader != nullptr )
188  {
189  QVector<Qgs3DExportObject *> objects = exporter->processSceneLoaderGeometries( sceneLoader, objectNamePrefix );
190  for ( Qgs3DExportObject *obj : objects )
191  {
192  obj->setSmoothEdges( exporter->smoothEdges() );
193  obj->setupMaterial( material() );
194  }
195  exporter->mObjects << objects;
196  }
197  else
198  {
199  QList<Qt3DRender::QMesh *> meshes = entity->findChildren<Qt3DRender::QMesh *>();
200  for ( Qt3DRender::QMesh *mesh : meshes )
201  {
202  Qgs3DExportObject *object = exporter->processGeometryRenderer( mesh, objectNamePrefix );
203  if ( object == nullptr ) continue;
204  object->setSmoothEdges( exporter->smoothEdges() );
205  object->setupMaterial( material() );
206  exporter->mObjects << object;
207  }
208  }
209  return true;
210  }
211  else if ( shape() == QgsPoint3DSymbol::Billboard )
212  {
213  Qgs3DExportObject *obj = exporter->processPoints( entity, objectNamePrefix );
214  if ( obj != nullptr ) exporter->mObjects << obj;
215  if ( obj != nullptr ) return true;
216  }
217  else
218  {
219  QVector<Qgs3DExportObject *> objects = exporter->processInstancedPointGeometry( entity, objectNamePrefix );
220  for ( Qgs3DExportObject *obj : objects )
221  {
222  obj->setupMaterial( material() );
223  exporter->mObjects << obj;
224  }
225  return true;
226  }
227  return false;
228 }
229 
231 {
232  return mBillboardSymbol.get();
233 }
234 
236 {
237  mBillboardSymbol.reset( symbol );
238 }
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:187
static QString matrix4x4toString(const QMatrix4x4 &m)
Converts a 4x4 transform matrix to a string.
Definition: qgs3dutils.cpp:329
static Qgs3DTypes::AltitudeClamping altClampingFromString(const QString &str)
Converts a string to a value from AltitudeClamping enum.
Definition: qgs3dutils.cpp:199
static QMatrix4x4 stringToMatrix4x4(const QString &str)
Convert a string to a 4x4 transform matrix.
Definition: qgs3dutils.cpp:339
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.
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+.
~QgsPoint3DSymbol() override
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.
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
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.
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:355
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.