23 #include <Qt3DCore/QTransform> 24 #include <Qt3DExtras/QPhongMaterial> 25 #include <Qt3DRender/QEffect> 26 #include <Qt3DRender/QTechnique> 27 #include <Qt3DRender/QCullFace> 28 #include <Qt3DRender/QGeometryRenderer> 40 class QgsPolygon3DSymbolHandler :
public QgsFeature3DHandler
44 : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
46 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
47 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
48 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
55 QList<QgsPolygon *> polygons;
56 QList<QgsFeatureId> fids;
57 QList<float> extrusionHeightPerPolygon;
60 void processPolygon(
QgsPolygon *polyClone,
QgsFeatureId fid,
float height,
bool hasDDExtrusion,
float extrusionHeight,
const Qgs3DRenderContext &context, PolygonData &out );
61 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PolygonData &out,
bool selected );
70 PolygonData outNormal;
71 PolygonData outSelected;
73 QgsLineVertexData outEdges;
77 bool QgsPolygon3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
79 outEdges.withAdjacency =
true;
80 outEdges.init( mSymbol.altitudeClamping(), mSymbol.altitudeBinding(), mSymbol.height(), &context.map() );
83 attributeNames.unite( attrs );
87 void QgsPolygon3DSymbolHandler::processPolygon(
QgsPolygon *polyClone,
QgsFeatureId fid,
float height,
bool hasDDExtrusion,
float extrusionHeight,
const Qgs3DRenderContext &context, PolygonData &out )
89 if ( mSymbol.edgesEnabled() )
92 outEdges.addLineString( *static_cast<const QgsLineString *>( polyClone->
exteriorRing() ) );
94 outEdges.addLineString( *static_cast<const QgsLineString *>( polyClone->
interiorRing( i ) ) );
96 if ( extrusionHeight )
100 outEdges.addLineString( *exterior, extrusionHeight );
101 outEdges.addVerticalLines( *exterior, extrusionHeight );
105 outEdges.addLineString( *interior, extrusionHeight );
106 outEdges.addVerticalLines( *interior, extrusionHeight );
112 out.polygons.append( polyClone );
113 out.fids.append( fid );
114 if ( hasDDExtrusion )
115 out.extrusionHeightPerPolygon.append( extrusionHeight );
118 void QgsPolygon3DSymbolHandler::processFeature(
QgsFeature &f,
const Qgs3DRenderContext &context )
123 PolygonData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
137 float height = mSymbol.height();
138 float extrusionHeight = mSymbol.extrusionHeight();
141 if ( hasDDExtrusion )
144 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon *>( g ) )
147 processPolygon( polyClone, f.
id(), height, hasDDExtrusion, extrusionHeight, context, out );
149 else if (
const QgsMultiPolygon *mpoly = qgsgeometry_cast< const QgsMultiPolygon *>( g ) )
151 for (
int i = 0; i < mpoly->numGeometries(); ++i )
156 processPolygon( polyClone, f.
id(), height, hasDDExtrusion, extrusionHeight, context, out );
161 for (
int i = 0; i < gc->numGeometries(); ++i )
167 processPolygon( polyClone, f.
id(), height, hasDDExtrusion, extrusionHeight, context, out );
172 qDebug() <<
"not a polygon";
176 void QgsPolygon3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
179 makeEntity( parent, context, outNormal,
false );
180 makeEntity( parent, context, outSelected,
true );
183 if ( mSymbol.edgesEnabled() && !outEdges.indexes.isEmpty() )
185 QgsLineMaterial *mat =
new QgsLineMaterial;
186 mat->setLineColor( mSymbol.edgeColor() );
187 mat->setLineWidth( mSymbol.edgeWidth() );
189 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
192 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
193 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
194 renderer->setGeometry( outEdges.createGeometry( entity ) );
195 renderer->setVertexCount( outEdges.indexes.count() );
196 renderer->setPrimitiveRestartEnabled(
true );
197 renderer->setRestartIndexValue( 0 );
200 entity->addComponent( renderer );
201 entity->addComponent( mat );
202 entity->setParent( parent );
207 void QgsPolygon3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PolygonData &out,
bool selected )
209 if ( out.polygons.isEmpty() )
212 Qt3DExtras::QPhongMaterial *mat = material( mSymbol );
216 mat->setDiffuse( context.map().selectionColor() );
217 mat->setAmbient( context.map().selectionColor().darker() );
220 QgsPointXY origin( context.map().origin().x(), context.map().origin().y() );
223 geometry->setAddBackFaces( mSymbol.addBackFaces() );
224 geometry->setPolygons( out.polygons, out.fids, origin, mSymbol.extrusionHeight(), out.extrusionHeightPerPolygon );
226 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
227 renderer->setGeometry( geometry );
230 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
231 entity->addComponent( renderer );
232 entity->addComponent( mat );
233 entity->setParent( parent );
236 entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral(
"main" ) );
249 return Qt3DRender::QCullFace::NoCulling;
252 Qt3DExtras::QPhongMaterial *QgsPolygon3DSymbolHandler::material(
const QgsPolygon3DSymbol &symbol )
const 254 Qt3DExtras::QPhongMaterial *material =
new Qt3DExtras::QPhongMaterial;
257 auto techniques = material->effect()->techniques();
258 for (
auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit )
260 auto renderPasses = ( *tit )->renderPasses();
261 for (
auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit )
263 Qt3DRender::QCullFace *cullFace =
new Qt3DRender::QCullFace;
264 cullFace->setMode( _qt3DcullingMode( symbol.
cullingMode() ) );
265 ( *rpit )->addRenderState( cullFace );
280 namespace Qgs3DSymbolImpl
291 QgsFeature3DHandler *handler = handlerForPolygon3DSymbol( layer, symbol );
292 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
float shininess() const
Returns shininess of the surface.
QSet< QgsFeatureId > QgsFeatureIds
void setInvertNormals(bool invert)
Sets whether the normals of triangles will be inverted (useful for fixing clockwise / counter-clockwi...
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double...
QColor specular() const
Returns specular color component.
A class to represent a 2D point.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
3 3D symbol that draws polygon geometries as planar polygons, optionally extruded (with added walls)...
CullingMode
Triangle culling mode.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides...
Extrusion height (zero means no extrusion)
A geometry is the spatial representation of a feature.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Will not render anything.
QgsPhongMaterialSettings material() const
Returns material used for shading of the symbol.
3 Definition of the world
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
Will render only front faces of triangles (recommended when input data are consistent) ...
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Will render only back faces of triangles.
Will render both front and back faces of triangles.
3 Class derived from Qt3DRender::QGeometry that represents polygons tessellated into 3D geometry...
Abstract base class for all geometries.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Qgs3DTypes::CullingMode cullingMode() const
Returns front/back culling mode.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext()) const override
Returns the set of any fields referenced by the active properties from the collection.
Multi polygon geometry collection.
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Line string geometry type, with support for z-dimension and m-values.
QgsPolygon * clone() const override
Clones the geometry by performing a deep copy.
QColor ambient() const
Returns ambient color component.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
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.
QColor diffuse() const
Returns diffuse color component.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
Represents a vector layer which manages a vector based data sets.
static Type flatType(Type type)
Returns the flat type for a WKB type.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.