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;
118 const int nSegments = 4;
121 const double mitreLimit = 0;
125 double width = mSymbol->width();
133 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
140 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
148 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
154 void QgsBufferedLine3DSymbolHandler::processPolygon(
QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &out )
158 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
159 const uint startingTriangleIndex =
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
160 out.triangleIndexStartingIndices.append( startingTriangleIndex );
161 out.triangleIndexFids.append( fid );
162 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
166 void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
169 makeEntity( parent, context, outNormal,
false );
170 makeEntity( parent, context, outSelected,
true );
172 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
173 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
177 void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected )
179 if ( out.tessellator->dataVerticesCount() == 0 )
188 const QByteArray data( (
const char * )out.tessellator->data().constData(), out.tessellator->data().count() *
sizeof(
float ) );
189 const int nVerts = data.count() / out.tessellator->stride();
195 geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
197 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
198 renderer->setGeometry( geometry );
201 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
202 entity->addComponent( renderer );
203 entity->addComponent( mat );
204 entity->setParent( parent );
207 entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral(
"main" ) );
217 class QgsSimpleLine3DSymbolHandler :
public QgsFeature3DHandler
222 , mSelectedIds( selectedIds )
226 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
227 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
228 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
232 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
233 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
236 std::unique_ptr< QgsLine3DSymbol > mSymbol;
241 QgsLineVertexData outNormal;
242 QgsLineVertexData outSelected;
247 bool QgsSimpleLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
249 Q_UNUSED( attributeNames )
251 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
252 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
257 void QgsSimpleLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
263 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
267 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
269 out.addLineString( *ls );
271 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
273 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
276 out.addLineString( *ls );
281 void QgsSimpleLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
284 makeEntity( parent, context, outNormal,
false );
285 makeEntity( parent, context, outSelected,
true );
287 updateZRangeFromPositions( outNormal.vertices );
288 updateZRangeFromPositions( outSelected.vertices );
292 void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
294 if ( out.indexes.isEmpty() )
306 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
308 Qt3DRender::QGeometry *geom = out.createGeometry( entity );
310 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
311 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
312 renderer->setGeometry( geom );
313 renderer->setVertexCount( out.indexes.count() );
314 renderer->setPrimitiveRestartEnabled(
true );
315 renderer->setRestartIndexValue( 0 );
318 entity->addComponent( renderer );
319 entity->addComponent( mat );
320 entity->setParent( parent );
328 class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
333 , mSelectedIds( selectedIds )
337 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
338 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
339 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
344 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
345 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
348 std::unique_ptr< QgsLine3DSymbol > mSymbol;
353 QgsLineVertexData outNormal;
354 QgsLineVertexData outSelected;
359 bool QgsThickLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
361 Q_UNUSED( attributeNames )
363 outNormal.withAdjacency =
true;
364 outSelected.withAdjacency =
true;
365 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
366 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
371 void QgsThickLine3DSymbolHandler::processFeature(
const QgsFeature &f,
const Qgs3DRenderContext &context )
377 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
389 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
391 out.addLineString( *ls );
393 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
395 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
398 out.addLineString( *ls );
403 void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
406 makeEntity( parent, context, outNormal,
false );
407 makeEntity( parent, context, outSelected,
true );
409 updateZRangeFromPositions( outNormal.vertices );
410 updateZRangeFromPositions( outSelected.vertices );
414 void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
416 if ( out.indexes.isEmpty() )
430 if ( QgsLineMaterial *lineMaterial =
dynamic_cast< QgsLineMaterial *
>( mat ) )
431 lineMaterial->setLineWidth( mSymbol->width() );
433 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
436 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
437 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
438 renderer->setGeometry( out.createGeometry( entity ) );
439 renderer->setVertexCount( out.indexes.count() );
440 renderer->setPrimitiveRestartEnabled(
true );
441 renderer->setRestartIndexValue( 0 );
444 entity->addComponent( renderer );
445 entity->addComponent( mat );
446 entity->setParent( parent );
453 namespace Qgs3DSymbolImpl
471 QgsFeature3DHandler *handler = handlerForLine3DSymbol( layer, &symbol );
472 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
JoinStyle
Join styles for buffers.
EndCapStyle
End cap styles for buffers.
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.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const SIP_HOLDGIL
Returns a reference to the simplest lossless representation of this geometry, e.g.
QgsWkbTypes::Type 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)
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