35 #include <Qt3DExtras/QPhongMaterial>
36 #include <Qt3DRender/QAttribute>
37 #include <Qt3DRender/QBuffer>
38 #include <Qt3DRender/QGeometryRenderer>
45 class QgsBufferedLine3DSymbolHandler :
public QgsFeature3DHandler
50 , mSelectedIds( selectedIds ) {}
52 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
53 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
54 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
61 std::unique_ptr<QgsTessellator> tessellator;
62 QVector<QgsFeatureId> triangleIndexFids;
63 QVector<uint> triangleIndexStartingIndices;
66 void processPolygon(
QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &out );
68 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected );
71 std::unique_ptr< QgsLine3DSymbol > mSymbol;
82 bool QgsBufferedLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
84 Q_UNUSED( attributeNames )
88 outNormal.tessellator.reset(
new QgsTessellator( context.map().origin().x(), context.map().origin().y(),
true,
91 texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
92 outSelected.tessellator.reset(
new QgsTessellator( context.map().origin().x(), context.map().origin().y(),
true,
95 texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
100 void QgsBufferedLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
105 LineData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
116 const int nSegments = 4;
119 const double mitreLimit = 0;
123 double width = mSymbol->width();
131 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
138 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
146 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
152 void QgsBufferedLine3DSymbolHandler::processPolygon(
QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &out )
156 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
157 uint startingTriangleIndex =
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
158 out.triangleIndexStartingIndices.append( startingTriangleIndex );
159 out.triangleIndexFids.append( fid );
160 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
164 void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
167 makeEntity( parent, context, outNormal,
false );
168 makeEntity( parent, context, outSelected,
true );
170 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
171 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
175 void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected )
177 if ( out.tessellator->dataVerticesCount() == 0 )
186 QByteArray data( (
const char * )out.tessellator->data().constData(), out.tessellator->data().count() *
sizeof(
float ) );
187 int nVerts = data.count() / out.tessellator->stride();
193 geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
195 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
196 renderer->setGeometry( geometry );
199 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
200 entity->addComponent( renderer );
201 entity->addComponent( mat );
202 entity->setParent( parent );
205 entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral(
"main" ) );
215 class QgsSimpleLine3DSymbolHandler :
public QgsFeature3DHandler
220 , mSelectedIds( selectedIds )
224 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
225 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
226 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
230 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
231 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
234 std::unique_ptr< QgsLine3DSymbol > mSymbol;
239 QgsLineVertexData outNormal;
240 QgsLineVertexData outSelected;
245 bool QgsSimpleLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
247 Q_UNUSED( attributeNames )
249 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
250 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
255 void QgsSimpleLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
261 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
265 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
267 out.addLineString( *ls );
269 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
271 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
274 out.addLineString( *ls );
279 void QgsSimpleLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
282 makeEntity( parent, context, outNormal,
false );
283 makeEntity( parent, context, outSelected,
true );
285 updateZRangeFromPositions( outNormal.vertices );
286 updateZRangeFromPositions( outSelected.vertices );
290 void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
292 if ( out.indexes.isEmpty() )
304 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
306 Qt3DRender::QGeometry *geom = out.createGeometry( entity );
308 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
309 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
310 renderer->setGeometry( geom );
311 renderer->setVertexCount( out.indexes.count() );
312 renderer->setPrimitiveRestartEnabled(
true );
313 renderer->setRestartIndexValue( 0 );
316 entity->addComponent( renderer );
317 entity->addComponent( mat );
318 entity->setParent( parent );
326 class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
331 , mSelectedIds( selectedIds )
335 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
336 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
337 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
342 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
343 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
346 std::unique_ptr< QgsLine3DSymbol > mSymbol;
351 QgsLineVertexData outNormal;
352 QgsLineVertexData outSelected;
357 bool QgsThickLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
359 Q_UNUSED( attributeNames )
361 outNormal.withAdjacency =
true;
362 outSelected.withAdjacency =
true;
363 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
364 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
369 void QgsThickLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
375 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
379 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
381 out.addLineString( *ls );
383 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
385 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
388 out.addLineString( *ls );
393 void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
396 makeEntity( parent, context, outNormal,
false );
397 makeEntity( parent, context, outSelected,
true );
399 updateZRangeFromPositions( outNormal.vertices );
400 updateZRangeFromPositions( outSelected.vertices );
404 void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
406 if ( out.indexes.isEmpty() )
420 if ( QgsLineMaterial *lineMaterial =
dynamic_cast< QgsLineMaterial *
>( mat ) )
421 lineMaterial->setLineWidth( mSymbol->width() );
423 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
426 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
427 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
428 renderer->setGeometry( out.createGeometry( entity ) );
429 renderer->setVertexCount( out.indexes.count() );
430 renderer->setPrimitiveRestartEnabled(
true );
431 renderer->setRestartIndexValue( 0 );
434 entity->addComponent( renderer );
435 entity->addComponent( mat );
436 entity->setParent( parent );
443 namespace Qgs3DSymbolImpl
461 QgsFeature3DHandler *handler = handlerForLine3DSymbol( layer, &symbol );
462 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
static void clampAltitudes(QgsLineString *lineString, Qgs3DTypes::AltitudeClamping altClamp, Qgs3DTypes::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.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
A geometry is the spatial representation of a feature.
JoinStyle
Join styles for buffers.
@ JoinStyleRound
Use rounded joins.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
EndCapStyle
End cap styles for buffers.
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)
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(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
static Type flatType(Type 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)
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features