38#include <Qt3DCore/QAttribute>
39#include <Qt3DCore/QBuffer>
40#include <Qt3DCore/QEntity>
41#include <Qt3DCore/QGeometry>
42#include <Qt3DRender/QGeometryRenderer>
44using namespace Qt::StringLiterals;
50 : mMapSettings( &map )
52 , mGeometryType( geometryType )
54 switch ( mGeometryType )
57 setupMarker( parentEntity );
60 setupLine( parentEntity );
61 setupMarker( parentEntity );
64 setupMarker( parentEntity );
65 setupLine( parentEntity );
66 setupPolygon( parentEntity );
70 QgsDebugError(
"Unknown GeometryType used in QgsRubberband3D" );
75void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
77 mMarkerEntity.reset(
new Qt3DCore::QEntity( parentEntity ) );
79 mMarkerGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
80 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
81 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
82 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
84 setMarkerType( mMarkerType );
85 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
87 mMarkerTransform =
new QgsGeoTransform;
88 mMarkerTransform->setOrigin( mMapSettings->origin() );
89 mMarkerEntity->addComponent( mMarkerTransform );
92void QgsRubberBand3D::setupLine( Qt3DCore::QEntity *parentEntity )
94 mLineEntity.reset(
new Qt3DCore::QEntity( parentEntity ) );
96 QgsLineVertexData dummyLineData;
97 mLineGeometry = dummyLineData.createGeometry( mLineEntity );
99 Q_ASSERT( mLineGeometry->attributes().count() == 2 );
100 mPositionAttribute = mLineGeometry->attributes().at( 0 );
101 mIndexAttribute = mLineGeometry->attributes().at( 1 );
103 mLineGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
104 mLineGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
105 mLineGeometryRenderer->setGeometry( mLineGeometry );
106 mLineGeometryRenderer->setPrimitiveRestartEnabled(
true );
107 mLineGeometryRenderer->setRestartIndexValue( 0 );
109 mLineEntity->addComponent( mLineGeometryRenderer );
111 mLineMaterial =
new QgsLineMaterial;
112 mLineMaterial->setLineWidth( mWidth );
113 mLineMaterial->setLineColor( mColor );
116 mLineMaterial->setViewportSize( mEngine->size() );
118 mLineEntity->addComponent( mLineMaterial );
120 mLineTransform =
new QgsGeoTransform;
121 mLineTransform->setOrigin( mMapSettings->origin() );
122 mLineEntity->addComponent( mLineTransform );
125void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity )
127 mPolygonEntity.reset(
new Qt3DCore::QEntity( parentEntity ) );
131 Qt3DRender::QGeometryRenderer *polygonGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
132 polygonGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
133 polygonGeometryRenderer->setGeometry( mPolygonGeometry );
134 mPolygonEntity->addComponent( polygonGeometryRenderer );
139 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
141 mPolygonEntity->addComponent( mPolygonMaterial );
143 mPolygonTransform =
new QgsGeoTransform;
144 mPolygonTransform->setOrigin( mMapSettings->origin() );
145 mPolygonEntity->addComponent( mPolygonTransform );
148void QgsRubberBand3D::removePoint(
int index )
153 const int vertexIndex = index < 0 ? lineString->
numPoints() - 1 + index : index;
163 const int vertexIndex = index < 0 ? lineString->
numPoints() + index : index;
174QgsRubberBand3D::~QgsRubberBand3D()
176 if ( mPolygonEntity )
178 mPolygonEntity.reset();
186 mMarkerEntity.reset();
191float QgsRubberBand3D::width()
const
196void QgsRubberBand3D::setWidth(
float width )
201 if ( isLineOrPolygon && mEdgesEnabled )
204 mLineMaterial->setLineWidth( width );
208 mMarkerSymbol->setSize( width );
209 updateMarkerMaterial();
212QColor QgsRubberBand3D::color()
const
217void QgsRubberBand3D::setColor(
const QColor color )
222 if ( mEdgesEnabled && isLineOrPolygon )
224 mLineMaterial->setLineColor( color );
227 if ( isLineOrPolygon )
229 mMarkerSymbol->setColor( color.lighter( 130 ) );
233 mMarkerSymbol->setColor( color );
236 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() ==
"SimpleMarker"_L1 && !mOutlineColor.value() )
238 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
240 updateMarkerMaterial();
244 if ( mPolygonMaterial )
245 mPolygonEntity->removeComponent( mPolygonMaterial );
247 if ( mPolygonFillEnabled )
252 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
254 mPolygonEntity->addComponent( mPolygonMaterial );
259QColor QgsRubberBand3D::outlineColor()
const
261 return mOutlineColor;
264void QgsRubberBand3D::setOutlineColor(
const QColor color )
266 mOutlineColor = color;
268 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() ==
"SimpleMarker"_L1 )
270 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
272 updateMarkerMaterial();
275void QgsRubberBand3D::setMarkerType(
const MarkerType marker )
277 mMarkerType = marker;
281 const QVariantMap props {
282 { u
"color"_s, lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
283 { u
"size_unit"_s, u
"pixel"_s },
284 { u
"size"_s, QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
285 { u
"outline_color"_s, mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
287 { u
"outline_width"_s, QString::number( lineOrPolygon ? 0.5 : 1 ) },
288 { u
"name"_s, mMarkerType == Square ? u
"square"_s : u
"circle"_s }
292 updateMarkerMaterial();
295QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType()
const
300void QgsRubberBand3D::setMarkerOutlineStyle(
const Qt::PenStyle style )
302 mMarkerOutlineStyle = style;
303 setMarkerType( markerType() );
306Qt::PenStyle QgsRubberBand3D::markerOutlineStyle()
const
308 return mMarkerOutlineStyle;
311void QgsRubberBand3D::setMarkersEnabled(
const bool enable )
313 mMarkerEnabled = enable;
314 updateMarkerMaterial();
317bool QgsRubberBand3D::hasMarkersEnabled()
const
319 return mMarkerEnabled;
322void QgsRubberBand3D::setEdgesEnabled(
const bool enable )
324 mEdgesEnabled = enable;
328bool QgsRubberBand3D::hasEdgesEnabled()
const
330 return mEdgesEnabled;
333void QgsRubberBand3D::setFillEnabled(
const bool enable )
335 mPolygonFillEnabled = enable;
339bool QgsRubberBand3D::hasFillEnabled()
const
341 return mPolygonFillEnabled;
344void QgsRubberBand3D::reset()
346 mGeometry.set(
nullptr );
350void QgsRubberBand3D::addPoint(
const QgsPoint &pt )
355 const int lastVertexIndex = exteriorRing->
numPoints() - 1;
367 else if ( !mGeometry.constGet() )
369 mGeometry.set(
new QgsLineString( QVector<QgsPoint> { pt } ) );
375void QgsRubberBand3D::setGeometry(
const QgsGeometry &geometry )
377 mGeometry = geometry;
378 mGeometryType = geometry.
type();
383void QgsRubberBand3D::removeLastPoint()
388void QgsRubberBand3D::removePenultimatePoint()
393void QgsRubberBand3D::moveLastPoint(
const QgsPoint &pt )
398 const int lastVertexIndex = lineString->
numPoints() - 2;
403 const int lastVertexIndex = lineString->
numPoints() - 1;
414void QgsRubberBand3D::updateGeometry()
417 const QgsBox3D box = mGeometry.constGet() ? mGeometry.constGet()->boundingBox3D() :
QgsBox3D();
420 QgsLineVertexData lineData;
421 lineData.withAdjacency =
true;
427 const int lastVertexIndex = lineString->
numPoints() - 1;
429 lineData.addLineString( *lineString, 0,
true );
433 lineData.addLineString( *lineString, 0,
false );
439 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
440 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
441 mLineGeometryRenderer->setVertexCount(
static_cast<int>( lineData.indexes.count() ) );
442 mLineTransform->setGeoTranslation( dataOrigin );
446 lineData.vertices.pop_front();
449 if ( mHideLastMarker && !lineData.vertices.isEmpty() )
450 lineData.vertices.pop_back();
452 mMarkerGeometry->setPositions( lineData.vertices );
453 mMarkerGeometryRenderer->setVertexCount(
static_cast<int>( lineData.vertices.count() ) );
454 mMarkerTransform->setGeoTranslation( dataOrigin );
461 tessellator.
setOrigin( mMapSettings->origin() );
465 if ( !tessellator.
error().isEmpty() )
470 const QByteArray vertexBuffer = tessellator.
vertexBuffer();
471 const QByteArray indexBuffer = tessellator.
indexBuffer();
475 mPolygonGeometry->setVertexBufferData( vertexBuffer, vertexCount, QVector<QgsFeatureId>(), QVector<uint>() );
476 mPolygonGeometry->setIndexBufferData( indexBuffer, indexCount );
477 mPolygonTransform->setGeoTranslation( mMapSettings->origin() );
481 mPolygonGeometry->setVertexBufferData( QByteArray(), 0, QVector<QgsFeatureId>(), QVector<uint>() );
482 mPolygonGeometry->setIndexBufferData( QByteArray(), 0 );
487void QgsRubberBand3D::updateMarkerMaterial()
489 if ( mMarkerEnabled )
491 if ( !mMarkerMaterial )
494 mMarkerEntity->addComponent( mMarkerMaterial );
500 mMarkerMaterial->setViewportSize( mEngine->size() );
502 else if ( !mMarkerEnabled && mMarkerMaterial )
504 mMarkerEntity->removeComponent( mMarkerMaterial );
505 mMarkerMaterial->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
506 mMarkerMaterial->deleteLater();
507 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.
@ 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.
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 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.
QgsMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QgsMaterial object representing the material settings.
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.
void setOutputZUp(bool zUp)
Sets whether the "up" direction should be the Z axis on output (true), otherwise the "up" direction w...
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 (true) or not (false).
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
@ Triangles
Triangle based rendering (default).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.