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   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   QByteArray data( ( 
const char * )out.tessellator->data().constData(), out.tessellator->data().count() * 
sizeof( 
float ) );
 
  189   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 );
 
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.
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