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>
48#include <Qt3DCore/QAttribute>
49#include <Qt3DCore/QBuffer>
55#include <Qt3DRender/QGeometryRenderer>
62class QgsBufferedLine3DSymbolHandler :
public QgsFeature3DHandler
65 QgsBufferedLine3DSymbolHandler(
const QgsLine3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
66 : mSymbol( static_cast<QgsLine3DSymbol *>( symbol->clone() ) )
67 , mSelectedIds( selectedIds ) {}
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;
77 std::unique_ptr<QgsTessellator> tessellator;
78 QVector<QgsFeatureId> triangleIndexFids;
79 QVector<uint> triangleIndexStartingIndices;
82 void processPolygon( QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &lineData );
84 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &lineData,
bool selected );
87 std::unique_ptr<QgsLine3DSymbol> mSymbol;
92 QgsVector3D mChunkOrigin;
95 LineData mLineDataNormal;
96 LineData mLineDataSelected;
102 Q_UNUSED( attributeNames )
104 mChunkOrigin = chunkOrigin;
108 const float textureRotation = texturedMaterialSettings ?
static_cast<float>( texturedMaterialSettings->
textureRotation() ) : 0;
109 const bool requiresTextureCoordinates = texturedMaterialSettings ? texturedMaterialSettings->
requiresTextureCoordinates() :
false;
111 auto lineDataNormalTessellator = std::make_unique<QgsTessellator>();
112 lineDataNormalTessellator->setOrigin( chunkOrigin );
113 lineDataNormalTessellator->setAddNormals(
true );
114 lineDataNormalTessellator->setAddTextureUVs( requiresTextureCoordinates );
116 lineDataNormalTessellator->setTextureRotation( textureRotation );
118 mLineDataNormal.tessellator = std::move( lineDataNormalTessellator );
120 auto lineDataSelectedTessellator = std::make_unique<QgsTessellator>();
121 lineDataSelectedTessellator->setOrigin( chunkOrigin );
122 lineDataSelectedTessellator->setAddNormals(
true );
123 lineDataSelectedTessellator->setAddTextureUVs( requiresTextureCoordinates );
125 lineDataSelectedTessellator->setTextureRotation( textureRotation );
127 mLineDataSelected.tessellator = std::move( lineDataSelectedTessellator );
129 mLineDataNormal.tessellator->setOutputZUp(
true );
130 mLineDataSelected.tessellator->setOutputZUp(
true );
140 LineData &lineData = mSelectedIds.contains( feature.
id() ) ? mLineDataSelected : mLineDataNormal;
153 const int nSegments = 4;
156 const double mitreLimit = 0;
158 const QgsGeos engine( abstractGeom );
160 double width = mSymbol->width();
168 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
175 processPolygon( polyBuffered, feature.
id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, lineData );
183 processPolygon( polyBuffered, feature.
id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, lineData );
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() )
207void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
210 makeEntity( parent, context, mLineDataNormal,
false );
211 makeEntity( parent, context, mLineDataSelected,
true );
213 mZMin = std::min( mLineDataNormal.tessellator->zMinimum(), mLineDataSelected.tessellator->zMinimum() );
214 mZMax = std::max( mLineDataNormal.tessellator->zMaximum(), mLineDataSelected.tessellator->zMaximum() );
218void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &lineData,
bool selected )
220 if ( lineData.tessellator->dataVerticesCount() == 0 )
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();
235 geometry->
setData( data, nVerts, lineData.triangleIndexFids, lineData.triangleIndexStartingIndices );
237 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
238 renderer->setGeometry( geometry );
241 QgsGeoTransform *transform =
new QgsGeoTransform;
242 transform->setGeoTranslation( mChunkOrigin );
245 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
246 entity->addComponent( renderer );
247 entity->addComponent( material );
248 entity->addComponent( transform );
249 entity->setParent( parent );
262class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
265 QgsThickLine3DSymbolHandler(
const QgsLine3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
266 : mSymbol( static_cast<QgsLine3DSymbol *>( symbol->clone() ) )
267 , mSelectedIds( selectedIds )
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;
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 );
281 std::unique_ptr<QgsLine3DSymbol> mSymbol;
286 QgsVector3D mChunkOrigin;
289 QgsLineVertexData mLineDataNormal;
290 QgsLineVertexData mLineDataSelected;
296 Q_UNUSED( attributeNames )
298 mChunkOrigin = chunkOrigin;
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 );
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 );
312 processMaterialDatadefined( mLineDataNormal.vertices.size(), context.
expressionContext(), mLineDataNormal );
313 processMaterialDatadefined( mLineDataSelected.vertices.size(), context.
expressionContext(), mLineDataSelected );
325 QgsLineVertexData &lineVertexData = mSelectedIds.contains( feature.
id() ) ? mLineDataSelected : mLineDataNormal;
327 const int oldVerticesCount = lineVertexData.vertices.size();
341 lineVertexData.addLineString( *lineString );
345 for (
int nGeom = 0; nGeom < multiLineString->numGeometries(); ++nGeom )
347 const QgsLineString *lineString = multiLineString->lineStringN( nGeom );
348 lineVertexData.addLineString( *lineString );
353 processMaterialDatadefined( lineVertexData.vertices.size() - oldVerticesCount, context.
expressionContext(), lineVertexData );
358void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
361 makeEntity( parent, context, mLineDataNormal,
false );
362 makeEntity( parent, context, mLineDataSelected,
true );
364 updateZRangeFromPositions( mLineDataNormal.vertices );
365 updateZRangeFromPositions( mLineDataSelected.vertices );
369void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &lineVertexData,
bool selected )
371 if ( lineVertexData.indexes.isEmpty() )
385 if ( QgsLineMaterial *lineMaterial =
dynamic_cast<QgsLineMaterial *
>( material ) )
386 lineMaterial->setLineWidth( mSymbol->width() );
388 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
391 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
392 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
393 Qt3DQGeometry *geometry = lineVertexData.createGeometry( entity );
396 mSymbol->materialSettings()->applyDataDefinedToGeometry( geometry, lineVertexData.vertices.size(), lineVertexData.materialDataDefined );
398 renderer->setGeometry( geometry );
400 renderer->setVertexCount( lineVertexData.indexes.count() );
401 renderer->setPrimitiveRestartEnabled(
true );
402 renderer->setRestartIndexValue( 0 );
405 QgsGeoTransform *transform =
new QgsGeoTransform;
406 transform->setGeoTranslation( mChunkOrigin );
409 entity->addComponent( renderer );
410 entity->addComponent( material );
411 entity->addComponent( transform );
412 entity->setParent( parent );
415void QgsThickLine3DSymbolHandler::processMaterialDatadefined( uint verticesCount,
const QgsExpressionContext &context, QgsLineVertexData &lineVertexData )
417 const QByteArray bytes = mSymbol->materialSettings()->dataDefinedVertexColorsAsByte( context );
418 lineVertexData.materialDataDefined.append( bytes.repeated(
static_cast<int>( verticesCount ) ) );
425namespace Qgs3DSymbolImpl
428 QgsFeature3DHandler *handlerForLine3DSymbol( QgsVectorLayer *layer,
const QgsAbstract3DSymbol *symbol )
430 const QgsLine3DSymbol *lineSymbol =
dynamic_cast<const QgsLine3DSymbol *
>( symbol );
JoinStyle
Join styles for buffers.
@ Round
Use rounded joins.
EndCapStyle
End cap styles for buffers.
@ MultiPolygon
MultiPolygon.
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.
static const char * PROP_NAME_3D_RENDERER_FLAG
Qt property name to hold the 3D geometry renderer flag.
static void clampAltitudes(QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint ¢roid, 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.
@ Ambient
Ambient color (phong material).
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...
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.
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.
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.
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...
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).
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