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.
@ Round
Use rounded joins.
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 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.
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, 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....
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)
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::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