40#include <Qt3DCore/QAttribute>
41#include <Qt3DCore/QBuffer>
42#include <Qt3DCore/QEntity>
43#include <Qt3DCore/QGeometry>
44#include <Qt3DRender/QGeometryRenderer>
46using namespace Qt::StringLiterals;
52 : mMapSettings( &map )
54 , mGeometryType( geometryType )
56 switch ( mGeometryType )
59 setupMarker( parentEntity );
62 setupLine( parentEntity );
63 setupMarker( parentEntity );
66 setupMarker( parentEntity );
67 setupLine( parentEntity );
68 setupPolygon( parentEntity );
72 QgsDebugError(
"Unknown GeometryType used in QgsRubberband3D" );
77void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
79 mMarkerEntity.reset(
new Qt3DCore::QEntity( parentEntity ) );
81 mMarkerGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
82 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
83 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
84 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
86 setMarkerType( mMarkerType );
87 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
89 mMarkerTransform =
new QgsGeoTransform;
90 mMarkerTransform->setOrigin( mMapSettings->origin() );
91 mMarkerEntity->addComponent( mMarkerTransform );
94void QgsRubberBand3D::setupLine( Qt3DCore::QEntity *parentEntity )
96 mLineEntity.reset(
new Qt3DCore::QEntity( parentEntity ) );
98 QgsLineVertexData dummyLineData;
99 mLineGeometry = dummyLineData.createGeometry( mLineEntity );
101 Q_ASSERT( mLineGeometry->attributes().count() == 2 );
102 mPositionAttribute = mLineGeometry->attributes().at( 0 );
103 mIndexAttribute = mLineGeometry->attributes().at( 1 );
105 mLineGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
106 mLineGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
107 mLineGeometryRenderer->setGeometry( mLineGeometry );
108 mLineGeometryRenderer->setPrimitiveRestartEnabled(
true );
109 mLineGeometryRenderer->setRestartIndexValue( 0 );
111 mLineEntity->addComponent( mLineGeometryRenderer );
113 mLineMaterial =
new QgsLineMaterial;
114 mLineMaterial->setLineWidth( mWidth );
115 mLineMaterial->setLineColor( mColor );
118 mLineMaterial->setViewportSize( mEngine->size() );
120 mLineEntity->addComponent( mLineMaterial );
122 mLineTransform =
new QgsGeoTransform;
123 mLineTransform->setOrigin( mMapSettings->origin() );
124 mLineEntity->addComponent( mLineTransform );
127void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity )
129 mPolygonEntity.reset(
new Qt3DCore::QEntity( parentEntity ) );
133 Qt3DRender::QGeometryRenderer *polygonGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
134 polygonGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
135 polygonGeometryRenderer->setGeometry( mPolygonGeometry );
136 mPolygonEntity->addComponent( polygonGeometryRenderer );
141 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
144 mPolygonEntity->addComponent( mPolygonMaterial );
146 mPolygonTransform =
new QgsGeoTransform;
147 mPolygonTransform->setOrigin( mMapSettings->origin() );
148 mPolygonEntity->addComponent( mPolygonTransform );
151void QgsRubberBand3D::removePoint(
int index )
156 const int vertexIndex = index < 0 ? lineString->
numPoints() - 1 + index : index;
166 const int vertexIndex = index < 0 ? lineString->
numPoints() + index : index;
177QgsRubberBand3D::~QgsRubberBand3D()
179 if ( mPolygonEntity )
181 mPolygonEntity.reset();
189 mMarkerEntity.reset();
194float QgsRubberBand3D::width()
const
199void QgsRubberBand3D::setWidth(
float width )
204 if ( isLineOrPolygon && mEdgesEnabled )
207 mLineMaterial->setLineWidth( width );
211 mMarkerSymbol->setSize( width );
212 updateMarkerMaterial();
215QColor QgsRubberBand3D::color()
const
220void QgsRubberBand3D::setColor(
const QColor color )
225 if ( mEdgesEnabled && isLineOrPolygon )
227 mLineMaterial->setLineColor( color );
230 if ( isLineOrPolygon )
232 mMarkerSymbol->setColor( color.lighter( 130 ) );
236 mMarkerSymbol->setColor( color );
239 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() ==
"SimpleMarker"_L1 && !mOutlineColor.value() )
241 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
243 updateMarkerMaterial();
247 if ( mPolygonMaterial )
248 mPolygonEntity->removeComponent( mPolygonMaterial );
250 if ( mPolygonFillEnabled )
255 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
258 mPolygonEntity->addComponent( mPolygonMaterial );
263QColor QgsRubberBand3D::outlineColor()
const
265 return mOutlineColor;
268void QgsRubberBand3D::setOutlineColor(
const QColor color )
270 mOutlineColor = color;
272 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() ==
"SimpleMarker"_L1 )
274 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
276 updateMarkerMaterial();
279void QgsRubberBand3D::setMarkerType(
const MarkerType marker )
281 mMarkerType = marker;
285 const QVariantMap props {
286 { u
"color"_s, lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
287 { u
"size_unit"_s, u
"pixel"_s },
288 { u
"size"_s, QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
289 { u
"outline_color"_s, mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
291 { u
"outline_width"_s, QString::number( lineOrPolygon ? 0.5 : 1 ) },
292 { u
"name"_s, mMarkerType == Square ? u
"square"_s : u
"circle"_s }
296 updateMarkerMaterial();
299QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType()
const
304void QgsRubberBand3D::setMarkerOutlineStyle(
const Qt::PenStyle style )
306 mMarkerOutlineStyle = style;
307 setMarkerType( markerType() );
310Qt::PenStyle QgsRubberBand3D::markerOutlineStyle()
const
312 return mMarkerOutlineStyle;
315void QgsRubberBand3D::setMarkersEnabled(
const bool enable )
317 mMarkerEnabled = enable;
318 updateMarkerMaterial();
321bool QgsRubberBand3D::hasMarkersEnabled()
const
323 return mMarkerEnabled;
326void QgsRubberBand3D::setEdgesEnabled(
const bool enable )
328 mEdgesEnabled = enable;
332bool QgsRubberBand3D::hasEdgesEnabled()
const
334 return mEdgesEnabled;
337void QgsRubberBand3D::setFillEnabled(
const bool enable )
339 mPolygonFillEnabled = enable;
343bool QgsRubberBand3D::hasFillEnabled()
const
345 return mPolygonFillEnabled;
348void QgsRubberBand3D::reset()
350 mGeometry.set(
nullptr );
354void QgsRubberBand3D::addPoint(
const QgsPoint &pt )
359 const int lastVertexIndex = exteriorRing->
numPoints() - 1;
371 else if ( !mGeometry.constGet() )
373 mGeometry.set(
new QgsLineString( QVector<QgsPoint> { pt } ) );
379void QgsRubberBand3D::setGeometry(
const QgsGeometry &geometry )
381 mGeometry = geometry;
382 mGeometryType = geometry.
type();
387void QgsRubberBand3D::removeLastPoint()
392void QgsRubberBand3D::removePenultimatePoint()
397void QgsRubberBand3D::moveLastPoint(
const QgsPoint &pt )
402 const int lastVertexIndex = lineString->
numPoints() - 2;
407 const int lastVertexIndex = lineString->
numPoints() - 1;
418void QgsRubberBand3D::updateGeometry()
421 const QgsBox3D box = mGeometry.constGet() ? mGeometry.constGet()->boundingBox3D() :
QgsBox3D();
424 QgsLineVertexData lineData;
425 lineData.withAdjacency =
true;
431 const int lastVertexIndex = lineString->
numPoints() - 1;
433 lineData.addLineString( *lineString, 0,
true );
437 lineData.addLineString( *lineString, 0,
false );
443 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
444 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
445 mLineGeometryRenderer->setVertexCount(
static_cast<int>( lineData.indexes.count() ) );
446 mLineTransform->setGeoTranslation( dataOrigin );
450 lineData.vertices.pop_front();
453 if ( mHideLastMarker && !lineData.vertices.isEmpty() )
454 lineData.vertices.pop_back();
456 mMarkerGeometry->setPositions( lineData.vertices );
457 mMarkerGeometryRenderer->setVertexCount(
static_cast<int>( lineData.vertices.count() ) );
458 mMarkerTransform->setGeoTranslation( dataOrigin );
465 tessellator.
setOrigin( mMapSettings->origin() );
468 if ( !tessellator.
error().isEmpty() )
473 const QByteArray vertexBuffer = tessellator.
vertexBuffer();
474 const QByteArray indexBuffer = tessellator.
indexBuffer();
478 mPolygonGeometry->setVertexBufferData( vertexBuffer, vertexCount, QVector<QgsFeatureId>(), QVector<uint>() );
479 mPolygonGeometry->setIndexBufferData( indexBuffer, indexCount );
480 mPolygonTransform->setGeoTranslation( mMapSettings->origin() );
484 mPolygonGeometry->setVertexBufferData( QByteArray(), 0, QVector<QgsFeatureId>(), QVector<uint>() );
485 mPolygonGeometry->setIndexBufferData( QByteArray(), 0 );
490void QgsRubberBand3D::updateMarkerMaterial()
492 if ( mMarkerEnabled )
494 if ( !mMarkerMaterial )
497 mMarkerEntity->addComponent( mMarkerMaterial );
503 mMarkerMaterial->setViewportSize( mEngine->size() );
505 else if ( !mMarkerEnabled && mMarkerMaterial )
507 mMarkerEntity->removeComponent( mMarkerMaterial );
508 mMarkerMaterial->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
509 mMarkerMaterial->deleteLater();
510 mMarkerMaterial =
nullptr;
@ Absolute
Elevation is taken directly from feature and is independent of terrain height (final elevation = feat...
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
@ Vertex
Clamp every vertex of feature.
@ Triangles
Triangle based rendering (default).
@ Globe
Scene is represented as a globe using a geocentric CRS.
static Qgs3DRenderContext fromMapSettings(const Qgs3DMapSettings *mapSettings)
Creates an initialized Qgs3DRenderContext instance from given Qgs3DMapSettings.
static QgsMaterial * toMaterial(const QgsAbstractMaterialSettings *settings, Qgis::MaterialRenderingTechnique technique, const QgsMaterialContext &context)
Creates a new QgsMaterial object representing the material settings.
Base class for 3D engine implementation.
void sizeChanged()
Emitted after a call to setSize().
Geometry of the billboard rendering for points in 3D map view.
A 3-dimensional box composed of x, y, z coordinates.
QgsVector3D center() const
Returns the center of the box as a vector.
bool isNull() const
Test if the box is null (holding no spatial information).
A geometry is the spatial representation of a feature.
Line string geometry type, with support for z-dimension and m-values.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
int numPoints() const override
Returns the number of points in the curve.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Context settings for a material.
static QgsMaterialContext fromRenderContext(const Qgs3DRenderContext &context)
Constructs a material context from the settings in a 3D render context.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Basic shading material used for rendering based on the Phong shading model with three color component...
void setOpacity(double opacity)
Sets opacity of the surface.
void setDiffuse(const QColor &diffuse)
Sets diffuse color component.
void setAmbient(const QColor &ambient)
Sets ambient color component.
Material of the billboard rendering for points in 3D map view.
Point geometry type, with support for z-dimension and m-values.
static QString encodePenStyle(Qt::PenStyle style)
Qt3DRender::QGeometry subclass that represents polygons tessellated into 3D geometry.
Tessellates polygons into triangles.
void setOrigin(const QgsVector3D &origin)
Sets the origin point of the map.
QByteArray vertexBuffer() const
Returns vertex buffer for the generated points.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
int uniqueVertexCount() const
Returns unique vertex count.
QByteArray indexBuffer() const
Returns index buffer for the generated points.
QString error() const
Returns a descriptive error string if the tessellation failed.
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
void setAddNormals(bool addNormals)
Sets whether normals should be added to the output data.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
T qgsgeometry_cast(QgsAbstractGeometry *geom)
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.