35#include <Qt3DExtras/QPhongMaterial>
36#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
37#include <Qt3DRender/QAttribute>
38#include <Qt3DRender/QBuffer>
44#include <Qt3DCore/QAttribute>
45#include <Qt3DCore/QBuffer>
51#include <Qt3DRender/QGeometryRenderer>
58class QgsBufferedLine3DSymbolHandler :
public QgsFeature3DHandler
63 , mSelectedIds( selectedIds ) {}
65 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
66 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
67 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
74 std::unique_ptr<QgsTessellator> tessellator;
75 QVector<QgsFeatureId> triangleIndexFids;
76 QVector<uint> triangleIndexStartingIndices;
79 void processPolygon(
QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &out );
81 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected );
84 std::unique_ptr< QgsLine3DSymbol > mSymbol;
95bool QgsBufferedLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
97 Q_UNUSED( attributeNames )
101 outNormal.tessellator.reset(
new QgsTessellator( context.map().origin().x(), context.map().origin().y(),
true,
104 texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
105 outSelected.tessellator.reset(
new QgsTessellator( context.map().origin().x(), context.map().origin().y(),
true,
108 texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
113void QgsBufferedLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
118 LineData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
131 const int nSegments = 4;
134 const double mitreLimit = 0;
138 double width = mSymbol->width();
146 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
153 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
161 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
168void QgsBufferedLine3DSymbolHandler::processPolygon(
QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &out )
172 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
173 const uint startingTriangleIndex =
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
174 out.triangleIndexStartingIndices.append( startingTriangleIndex );
175 out.triangleIndexFids.append( fid );
176 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
180void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
183 makeEntity( parent, context, outNormal,
false );
184 makeEntity( parent, context, outSelected,
true );
186 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
187 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
191void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected )
193 if ( out.tessellator->dataVerticesCount() == 0 )
202 const QByteArray data( (
const char * )out.tessellator->data().constData(), out.tessellator->data().count() *
sizeof(
float ) );
203 const int nVerts = data.count() / out.tessellator->stride();
209 geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
211 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
212 renderer->setGeometry( geometry );
215 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
216 entity->addComponent( renderer );
217 entity->addComponent( mat );
218 entity->setParent( parent );
231class QgsSimpleLine3DSymbolHandler :
public QgsFeature3DHandler
236 , mSelectedIds( selectedIds )
240 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
241 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
242 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
246 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
247 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
250 std::unique_ptr< QgsLine3DSymbol > mSymbol;
255 QgsLineVertexData outNormal;
256 QgsLineVertexData outSelected;
261bool QgsSimpleLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
263 Q_UNUSED( attributeNames )
265 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
266 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
271void QgsSimpleLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
277 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
281 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
283 out.addLineString( *ls );
285 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
287 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
290 out.addLineString( *ls );
296void QgsSimpleLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
299 makeEntity( parent, context, outNormal,
false );
300 makeEntity( parent, context, outSelected,
true );
302 updateZRangeFromPositions( outNormal.vertices );
303 updateZRangeFromPositions( outSelected.vertices );
307void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
309 if ( out.indexes.isEmpty() )
321 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
325 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
326 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
327 renderer->setGeometry( geom );
328 renderer->setVertexCount( out.indexes.count() );
329 renderer->setPrimitiveRestartEnabled(
true );
330 renderer->setRestartIndexValue( 0 );
333 entity->addComponent( renderer );
334 entity->addComponent( mat );
335 entity->setParent( parent );
343class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
348 , mSelectedIds( selectedIds )
352 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
353 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
354 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
359 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
360 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
363 std::unique_ptr< QgsLine3DSymbol > mSymbol;
368 QgsLineVertexData outNormal;
369 QgsLineVertexData outSelected;
374bool QgsThickLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
376 Q_UNUSED( attributeNames )
378 outNormal.withAdjacency =
true;
379 outSelected.withAdjacency =
true;
380 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
381 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
386void QgsThickLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
392 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
404 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
406 out.addLineString( *ls );
408 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
410 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
413 out.addLineString( *ls );
419void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
422 makeEntity( parent, context, outNormal,
false );
423 makeEntity( parent, context, outSelected,
true );
425 updateZRangeFromPositions( outNormal.vertices );
426 updateZRangeFromPositions( outSelected.vertices );
430void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
432 if ( out.indexes.isEmpty() )
446 if ( QgsLineMaterial *lineMaterial =
dynamic_cast< QgsLineMaterial *
>( mat ) )
447 lineMaterial->setLineWidth( mSymbol->width() );
449 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
452 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
453 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
454 renderer->setGeometry( out.createGeometry( entity ) );
455 renderer->setVertexCount( out.indexes.count() );
456 renderer->setPrimitiveRestartEnabled(
true );
457 renderer->setRestartIndexValue( 0 );
460 entity->addComponent( renderer );
461 entity->addComponent( mat );
462 entity->setParent( parent );
469namespace Qgs3DSymbolImpl
487 QgsFeature3DHandler *handler = handlerForLine3DSymbol( layer, &symbol );
488 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
JoinStyle
Join styles for buffers.
EndCapStyle
End cap styles for buffers.
@ MultiPolygon
MultiPolygon.
@ 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 height, const Qgs3DMapSettings &map)
Clamps altitude of vertices of a linestring according to the settings.
Abstract base class for all geometries.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const SIP_HOLDGIL
Returns a reference to the simplest lossless representation of this geometry, e.g.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Does vector analysis using the geos library and handles import, export, exception handling*.
bool renderAsSimpleLines() const
Returns whether the renderer will render data with simple lines (otherwise it uses buffer)
QgsAbstract3DSymbol * clone() const override SIP_FACTORY
Line string geometry type, with support for z-dimension and m-values.
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.
Multi line string geometry collection.
Multi polygon geometry collection.
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
float textureRotation() const
Returns the texture rotation, in degrees.
Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QMaterial object representing the material settings.
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.
Class that takes care of tessellation of polygons into triangles.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
static bool isCurvedType(Qgis::WkbType type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
static Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
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::QGeometry Qt3DQGeometry
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry