36#include <Qt3DCore/QTransform>
37#include <Qt3DExtras/QPhongMaterial>
38#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
39#include <Qt3DRender/QAttribute>
40#include <Qt3DRender/QBuffer>
46#include <Qt3DCore/QAttribute>
47#include <Qt3DCore/QBuffer>
53#include <Qt3DRender/QGeometryRenderer>
60class QgsBufferedLine3DSymbolHandler :
public QgsFeature3DHandler
65 , mSelectedIds( selectedIds ) {}
69 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
76 std::unique_ptr<QgsTessellator> tessellator;
77 QVector<QgsFeatureId> triangleIndexFids;
78 QVector<uint> triangleIndexStartingIndices;
83 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected );
86 std::unique_ptr< QgsLine3DSymbol > mSymbol;
102 Q_UNUSED( attributeNames )
104 mChunkOrigin = chunkOrigin;
108 outNormal.tessellator.reset(
new QgsTessellator( chunkOrigin.
x(), chunkOrigin.
y(),
true,
111 texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
112 outSelected.tessellator.reset(
new QgsTessellator( chunkOrigin.
x(), chunkOrigin.
y(),
true,
115 texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
117 outNormal.tessellator->setOutputZUp(
true );
118 outSelected.tessellator->setOutputZUp(
true );
128 LineData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
141 const int nSegments = 4;
144 const double mitreLimit = 0;
148 double width = mSymbol->width();
156 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
163 processPolygon( polyBuffered, f.
id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, out );
171 processPolygon( polyBuffered, f.
id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, out );
182 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
183 const uint startingTriangleIndex =
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
184 out.triangleIndexStartingIndices.append( startingTriangleIndex );
185 out.triangleIndexFids.append( fid );
186 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
187 if ( !out.tessellator->error().isEmpty() )
195void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
198 makeEntity( parent, context, outNormal,
false );
199 makeEntity( parent, context, outSelected,
true );
201 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
202 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
206void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected )
208 if ( out.tessellator->dataVerticesCount() == 0 )
217 const QByteArray data( (
const char * )out.tessellator->data().constData(), out.tessellator->data().count() *
sizeof(
float ) );
218 const int nVerts = data.count() / out.tessellator->stride();
224 geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
226 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
227 renderer->setGeometry( geometry );
230 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
231 QVector3D nodeTranslation = ( mChunkOrigin - context.
origin() ).toVector3D();
232 tr->setTranslation( nodeTranslation );
235 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
236 entity->addComponent( renderer );
237 entity->addComponent( mat );
238 entity->addComponent( tr );
239 entity->setParent( parent );
252class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
257 , mSelectedIds( selectedIds )
263 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
268 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
269 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
270 void processMaterialDatadefined( uint verticesCount,
const QgsExpressionContext &context, QgsLineVertexData &out );
273 std::unique_ptr< QgsLine3DSymbol > mSymbol;
281 QgsLineVertexData outNormal;
282 QgsLineVertexData outSelected;
289 Q_UNUSED( attributeNames )
291 mChunkOrigin = chunkOrigin;
293 outNormal.withAdjacency =
true;
294 outSelected.withAdjacency =
true;
295 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
296 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
298 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.
expressionContext() );
299 attributeNames.unite( attrs );
300 attrs = mSymbol->materialSettings()->dataDefinedProperties().referencedFields( context.
expressionContext() );
301 attributeNames.unite( attrs );
305 processMaterialDatadefined( outNormal.vertices.size(), context.
expressionContext(), outNormal );
306 processMaterialDatadefined( outSelected.vertices.size(), context.
expressionContext(), outSelected );
318 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
320 const int oldVerticesCount = out.vertices.size();
332 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
334 out.addLineString( *ls );
336 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
338 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
341 out.addLineString( *ls );
346 processMaterialDatadefined( out.vertices.size() - oldVerticesCount, context.
expressionContext(), out );
351void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
354 makeEntity( parent, context, outNormal,
false );
355 makeEntity( parent, context, outSelected,
true );
357 updateZRangeFromPositions( outNormal.vertices );
358 updateZRangeFromPositions( outSelected.vertices );
362void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
364 if ( out.indexes.isEmpty() )
378 if ( QgsLineMaterial *lineMaterial =
dynamic_cast< QgsLineMaterial *
>( mat ) )
379 lineMaterial->setLineWidth( mSymbol->width() );
381 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
384 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
385 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
389 mSymbol->materialSettings()->applyDataDefinedToGeometry( geometry, out.vertices.size(), out.materialDataDefined );
391 renderer->setGeometry( geometry );
393 renderer->setVertexCount( out.indexes.count() );
394 renderer->setPrimitiveRestartEnabled(
true );
395 renderer->setRestartIndexValue( 0 );
398 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
399 QVector3D nodeTranslation = ( mChunkOrigin - context.
origin() ).toVector3D();
400 tr->setTranslation( nodeTranslation );
403 entity->addComponent( renderer );
404 entity->addComponent( mat );
405 entity->addComponent( tr );
406 entity->setParent( parent );
409void QgsThickLine3DSymbolHandler::processMaterialDatadefined( uint verticesCount,
const QgsExpressionContext &context, QgsLineVertexData &out )
411 const QByteArray bytes = mSymbol->materialSettings()->dataDefinedVertexColorsAsByte( context );
412 out.materialDataDefined.append( bytes.repeated( verticesCount ) );
419namespace Qgs3DSymbolImpl
JoinStyle
Join styles for buffers.
@ Round
Use rounded joins.
EndCapStyle
End cap styles for buffers.
@ MultiPolygon
MultiPolygon.
QColor selectionColor() const
Returns color used for selected features.
QgsExpressionContext & expressionContext()
Gets the expression context.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
@ 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, 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.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
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.
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
QgsMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QgsMaterial 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.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
double y() const
Returns Y coordinate.
double x() const
Returns X coordinate.
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