37#include <Qt3DCore/QTransform>
38#include <Qt3DExtras/QPhongMaterial>
39#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
40#include <Qt3DRender/QAttribute>
41#include <Qt3DRender/QBuffer>
47#include <Qt3DCore/QAttribute>
48#include <Qt3DCore/QBuffer>
54#include <Qt3DRender/QGeometryRenderer>
61class QgsBufferedLine3DSymbolHandler :
public QgsFeature3DHandler
66 , mSelectedIds( selectedIds ) {}
70 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;
101 Q_UNUSED( attributeNames )
103 mChunkOrigin = chunkOrigin;
107 outNormal.tessellator.reset(
new QgsTessellator( chunkOrigin.
x(), chunkOrigin.
y(),
true,
false,
false,
false, texturedMaterialSettings ? texturedMaterialSettings->
requiresTextureCoordinates() : false, 3, texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
108 outSelected.tessellator.reset(
new QgsTessellator( chunkOrigin.
x(), chunkOrigin.
y(),
true,
false,
false,
false, texturedMaterialSettings ? texturedMaterialSettings->
requiresTextureCoordinates() : false, 3, texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
110 outNormal.tessellator->setOutputZUp(
true );
111 outSelected.tessellator->setOutputZUp(
true );
121 LineData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
134 const int nSegments = 4;
137 const double mitreLimit = 0;
141 double width = mSymbol->width();
149 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
156 processPolygon( polyBuffered, f.
id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, out );
164 processPolygon( polyBuffered, f.
id(), mSymbol->offset(), mSymbol->extrusionHeight(), context, out );
175 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
176 const uint startingTriangleIndex =
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
177 out.triangleIndexStartingIndices.append( startingTriangleIndex );
178 out.triangleIndexFids.append( fid );
179 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
180 if ( !out.tessellator->error().isEmpty() )
188void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
191 makeEntity( parent, context, outNormal,
false );
192 makeEntity( parent, context, outSelected,
true );
194 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
195 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
199void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected )
201 if ( out.tessellator->dataVerticesCount() == 0 )
210 const QByteArray data( (
const char * ) out.tessellator->data().constData(), out.tessellator->data().count() *
sizeof(
float ) );
211 const int nVerts = data.count() / out.tessellator->stride();
216 geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
218 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
219 renderer->setGeometry( geometry );
222 QgsGeoTransform *tr =
new QgsGeoTransform;
223 tr->setGeoTranslation( mChunkOrigin );
226 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
227 entity->addComponent( renderer );
228 entity->addComponent( mat );
229 entity->addComponent( tr );
230 entity->setParent( parent );
243class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
248 , mSelectedIds( selectedIds )
254 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
257 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
258 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
259 void processMaterialDatadefined( uint verticesCount,
const QgsExpressionContext &context, QgsLineVertexData &out );
262 std::unique_ptr<QgsLine3DSymbol> mSymbol;
270 QgsLineVertexData outNormal;
271 QgsLineVertexData outSelected;
277 Q_UNUSED( attributeNames )
279 mChunkOrigin = chunkOrigin;
281 outNormal.withAdjacency =
true;
282 outSelected.withAdjacency =
true;
283 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
284 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
286 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.
expressionContext() );
287 attributeNames.unite( attrs );
288 attrs = mSymbol->materialSettings()->dataDefinedProperties().referencedFields( context.
expressionContext() );
289 attributeNames.unite( attrs );
293 processMaterialDatadefined( outNormal.vertices.size(), context.
expressionContext(), outNormal );
294 processMaterialDatadefined( outSelected.vertices.size(), context.
expressionContext(), outSelected );
306 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
308 const int oldVerticesCount = out.vertices.size();
320 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
322 out.addLineString( *ls );
324 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
326 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
329 out.addLineString( *ls );
334 processMaterialDatadefined( out.vertices.size() - oldVerticesCount, context.
expressionContext(), out );
339void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
342 makeEntity( parent, context, outNormal,
false );
343 makeEntity( parent, context, outSelected,
true );
345 updateZRangeFromPositions( outNormal.vertices );
346 updateZRangeFromPositions( outSelected.vertices );
350void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
352 if ( out.indexes.isEmpty() )
366 if ( QgsLineMaterial *lineMaterial =
dynamic_cast<QgsLineMaterial *
>( mat ) )
367 lineMaterial->setLineWidth( mSymbol->width() );
369 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
372 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
373 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
377 mSymbol->materialSettings()->applyDataDefinedToGeometry( geometry, out.vertices.size(), out.materialDataDefined );
379 renderer->setGeometry( geometry );
381 renderer->setVertexCount( out.indexes.count() );
382 renderer->setPrimitiveRestartEnabled(
true );
383 renderer->setRestartIndexValue( 0 );
386 QgsGeoTransform *tr =
new QgsGeoTransform;
387 tr->setGeoTranslation( mChunkOrigin );
390 entity->addComponent( renderer );
391 entity->addComponent( mat );
392 entity->addComponent( tr );
393 entity->setParent( parent );
396void QgsThickLine3DSymbolHandler::processMaterialDatadefined( uint verticesCount,
const QgsExpressionContext &context, QgsLineVertexData &out )
398 const QByteArray bytes = mSymbol->materialSettings()->dataDefinedVertexColorsAsByte( context );
399 out.materialDataDefined.append( bytes.repeated( verticesCount ) );
406namespace 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.
@ 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)
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