QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgsline3dsymbol_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsline3dsymbol_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
16#include "qgsline3dsymbol_p.h"
17
18#include "qgs3dmapsettings.h"
19#include "qgsgeotransform.h"
20#include "qgsline3dsymbol.h"
21#include "qgslinematerial_p.h"
22#include "qgslinevertexdata_p.h"
24#include "qgstessellator.h"
25
26//#include "qgsterraingenerator.h"
27#include "qgs3dutils.h"
28
29#include "qgsvectorlayer.h"
30#include "qgsmultilinestring.h"
31#include "qgsmultipolygon.h"
32#include "qgsgeos.h"
34#include "qgspolygon.h"
36#include "qgsmessagelog.h"
37
38#include <Qt3DCore/QTransform>
39#include <Qt3DExtras/QPhongMaterial>
40#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
41#include <Qt3DRender/QAttribute>
42#include <Qt3DRender/QBuffer>
43
44typedef Qt3DRender::QAttribute Qt3DQAttribute;
45typedef Qt3DRender::QBuffer Qt3DQBuffer;
46typedef Qt3DRender::QGeometry Qt3DQGeometry;
47#else
48#include <Qt3DCore/QAttribute>
49#include <Qt3DCore/QBuffer>
50
51typedef Qt3DCore::QAttribute Qt3DQAttribute;
52typedef Qt3DCore::QBuffer Qt3DQBuffer;
53typedef Qt3DCore::QGeometry Qt3DQGeometry;
54#endif
55#include <Qt3DRender/QGeometryRenderer>
56
58
59// -----------
60
61
62class QgsBufferedLine3DSymbolHandler : public QgsFeature3DHandler
63{
64 public:
65 QgsBufferedLine3DSymbolHandler( const QgsLine3DSymbol *symbol, const QgsFeatureIds &selectedIds )
66 : mSymbol( static_cast<QgsLine3DSymbol *>( symbol->clone() ) )
67 , mSelectedIds( selectedIds ) {}
68
69 bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
70 void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
71 void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
72
73 private:
75 struct LineData
76 {
77 std::unique_ptr<QgsTessellator> tessellator;
78 QVector<QgsFeatureId> triangleIndexFids;
79 QVector<uint> triangleIndexStartingIndices;
80 };
81
82 void processPolygon( QgsPolygon *polyBuffered, QgsFeatureId fid, float height, float extrusionHeight, const Qgs3DRenderContext &context, LineData &lineData );
83
84 void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, LineData &lineData, bool selected );
85
86 // input specific for this class
87 std::unique_ptr<QgsLine3DSymbol> mSymbol;
88 // inputs - generic
89 QgsFeatureIds mSelectedIds;
90
92 QgsVector3D mChunkOrigin;
93
94 // outputs
95 LineData mLineDataNormal;
96 LineData mLineDataSelected;
97};
98
99
100bool QgsBufferedLine3DSymbolHandler::prepare( const Qgs3DRenderContext &, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
101{
102 Q_UNUSED( attributeNames )
103
104 mChunkOrigin = chunkOrigin;
105
106 const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast<const QgsPhongTexturedMaterialSettings *>( mSymbol->materialSettings() );
107
108 const float textureRotation = texturedMaterialSettings ? static_cast<float>( texturedMaterialSettings->textureRotation() ) : 0;
109 const bool requiresTextureCoordinates = texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false;
110
111 auto lineDataNormalTessellator = std::make_unique<QgsTessellator>();
112 lineDataNormalTessellator->setOrigin( chunkOrigin );
113 lineDataNormalTessellator->setAddNormals( true );
114 lineDataNormalTessellator->setAddTextureUVs( requiresTextureCoordinates );
115 lineDataNormalTessellator->setExtrusionFaces( Qgis::ExtrusionFace::Walls | Qgis::ExtrusionFace::Roof );
116 lineDataNormalTessellator->setTextureRotation( textureRotation );
117
118 mLineDataNormal.tessellator = std::move( lineDataNormalTessellator );
119
120 auto lineDataSelectedTessellator = std::make_unique<QgsTessellator>();
121 lineDataSelectedTessellator->setOrigin( chunkOrigin );
122 lineDataSelectedTessellator->setAddNormals( true );
123 lineDataSelectedTessellator->setAddTextureUVs( requiresTextureCoordinates );
124 lineDataSelectedTessellator->setExtrusionFaces( Qgis::ExtrusionFace::Walls | Qgis::ExtrusionFace::Roof );
125 lineDataSelectedTessellator->setTextureRotation( textureRotation );
126
127 mLineDataSelected.tessellator = std::move( lineDataSelectedTessellator );
128
129 mLineDataNormal.tessellator->setOutputZUp( true );
130 mLineDataSelected.tessellator->setOutputZUp( true );
131
132 return true;
133}
134
135void QgsBufferedLine3DSymbolHandler::processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context )
136{
137 if ( feature.geometry().isNull() )
138 return;
139
140 LineData &lineData = mSelectedIds.contains( feature.id() ) ? mLineDataSelected : mLineDataNormal;
141
142 QgsGeometry geom = feature.geometry();
143 const QgsAbstractGeometry *abstractGeom = geom.constGet()->simplifiedTypeRef();
144
145 // segmentize curved geometries if necessary
146 if ( QgsWkbTypes::isCurvedType( abstractGeom->wkbType() ) )
147 {
148 geom = QgsGeometry( abstractGeom->segmentize() );
149 abstractGeom = geom.constGet()->simplifiedTypeRef();
150 }
151
152 // TODO: configurable
153 const int nSegments = 4;
155 const Qgis::JoinStyle joinStyle = Qgis::JoinStyle::Round;
156 const double mitreLimit = 0;
157
158 const QgsGeos engine( abstractGeom );
159
160 double width = mSymbol->width();
161 if ( qgsDoubleNear( width, 0 ) )
162 {
163 // a zero-width buffered line should be treated like a "wall" or "fence" -- we fake this by bumping the width to a very tiny amount,
164 // so that we get a very narrow polygon shape to work with...
165 width = 0.001;
166 }
167
168 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory
169 if ( !buffered )
170 return;
171
173 {
174 QgsPolygon *polyBuffered = qgsgeometry_cast<QgsPolygon *>( buffered );
175 processPolygon( polyBuffered, feature.id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, lineData );
176 }
177 else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == Qgis::WkbType::MultiPolygon )
178 {
179 QgsMultiPolygon *mpolyBuffered = qgsgeometry_cast<QgsMultiPolygon *>( buffered );
180 for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i )
181 {
182 QgsPolygon *polyBuffered = qgsgeometry_cast<QgsPolygon *>( mpolyBuffered->polygonN( i ) )->clone(); // need to clone individual geometry parts
183 processPolygon( polyBuffered, feature.id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, lineData );
184 }
185 delete buffered;
186 }
187 mFeatureCount++;
188}
189
190void QgsBufferedLine3DSymbolHandler::processPolygon( QgsPolygon *polyBuffered, QgsFeatureId fid, float height, float extrusionHeight, const Qgs3DRenderContext &context, LineData &lineData )
191{
192 Qgs3DUtils::clampAltitudes( polyBuffered, mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), height, context );
193
194 Q_ASSERT( lineData.tessellator->dataVerticesCount() % 3 == 0 );
195 const uint startingTriangleIndex = static_cast<uint>( lineData.tessellator->dataVerticesCount() / 3 );
196 lineData.triangleIndexStartingIndices.append( startingTriangleIndex );
197 lineData.triangleIndexFids.append( fid );
198 lineData.tessellator->addPolygon( *polyBuffered, extrusionHeight );
199 if ( !lineData.tessellator->error().isEmpty() )
200 {
201 QgsMessageLog::logMessage( lineData.tessellator->error(), QObject::tr( "3D" ) );
202 }
203
204 delete polyBuffered;
205}
206
207void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
208{
209 // create entity for selected and not selected
210 makeEntity( parent, context, mLineDataNormal, false );
211 makeEntity( parent, context, mLineDataSelected, true );
212
213 mZMin = std::min( mLineDataNormal.tessellator->zMinimum(), mLineDataSelected.tessellator->zMinimum() );
214 mZMax = std::max( mLineDataNormal.tessellator->zMaximum(), mLineDataSelected.tessellator->zMaximum() );
215}
216
217
218void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, LineData &lineData, bool selected )
219{
220 if ( lineData.tessellator->dataVerticesCount() == 0 )
221 return; // nothing to show - no need to create the entity
222
223 QgsMaterialContext materialContext;
224 materialContext.setIsSelected( selected );
225 materialContext.setSelectionColor( context.selectionColor() );
226 QgsMaterial *material = mSymbol->materialSettings()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, materialContext );
227
228 // extract vertex buffer data from tessellator
229 const QByteArray data( ( const char * ) lineData.tessellator->data().constData(), static_cast<int>( lineData.tessellator->data().count() * sizeof( float ) ) );
230 const int nVerts = data.count() / lineData.tessellator->stride();
231
232 const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast<const QgsPhongTexturedMaterialSettings *>( mSymbol->materialSettings() );
233
234 QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry( true, false, false, texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false );
235 geometry->setData( data, nVerts, lineData.triangleIndexFids, lineData.triangleIndexStartingIndices );
236
237 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
238 renderer->setGeometry( geometry );
239
240 // add transform (our geometry has coordinates relative to mChunkOrigin)
241 QgsGeoTransform *transform = new QgsGeoTransform;
242 transform->setGeoTranslation( mChunkOrigin );
243
244 // make entity
245 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
246 entity->addComponent( renderer );
247 entity->addComponent( material );
248 entity->addComponent( transform );
249 entity->setParent( parent );
250
251 if ( !selected )
252 renderer->setProperty( Qgs3DTypes::PROP_NAME_3D_RENDERER_FLAG, Qgs3DTypes::Main3DRenderer ); // temporary measure to distinguish between "selected" and "main"
253
254 // cppcheck wrongly believes entity will leak
255 // cppcheck-suppress memleak
256}
257
258
259// --------------
260
261
262class QgsThickLine3DSymbolHandler : public QgsFeature3DHandler
263{
264 public:
265 QgsThickLine3DSymbolHandler( const QgsLine3DSymbol *symbol, const QgsFeatureIds &selectedIds )
266 : mSymbol( static_cast<QgsLine3DSymbol *>( symbol->clone() ) )
267 , mSelectedIds( selectedIds )
268 {
269 }
270
271 bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
272 void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
273 void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
274
275 private:
276 void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QgsLineVertexData &lineVertexData, bool selected );
277 Qt3DExtras::QPhongMaterial *material( const QgsLine3DSymbol &symbol ) const;
278 void processMaterialDatadefined( uint verticesCount, const QgsExpressionContext &context, QgsLineVertexData &lineVertexData );
279
280 // input specific for this class
281 std::unique_ptr<QgsLine3DSymbol> mSymbol;
282 // inputs - generic
283 QgsFeatureIds mSelectedIds;
284
286 QgsVector3D mChunkOrigin;
287
288 // outputs
289 QgsLineVertexData mLineDataNormal;
290 QgsLineVertexData mLineDataSelected;
291};
292
293
294bool QgsThickLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
295{
296 Q_UNUSED( attributeNames )
297
298 mChunkOrigin = chunkOrigin;
299
300 mLineDataNormal.withAdjacency = true;
301 mLineDataSelected.withAdjacency = true;
302 mLineDataNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
303 mLineDataSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
304
305 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.expressionContext() );
306 attributeNames.unite( attrs );
307 attrs = mSymbol->materialSettings()->dataDefinedProperties().referencedFields( context.expressionContext() );
308 attributeNames.unite( attrs );
309
310 if ( mSymbol->materialSettings()->dataDefinedProperties().isActive( QgsAbstractMaterialSettings::Property::Ambient ) )
311 {
312 processMaterialDatadefined( mLineDataNormal.vertices.size(), context.expressionContext(), mLineDataNormal );
313 processMaterialDatadefined( mLineDataSelected.vertices.size(), context.expressionContext(), mLineDataSelected );
314 }
315
316 return true;
317}
318
319void QgsThickLine3DSymbolHandler::processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context )
320{
321 Q_UNUSED( context )
322 if ( feature.geometry().isNull() )
323 return;
324
325 QgsLineVertexData &lineVertexData = mSelectedIds.contains( feature.id() ) ? mLineDataSelected : mLineDataNormal;
326
327 const int oldVerticesCount = lineVertexData.vertices.size();
328
329 QgsGeometry geom = feature.geometry();
330 const QgsAbstractGeometry *abstractGeom = geom.constGet()->simplifiedTypeRef();
331
332 // segmentize curved geometries if necessary
333 if ( QgsWkbTypes::isCurvedType( abstractGeom->wkbType() ) )
334 {
335 geom = QgsGeometry( abstractGeom->segmentize() );
336 abstractGeom = geom.constGet()->simplifiedTypeRef();
337 }
338
339 if ( const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( abstractGeom ) )
340 {
341 lineVertexData.addLineString( *lineString );
342 }
343 else if ( const QgsMultiLineString *multiLineString = qgsgeometry_cast<const QgsMultiLineString *>( abstractGeom ) )
344 {
345 for ( int nGeom = 0; nGeom < multiLineString->numGeometries(); ++nGeom )
346 {
347 const QgsLineString *lineString = multiLineString->lineStringN( nGeom );
348 lineVertexData.addLineString( *lineString );
349 }
350 }
351
352 if ( mSymbol->materialSettings()->dataDefinedProperties().isActive( QgsAbstractMaterialSettings::Property::Ambient ) )
353 processMaterialDatadefined( lineVertexData.vertices.size() - oldVerticesCount, context.expressionContext(), lineVertexData );
354
355 mFeatureCount++;
356}
357
358void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
359{
360 // create entity for selected and not selected
361 makeEntity( parent, context, mLineDataNormal, false );
362 makeEntity( parent, context, mLineDataSelected, true );
363
364 updateZRangeFromPositions( mLineDataNormal.vertices );
365 updateZRangeFromPositions( mLineDataSelected.vertices );
366}
367
368
369void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QgsLineVertexData &lineVertexData, bool selected )
370{
371 if ( lineVertexData.indexes.isEmpty() )
372 return;
373
374 // material (only ambient color is used for the color)
375 QgsMaterialContext materialContext;
376 materialContext.setIsSelected( selected );
377 materialContext.setSelectionColor( context.selectionColor() );
378 QgsMaterial *material = mSymbol->materialSettings()->toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
379 if ( !material )
380 {
381 const QgsSimpleLineMaterialSettings defaultMaterial;
382 material = defaultMaterial.toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
383 }
384
385 if ( QgsLineMaterial *lineMaterial = dynamic_cast<QgsLineMaterial *>( material ) )
386 lineMaterial->setLineWidth( mSymbol->width() );
387
388 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
389
390 // geometry renderer
391 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
392 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
393 Qt3DQGeometry *geometry = lineVertexData.createGeometry( entity );
394
395 if ( mSymbol->materialSettings()->dataDefinedProperties().isActive( QgsAbstractMaterialSettings::Property::Ambient ) )
396 mSymbol->materialSettings()->applyDataDefinedToGeometry( geometry, lineVertexData.vertices.size(), lineVertexData.materialDataDefined );
397
398 renderer->setGeometry( geometry );
399
400 renderer->setVertexCount( lineVertexData.indexes.count() );
401 renderer->setPrimitiveRestartEnabled( true );
402 renderer->setRestartIndexValue( 0 );
403
404 // add transform (our geometry has coordinates relative to mChunkOrigin)
405 QgsGeoTransform *transform = new QgsGeoTransform;
406 transform->setGeoTranslation( mChunkOrigin );
407
408 // make entity
409 entity->addComponent( renderer );
410 entity->addComponent( material );
411 entity->addComponent( transform );
412 entity->setParent( parent );
413}
414
415void QgsThickLine3DSymbolHandler::processMaterialDatadefined( uint verticesCount, const QgsExpressionContext &context, QgsLineVertexData &lineVertexData )
416{
417 const QByteArray bytes = mSymbol->materialSettings()->dataDefinedVertexColorsAsByte( context );
418 lineVertexData.materialDataDefined.append( bytes.repeated( static_cast<int>( verticesCount ) ) );
419}
420
421
422// --------------
423
424
425namespace Qgs3DSymbolImpl
426{
427
428 QgsFeature3DHandler *handlerForLine3DSymbol( QgsVectorLayer *layer, const QgsAbstract3DSymbol *symbol )
429 {
430 const QgsLine3DSymbol *lineSymbol = dynamic_cast<const QgsLine3DSymbol *>( symbol );
431 if ( !lineSymbol )
432 return nullptr;
433
434 if ( lineSymbol->renderAsSimpleLines() )
435 return new QgsThickLine3DSymbolHandler( lineSymbol, layer->selectedFeatureIds() );
436 else
437 return new QgsBufferedLine3DSymbolHandler( lineSymbol, layer->selectedFeatureIds() );
438 }
439} // namespace Qgs3DSymbolImpl
440
JoinStyle
Join styles for buffers.
Definition qgis.h:2121
@ Round
Use rounded joins.
Definition qgis.h:2122
EndCapStyle
End cap styles for buffers.
Definition qgis.h:2108
@ Round
Round cap.
Definition qgis.h:2109
@ Polygon
Polygon.
Definition qgis.h:281
@ MultiPolygon
MultiPolygon.
Definition qgis.h:285
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
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.
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.
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:58
QgsFeatureId id
Definition qgsfeature.h:66
QgsGeometry geometry
Definition qgsfeature.h:69
int numGeometries() const
Returns the number of geometries within the collection.
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.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
Definition qgsgeos.h:141
bool renderAsSimpleLines() const
Returns whether the renderer will render data with simple lines (otherwise it uses buffer).
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.
Base class for all materials used within QGIS 3D views.
Definition qgsmaterial.h:39
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())
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
Multi polygon geometry collection.
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
A Phong shading model with diffuse texture map.
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
double textureRotation() const
Returns the texture rotation, in degrees.
Polygon geometry type.
Definition qgspolygon.h:33
QgsPolygon * clone() const override
Clones the geometry by performing a deep copy.
Basic shading material used for rendering simple lines as solid line components.
QgsMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QgsMaterial object representing the material settings.
Qt3DRender::QGeometry subclass that represents polygons tessellated into 3D geometry.
void setData(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.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
Definition qgsvector3d.h:30
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.
@ Triangles
Triangle based rendering (default).
@ Lines
Line based rendering, requires line data.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features