QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
qgspolygon3dsymbol_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspolygon3dsymbol_p.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
17
18#include "qgs3d.h"
19#include "qgs3drendercontext.h"
20#include "qgs3dutils.h"
22#include "qgsgeotransform.h"
23#include "qgslinematerial_p.h"
24#include "qgslinestring.h"
25#include "qgslinevertexdata_p.h"
27#include "qgsmessagelog.h"
28#include "qgsmultilinestring.h"
29#include "qgsmultipolygon.h"
31#include "qgspolygon.h"
32#include "qgspolygon3dsymbol.h"
35#include "qgstessellator.h"
36#include "qgsvectorlayer.h"
37
38#include <Qt3DExtras/QDiffuseMapMaterial>
39#include <Qt3DExtras/QPhongMaterial>
40#include <Qt3DRender/QAbstractTextureImage>
41#include <Qt3DRender/QCullFace>
42#include <Qt3DRender/QEffect>
43#include <Qt3DRender/QGeometryRenderer>
44#include <Qt3DRender/QTechnique>
45#include <Qt3DRender/QTexture>
46
48
49
50class QgsPolygon3DSymbolHandler : public QgsFeature3DHandler
51{
52 public:
53 QgsPolygon3DSymbolHandler( const QgsPolygon3DSymbol *symbol, const QgsFeatureIds &selectedIds )
54 : mSymbol( static_cast<QgsPolygon3DSymbol *>( symbol->clone() ) )
55 , mSelectedIds( selectedIds )
56 {}
57
58 bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsBox3D &chunkExtent ) override;
59 void processFeature( const QgsFeature &f, const Qgs3DRenderContext &context ) override;
60 void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
61
62 private:
64 struct PolygonData
65 {
66 std::unique_ptr<QgsTessellator> tessellator;
67 QVector<QgsFeatureId> triangleIndexFids;
68 QVector<uint> triangleIndexStartingIndices;
69 QByteArray materialDataDefined;
70 };
71
72 void processPolygon( const QgsPolygon *poly, QgsFeatureId fid, float offset, float extrusionHeight, const Qgs3DRenderContext &context, PolygonData &out );
73 void processMaterialDatadefined( uint verticesCount, const QgsExpressionContext &context, PolygonData &out );
74 void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PolygonData &out, bool selected );
75 QgsMaterial *material( const QgsPolygon3DSymbol *symbol, bool isSelected, const Qgs3DRenderContext &context ) const;
76
77 // input specific for this class
78 std::unique_ptr<QgsPolygon3DSymbol> mSymbol;
79 // inputs - generic
80 QgsFeatureIds mSelectedIds;
81 // outputs
82 PolygonData outNormal;
83 PolygonData outSelected;
84
85 QgsLineVertexData outEdges;
86
88 bool mWasClippedToExtent = false;
89};
90
91
92bool QgsPolygon3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsBox3D &chunkExtent )
93{
94 mChunkOrigin = chunkExtent.center();
95 mChunkOrigin.setZ( 0. ); // set the chunk origin to the bottom of the box, as the tessellator currently always considers origin z to be zero
96 mChunkExtent = chunkExtent;
97
98 outEdges.withAdjacency = true;
99 outEdges.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), 0, context, mChunkOrigin );
100
101 const bool requiresTextureCoordinates = mSymbol->materialSettings() && mSymbol->materialSettings()->requiresTextureCoordinates();
102 const bool requiresTangents = mSymbol->materialSettings() && mSymbol->materialSettings()->requiresTangents();
103
104 auto tessellator = std::make_unique<QgsTessellator>();
105 tessellator->setOrigin( mChunkOrigin );
106 tessellator->setAddNormals( true );
107 tessellator->setInvertNormals( mSymbol->invertNormals() );
108 tessellator->setBackFacesEnabled( mSymbol->addBackFaces() );
109 tessellator->setExtrusionFaces( mSymbol->extrusionFaces() );
110 tessellator->setAddTextureUVs( requiresTextureCoordinates );
111 tessellator->setAddTangents( requiresTangents );
112 tessellator->setTriangulationAlgorithm( Qgis::TriangulationAlgorithm::Earcut );
113
114 outNormal.tessellator = std::move( tessellator );
115
116 tessellator = std::make_unique<QgsTessellator>();
117 tessellator->setOrigin( mChunkOrigin );
118 tessellator->setAddNormals( true );
119 tessellator->setInvertNormals( mSymbol->invertNormals() );
120 tessellator->setBackFacesEnabled( mSymbol->addBackFaces() );
121 tessellator->setExtrusionFaces( mSymbol->extrusionFaces() );
122 tessellator->setAddTextureUVs( requiresTextureCoordinates );
123 tessellator->setAddTangents( requiresTangents );
124 tessellator->setTriangulationAlgorithm( Qgis::TriangulationAlgorithm::Earcut );
125
126 outSelected.tessellator = std::move( tessellator );
127
128 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.expressionContext() );
129 attributeNames.unite( attrs );
130 attrs = mSymbol->materialSettings()->dataDefinedProperties().referencedFields( context.expressionContext() );
131 attributeNames.unite( attrs );
132 return true;
133}
134
135void QgsPolygon3DSymbolHandler::processPolygon( const QgsPolygon *poly, QgsFeatureId fid, float offset, float extrusionHeight, const Qgs3DRenderContext &context, PolygonData &out )
136{
137 std::unique_ptr<QgsPolygon> polyClone( poly->clone() );
138
139 if ( mSymbol->edgesEnabled() )
140 {
141 // add edges before the polygon gets the Z values modified because addLineString() does its own altitude handling
142 const QgsAbstractGeometry *exteriorRing = static_cast<const QgsLineString *>( polyClone->exteriorRing() );
143
144 // This geometry will take ownership of the cleaned exteriorRing abstract geom.
145 // We need this to live for as long as exteriorRing is used.
146 QgsGeometry cleanedExteriorRingGeometry;
147
148 if ( mWasClippedToExtent )
149 {
150 // if the polygon was clipped to the chunk extent, then we need to remove any part of the exterior ring that
151 // overlaps the chunk extent line, otherwise the chunk extents will appear as edges. Any interior rings
152 // that were intersected by the extent will now be part of the exterior ring of the clipped geometry.
153 const QVector< QgsPointXY > extentPoints {
154 { mChunkExtent.xMinimum(), mChunkExtent.yMinimum() },
155 { mChunkExtent.xMaximum(), mChunkExtent.yMinimum() },
156 { mChunkExtent.xMaximum(), mChunkExtent.yMaximum() },
157 { mChunkExtent.xMinimum(), mChunkExtent.yMaximum() },
158 { mChunkExtent.xMinimum(), mChunkExtent.yMinimum() }
159 };
160 auto extentLinestring = std::make_unique<QgsLineString>( extentPoints );
161
162 const QgsGeometry exteriorRingGeometry( exteriorRing->clone() );
163 // it should be safe to perform the diff without any tolerance, the extent line string is a simple rectangle (chunk perimeter)
164 cleanedExteriorRingGeometry = exteriorRingGeometry.difference( QgsGeometry( extentLinestring.release() ) );
165 // make sure the diff didn't produce some degenerate geometry
166 ( void ) cleanedExteriorRingGeometry.convertGeometryCollectionToSubclass( Qgis::GeometryType::Line );
167 exteriorRing = cleanedExteriorRingGeometry.constGet()->simplifiedTypeRef();
168 }
169
170 if ( const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( exteriorRing ) )
171 {
172 outEdges.addLineString( *line, offset );
173 }
174 // if geometry was clipped to the chunk extents, we might now have a multilinestring
175 else if ( const QgsMultiLineString *mline = qgsgeometry_cast<const QgsMultiLineString *>( exteriorRing ) )
176 {
177 for ( int i = 0; i < mline->numGeometries(); ++i )
178 {
179 const QgsLineString *line = mline->lineStringN( i );
180 outEdges.addLineString( *line, offset );
181 }
182 }
183
184 // if geometry was clipped to the chunk extents and the chunk extents intersected an interior ring, then
185 // that ring is now part of the exterior ring. Hence we don't need to treat interior rings any differently
186 for ( int i = 0; i < polyClone->numInteriorRings(); ++i )
187 outEdges.addLineString( *static_cast<const QgsLineString *>( polyClone->interiorRing( i ) ), offset );
188
189 if ( extrusionHeight != 0.f )
190 {
191 // add roof and wall edges
192
193 if ( const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( exteriorRing ) )
194 {
195 outEdges.addLineString( *line, extrusionHeight + offset );
196 outEdges.addVerticalLines( *line, extrusionHeight, offset );
197 }
198 // if geometry was clipped to the chunk extents, we might now have a multilinestring
199 else if ( const QgsMultiLineString *mline = qgsgeometry_cast<const QgsMultiLineString *>( exteriorRing ) )
200 {
201 for ( int i = 0; i < mline->numGeometries(); ++i )
202 {
203 const QgsLineString *line = mline->lineStringN( i );
204 outEdges.addLineString( *line, extrusionHeight + offset );
205 outEdges.addVerticalLines( *line, extrusionHeight, offset );
206 }
207 }
208
209 // if geometry was clipped to the chunk extents and the chunk extents intersected an interior ring, then
210 // that ring is now part of the exterior ring. Hence we don't need to treat interior rings any differently
211 for ( int i = 0; i < polyClone->numInteriorRings(); ++i )
212 {
213 const QgsLineString *interior = static_cast<const QgsLineString *>( polyClone->interiorRing( i ) );
214 outEdges.addLineString( *interior, extrusionHeight + offset );
215 outEdges.addVerticalLines( *interior, extrusionHeight, offset );
216 }
217 }
218 }
219
220 Qgs3DUtils::clampAltitudes( polyClone.get(), mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), offset, context );
221
222 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
223 const uint startingTriangleIndex = static_cast<uint>( out.tessellator->dataVerticesCount() / 3 );
224 out.triangleIndexStartingIndices.append( startingTriangleIndex );
225 out.triangleIndexFids.append( fid );
226
227 const size_t oldVertexCount = out.tessellator->uniqueVertexCount();
228 out.tessellator->addPolygon( *polyClone, extrusionHeight );
229 if ( !out.tessellator->error().isEmpty() )
230 {
231 QgsMessageLog::logMessage( out.tessellator->error(), QObject::tr( "3D" ) );
232 }
233
234 if ( mSymbol->materialSettings()->dataDefinedProperties().hasActiveProperties() )
235 {
236 const uint newUniqueVertices = out.tessellator->uniqueVertexCount() - oldVertexCount;
237 processMaterialDatadefined( newUniqueVertices, context.expressionContext(), out );
238 }
239}
240
241void QgsPolygon3DSymbolHandler::processMaterialDatadefined( uint verticesCount, const QgsExpressionContext &context, QgsPolygon3DSymbolHandler::PolygonData &out )
242{
243 const QByteArray bytes = Qgs3D::materialDataDefinedVertexColorsAsByte( mSymbol->materialSettings(), context );
244 out.materialDataDefined.append( bytes.repeated( verticesCount ) );
245}
246
247void QgsPolygon3DSymbolHandler::processFeature( const QgsFeature &f, const Qgs3DRenderContext &context )
248{
249 if ( f.geometry().isNull() )
250 return;
251
252 PolygonData &out = mSelectedIds.contains( f.id() ) ? outSelected : outNormal;
253
254 QgsGeometry geom = f.geometry();
255 mWasClippedToExtent = clipGeometryIfTooLarge( geom );
256
257 if ( geom.isEmpty() )
258 return;
259
261
262 // segmentize curved geometries if necessary
264 {
265 geom = QgsGeometry( g->segmentize() );
266 g = geom.constGet()->simplifiedTypeRef();
267 }
268
269 const QgsPropertyCollection &ddp = mSymbol->dataDefinedProperties();
270 const bool hasDDHeight = ddp.isActive( QgsAbstract3DSymbol::Property::Height );
271 const bool hasDDExtrusion = ddp.isActive( QgsAbstract3DSymbol::Property::ExtrusionHeight );
272
273 float offset = mSymbol->offset();
274 float extrusionHeight = mSymbol->extrusionHeight();
275 if ( hasDDHeight )
276 offset = static_cast<float>( ddp.valueAsDouble( QgsAbstract3DSymbol::Property::Height, context.expressionContext(), offset ) );
277 if ( hasDDExtrusion )
278 extrusionHeight = ddp.valueAsDouble( QgsAbstract3DSymbol::Property::ExtrusionHeight, context.expressionContext(), extrusionHeight );
279
280 if ( const QgsPolygon *poly = qgsgeometry_cast<const QgsPolygon *>( g ) )
281 {
282 processPolygon( poly, f.id(), offset, extrusionHeight, context, out );
283 }
284 else if ( const QgsMultiPolygon *mpoly = qgsgeometry_cast<const QgsMultiPolygon *>( g ) )
285 {
286 for ( int i = 0; i < mpoly->numGeometries(); ++i )
287 {
288 const QgsPolygon *poly = mpoly->polygonN( i );
289 processPolygon( poly, f.id(), offset, extrusionHeight, context, out );
290 }
291 }
293 {
294 for ( int i = 0; i < gc->numGeometries(); ++i )
295 {
296 const QgsAbstractGeometry *g2 = gc->geometryN( i );
298 {
299 const QgsPolygon *poly = static_cast<const QgsPolygon *>( g2 );
300 processPolygon( poly, f.id(), offset, extrusionHeight, context, out );
301 }
302 }
303 }
304 else if ( const QgsPolyhedralSurface *polySurface = qgsgeometry_cast<const QgsPolyhedralSurface *>( g ) )
305 {
306 for ( int i = 0; i < polySurface->numPatches(); ++i )
307 {
308 const QgsPolygon *poly = polySurface->patchN( i );
309 processPolygon( poly, f.id(), offset, extrusionHeight, context, out );
310 }
311 }
312 else
313 qWarning() << "not a polygon";
314
315 mFeatureCount++;
316}
317
318void QgsPolygon3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
319{
320 // create entity for selected and not selected
321 makeEntity( parent, context, outNormal, false );
322 makeEntity( parent, context, outSelected, true );
323
324 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
325 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
326
327 // add entity for edges, but not when doing highlighting
328 if ( mSymbol->edgesEnabled() && !outEdges.indexes.isEmpty() && !mHighlightingEnabled )
329 {
330 QgsLineMaterial *mat = new QgsLineMaterial;
331 mat->setLineColor( mSymbol->edgeColor() );
332 mat->setLineWidth( mSymbol->edgeWidth() );
333
334 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
335 entity->setObjectName( parent->objectName() + "_EDGES" );
336
337 // geometry renderer
338 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
339 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
340 renderer->setGeometry( outEdges.createGeometry( entity ) );
341 renderer->setVertexCount( outEdges.indexes.count() );
342 renderer->setPrimitiveRestartEnabled( true );
343 renderer->setRestartIndexValue( 0 );
344
345 // add transform (our geometry has coordinates relative to mChunkOrigin)
346 QgsGeoTransform *tr = new QgsGeoTransform;
347 tr->setGeoTranslation( mChunkOrigin );
348
349 // make entity
350 entity->addComponent( renderer );
351 entity->addComponent( mat );
352 entity->addComponent( tr );
353 entity->setParent( parent );
354 }
355}
356
357
358void QgsPolygon3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PolygonData &polyData, bool selected )
359{
360 if ( polyData.tessellator->dataVerticesCount() == 0 )
361 return; // nothing to show - no need to create the entity
362
363 QgsMaterial *mat = material( mSymbol.get(), selected, context );
364
365 // extract vertex buffer data from tessellator
366 const QByteArray vertexBuffer = polyData.tessellator->vertexBuffer();
367 const QByteArray indexBuffer = polyData.tessellator->indexBuffer();
368 const int vertexCount = polyData.tessellator->uniqueVertexCount();
369 const size_t indexCount = polyData.tessellator->dataVerticesCount();
370
372 true,
373 mSymbol->invertNormals(),
374 mSymbol->addBackFaces(),
375 mSymbol->materialSettings() && mSymbol->materialSettings()->requiresTextureCoordinates(),
376 mSymbol->materialSettings() && mSymbol->materialSettings()->requiresTangents()
377 );
378
379 geometry->setVertexBufferData( vertexBuffer, vertexCount, polyData.triangleIndexFids, polyData.triangleIndexStartingIndices );
380 geometry->setIndexBufferData( indexBuffer, indexCount );
381
382 if ( mSymbol->materialSettings()->dataDefinedProperties().hasActiveProperties() )
383 {
384 Qgs3D::applyMaterialDataDefinedToGeometry( mSymbol->materialSettings(), geometry, vertexCount, polyData.materialDataDefined );
385 }
386 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
387 renderer->setGeometry( geometry );
388
389 // add transform (our geometry has coordinates relative to mChunkOrigin)
390 QgsGeoTransform *tr = new QgsGeoTransform;
391 tr->setGeoTranslation( mChunkOrigin );
392
393 // make entity
394 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
395 entity->setObjectName( parent->objectName() + "_CHUNK_MESH" );
396 entity->addComponent( renderer );
397 entity->addComponent( mat );
398 entity->addComponent( tr );
399 entity->setParent( parent );
400
401 if ( !selected )
402 renderer->setProperty( Qgs3DTypes::PROP_NAME_3D_RENDERER_FLAG, Qgs3DTypes::Main3DRenderer ); // temporary measure to distinguish between "selected" and "main"
403
404 // cppcheck wrongly believes entity will leak
405 // cppcheck-suppress memleak
406}
407
408// front/back side culling
409static void applyCullingMode( Qgs3DTypes::CullingMode cullingMode, QgsMaterial *material )
410{
411 const auto techniques = material->effect()->techniques();
412 for ( auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit )
413 {
414 auto renderPasses = ( *tit )->renderPasses();
415 for ( auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit )
416 {
417 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
418 cullFace->setMode( Qgs3DUtils::qt3DcullingMode( cullingMode ) );
419 ( *rpit )->addRenderState( cullFace );
420 }
421 }
422}
423
424QgsMaterial *QgsPolygon3DSymbolHandler::material( const QgsPolygon3DSymbol *symbol, bool isSelected, const Qgs3DRenderContext &context ) const
425{
426 QgsMaterialContext materialContext;
427 materialContext.setIsSelected( isSelected );
428 materialContext.setSelectionColor( context.selectionColor() );
429 materialContext.setIsHighlighted( mHighlightingEnabled );
430
431 const bool dataDefined = mSymbol->materialSettings()->dataDefinedProperties().hasActiveProperties();
433 applyCullingMode( symbol->cullingMode(), material );
434 return material;
435}
436
437
438// --------------
439
440
441namespace Qgs3DSymbolImpl
442{
443
444
445 QgsFeature3DHandler *handlerForPolygon3DSymbol( QgsVectorLayer *layer, const QgsAbstract3DSymbol *symbol )
446 {
447 const QgsPolygon3DSymbol *polygonSymbol = dynamic_cast<const QgsPolygon3DSymbol *>( symbol );
448 if ( !polygonSymbol )
449 return nullptr;
450
451 return new QgsPolygon3DSymbolHandler( polygonSymbol, layer->selectedFeatureIds() );
452 }
453} // namespace Qgs3DSymbolImpl
454
@ Line
Lines.
Definition qgis.h:381
@ Triangles
Triangle based rendering (default).
Definition qgis.h:4343
@ TrianglesDataDefined
Triangle based rendering with possibility of datadefined color.
Definition qgis.h:4349
@ Polygon
Polygon.
Definition qgis.h:298
Rendering context for preparation of 3D entities.
QColor selectionColor() const
Returns color used for selected features.
QgsExpressionContext & expressionContext()
Gets the expression context.
@ Main3DRenderer
Renderer for normal entities.
Definition qgs3dtypes.h:48
static const char * PROP_NAME_3D_RENDERER_FLAG
Qt property name to hold the 3D geometry renderer flag.
Definition qgs3dtypes.h:43
CullingMode
Triangle culling mode.
Definition qgs3dtypes.h:35
static Qt3DRender::QCullFace::CullingMode qt3DcullingMode(Qgs3DTypes::CullingMode mode)
Converts Qgs3DTypes::CullingMode mode into its Qt3D equivalent.
static void clampAltitudes(QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float offset, const Qgs3DRenderContext &context)
Clamps altitude of vertices of a linestring according to the settings.
static QgsMaterial * toMaterial(const QgsAbstractMaterialSettings *settings, Qgis::MaterialRenderingTechnique technique, const QgsMaterialContext &context)
Creates a new QgsMaterial object representing the material settings.
Definition qgs3d.cpp:141
static QByteArray materialDataDefinedVertexColorsAsByte(const QgsAbstractMaterialSettings *settings, const QgsExpressionContext &expressionContext)
Returns byte array corresponding to the data defined colors depending of the expressionContext,...
Definition qgs3d.cpp:175
static void applyMaterialDataDefinedToGeometry(const QgsAbstractMaterialSettings *settings, Qt3DCore::QGeometry *geometry, int vertexCount, const QByteArray &dataDefinedBytes)
Applies the data defined bytes, dataDefinedBytes, on the geometry by filling a specific vertex buffer...
Definition qgs3d.cpp:167
@ ExtrusionHeight
Extrusion height (zero means no extrusion).
Abstract base class for all geometries.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:45
QgsVector3D center() const
Returns the center of the box as a vector.
Definition qgsbox3d.cpp:124
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsFeatureId id
Definition qgsfeature.h:68
QgsGeometry geometry
Definition qgsfeature.h:71
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
bool convertGeometryCollectionToSubclass(Qgis::GeometryType geomType)
Converts geometry collection to a the desired geometry type subclass (multi-point,...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters &parameters=QgsGeometryParameters(), QgsFeedback *feedback=nullptr) const
Returns a geometry representing the points making up this geometry that do not make up other.
Line string geometry type, with support for z-dimension and m-values.
Context settings for a material.
void setIsSelected(bool isSelected)
Sets whether the material should represent a selected state.
void setSelectionColor(const QColor &color)
Sets the color for representing materials in a selected state.
void setIsHighlighted(bool isHighlighted)
Sets whether the material should represent a highlighted state.
Base class for all materials used within QGIS 3D views.
Definition qgsmaterial.h:40
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
Multi polygon geometry collection.
3D symbol that draws polygon geometries as planar polygons, optionally extruded (with added walls).
QgsAbstractMaterialSettings * materialSettings() const
Returns material settings used for shading of the symbol.
Qgs3DTypes::CullingMode cullingMode() const
Returns front/back culling mode.
Polygon geometry type.
Definition qgspolygon.h:37
QgsPolygon * clone() const override
Clones the geometry by performing a deep copy.
Polyhedral surface geometry type.
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
Qt3DRender::QGeometry subclass that represents polygons tessellated into 3D geometry.
void setVertexBufferData(const QByteArray &vertexBufferData, int vertexCount, const QVector< QgsFeatureId > &triangleIndexFids, const QVector< uint > &triangleIndexStartingIndices)
Initializes vertex buffer (and other members) from data that were already tessellated.
void setIndexBufferData(const QByteArray &indexBufferData, size_t indexCount)
Sets index buffer data.
void setZ(double z)
Sets Z coordinate.
Definition qgsvector3d.h:80
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
static Q_INVOKABLE bool isCurvedType(Qgis::WkbType type)
Returns true if the WKB type is a curved type or can contain curved geometries.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features