44#include <Qt3DCore/QAttribute>
45#include <Qt3DCore/QBuffer>
46#include <Qt3DCore/QEntity>
47#include <Qt3DCore/QGeometry>
48#include <Qt3DRender/QGeometryRenderer>
50using namespace Qt::StringLiterals;
56 : mMapSettings( scene->mapSettings() )
57 , mEngine( scene->engine() )
58 , mGeometryType( geometryType )
60 Qt3DCore::QEntity *parentEntity = mEngine->frameGraph()->rubberBandRenderView().rubberBandEntity();
62 switch ( mGeometryType )
65 setupMarker( parentEntity );
68 setupLine( parentEntity );
69 setupMarker( parentEntity );
72 setupMarker( parentEntity );
73 setupLine( parentEntity );
74 setupPolygon( parentEntity );
78 QgsDebugError(
"Unknown GeometryType used in QgsRubberband3D" );
83void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
87 mMarkerGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
88 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::TriangleStrip );
89 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
90 mMarkerGeometryRenderer->setVertexCount( 4 );
91 mMarkerGeometryRenderer->setInstanceCount( 0 );
93 setMarkerType( mMarkerType );
94 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
96 mMarkerTransform =
new QgsGeoTransform;
97 mMarkerTransform->setOrigin( mMapSettings->origin() );
98 mMarkerEntity->addComponent( mMarkerTransform );
101void QgsRubberBand3D::setupLine( Qt3DCore::QEntity *parentEntity )
105 QgsLineVertexData dummyLineData;
106 mLineGeometry = dummyLineData.createGeometry( mLineEntity );
108 Q_ASSERT( mLineGeometry->attributes().count() == 5 );
109 mPointAAttribute = mLineGeometry->attributes().at( 1 );
110 mPointBAttribute = mLineGeometry->attributes().at( 2 );
111 mPointPrevAttribute = mLineGeometry->attributes().at( 3 );
112 mPointNextAttribute = mLineGeometry->attributes().at( 4 );
114 mLineGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
115 mLineGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
116 mLineGeometryRenderer->setGeometry( mLineGeometry );
117 mLineGeometryRenderer->setVertexCount( 6 );
118 mLineGeometryRenderer->setInstanceCount( 0 );
120 mLineEntity->addComponent( mLineGeometryRenderer );
122 mLineMaterial =
new QgsLineMaterial;
123 mLineMaterial->setLineWidth( mWidth );
124 mLineMaterial->setLineColor( mColor );
127 mLineMaterial->setViewportSize( mEngine->size() );
129 mLineEntity->addComponent( mLineMaterial );
131 mLineTransform =
new QgsGeoTransform;
132 mLineTransform->setOrigin( mMapSettings->origin() );
133 mLineEntity->addComponent( mLineTransform );
137 mJoinGeometry = dummyLineData.createJoinGeometry( mJoinEntity );
139 mJoinPointAAttribute = mJoinGeometry->attributes().at( 1 );
140 mJoinPointBAttribute = mJoinGeometry->attributes().at( 2 );
141 mJoinPointCAttribute = mJoinGeometry->attributes().at( 3 );
143 mJoinGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
144 mJoinGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
145 mJoinGeometryRenderer->setGeometry( mJoinGeometry );
146 mJoinGeometryRenderer->setVertexCount( 6 );
147 mJoinGeometryRenderer->setInstanceCount( 0 );
149 mJoinEntity->addComponent( mJoinGeometryRenderer );
151 mJoinMaterial =
new QgsLineMaterial( QgsLineMaterial::LinePart::Join );
152 mJoinMaterial->setLineWidth( mWidth );
153 mJoinMaterial->setLineColor( mColor );
156 mJoinMaterial->setViewportSize( mEngine->size() );
158 mJoinEntity->addComponent( mJoinMaterial );
160 mJoinTransform =
new QgsGeoTransform;
161 mJoinTransform->setOrigin( mMapSettings->origin() );
162 mJoinEntity->addComponent( mJoinTransform );
165void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity )
171 Qt3DRender::QGeometryRenderer *polygonGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
172 polygonGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
173 polygonGeometryRenderer->setGeometry( mPolygonGeometry );
174 mPolygonEntity->addComponent( polygonGeometryRenderer );
176 QColor color = mColor;
177 color.setAlphaF( DEFAULT_POLYGON_OPACITY );
178 mPolygonMaterial =
new QgsUnlitMaterial();
179 mPolygonMaterial->setColor( color );
181 mPolygonEntity->addComponent( mPolygonMaterial );
183 mPolygonTransform =
new QgsGeoTransform;
184 mPolygonTransform->setOrigin( mMapSettings->origin() );
185 mPolygonEntity->addComponent( mPolygonTransform );
188void QgsRubberBand3D::removePoint(
int index )
193 const int vertexIndex = index < 0 ? lineString->
numPoints() - 1 + index : index;
203 const int vertexIndex = index < 0 ? lineString->
numPoints() + index : index;
214QgsRubberBand3D::~QgsRubberBand3D()
216 if ( mPolygonEntity )
218 mPolygonEntity.reset();
230 mMarkerEntity.reset();
235float QgsRubberBand3D::width()
const
240void QgsRubberBand3D::setWidth(
float width )
245 if ( isLineOrPolygon && mEdgesEnabled )
248 mLineMaterial->setLineWidth( width );
249 mJoinMaterial->setLineWidth( width );
253 mMarkerSymbol->setSize( width );
254 updateMarkerMaterial();
257QColor QgsRubberBand3D::color()
const
262void QgsRubberBand3D::setColor(
const QColor color )
267 if ( mEdgesEnabled && isLineOrPolygon )
269 mLineMaterial->setLineColor( color );
270 mJoinMaterial->setLineColor( color );
273 if ( isLineOrPolygon )
275 mMarkerSymbol->setColor( color.lighter( 130 ) );
279 mMarkerSymbol->setColor( color );
282 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() ==
"SimpleMarker"_L1 && !mOutlineColor.value() )
284 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
286 updateMarkerMaterial();
290 if ( mPolygonMaterial )
291 mPolygonEntity->removeComponent( mPolygonMaterial );
293 if ( mPolygonFillEnabled )
295 QColor color = mColor;
296 color.setAlphaF( DEFAULT_POLYGON_OPACITY );
297 mPolygonMaterial =
new QgsUnlitMaterial();
298 mPolygonMaterial->setColor( color );
299 mPolygonEntity->addComponent( mPolygonMaterial );
304QColor QgsRubberBand3D::outlineColor()
const
306 return mOutlineColor;
309void QgsRubberBand3D::setOutlineColor(
const QColor color )
311 mOutlineColor = color;
313 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() ==
"SimpleMarker"_L1 )
315 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
317 updateMarkerMaterial();
320void QgsRubberBand3D::setMarkerType(
const MarkerType marker )
322 mMarkerType = marker;
326 const QVariantMap props {
327 { u
"color"_s, lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
328 { u
"size_unit"_s, u
"pixel"_s },
329 { u
"size"_s, QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
330 { u
"outline_color"_s, mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
332 { u
"outline_width"_s, QString::number( lineOrPolygon ? 0.5 : 1 ) },
333 { u
"name"_s, mMarkerType == Square ? u
"square"_s : u
"circle"_s }
337 updateMarkerMaterial();
340QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType()
const
345void QgsRubberBand3D::setMarkerOutlineStyle(
const Qt::PenStyle style )
347 mMarkerOutlineStyle = style;
348 setMarkerType( markerType() );
351Qt::PenStyle QgsRubberBand3D::markerOutlineStyle()
const
353 return mMarkerOutlineStyle;
356void QgsRubberBand3D::setMarkersEnabled(
const bool enable )
358 mMarkerEnabled = enable;
359 updateMarkerMaterial();
362bool QgsRubberBand3D::hasMarkersEnabled()
const
364 return mMarkerEnabled;
367void QgsRubberBand3D::setEdgesEnabled(
const bool enable )
369 mEdgesEnabled = enable;
373bool QgsRubberBand3D::hasEdgesEnabled()
const
375 return mEdgesEnabled;
378void QgsRubberBand3D::setFillEnabled(
const bool enable )
380 mPolygonFillEnabled = enable;
384bool QgsRubberBand3D::hasFillEnabled()
const
386 return mPolygonFillEnabled;
389void QgsRubberBand3D::reset()
391 mGeometry.set(
nullptr );
395void QgsRubberBand3D::addPoint(
const QgsPoint &pt )
400 const int lastVertexIndex = exteriorRing->
numPoints() - 1;
412 else if ( !mGeometry.constGet() )
414 mGeometry.set(
new QgsLineString( QVector<QgsPoint> { pt } ) );
420void QgsRubberBand3D::setGeometry(
const QgsGeometry &geometry )
422 mGeometry = geometry;
423 mGeometryType = geometry.
type();
428void QgsRubberBand3D::removeLastPoint()
433void QgsRubberBand3D::removePenultimatePoint()
438void QgsRubberBand3D::moveLastPoint(
const QgsPoint &pt )
443 const int lastVertexIndex = lineString->
numPoints() - 2;
448 const int lastVertexIndex = lineString->
numPoints() - 1;
459void QgsRubberBand3D::updateGeometry()
462 const QgsBox3D box = mGeometry.constGet() ? mGeometry.constGet()->boundingBox3D() :
QgsBox3D();
465 QgsLineVertexData lineData;
471 const int lastVertexIndex = lineString->
numPoints() - 1;
473 lineData.addLineString( *lineString, 0,
true );
477 lineData.addLineString( *lineString, 0,
false );
483 mPointAAttribute->buffer()->setData( lineData.createPointABuffer() );
484 mPointBAttribute->buffer()->setData( lineData.createPointBBuffer() );
485 mPointPrevAttribute->buffer()->setData( lineData.createPointPrevBuffer() );
486 mPointNextAttribute->buffer()->setData( lineData.createPointNextBuffer() );
487 mLineGeometryRenderer->setInstanceCount( lineData.pointsA.size() );
488 mLineTransform->setGeoTranslation( dataOrigin );
490 mJoinPointAAttribute->buffer()->setData( lineData.createJoinPointABuffer() );
491 mJoinPointBAttribute->buffer()->setData( lineData.createJoinPointBBuffer() );
492 mJoinPointCAttribute->buffer()->setData( lineData.createJoinPointCBuffer() );
493 mJoinGeometryRenderer->setInstanceCount( lineData.joinPointA.size() );
494 mJoinTransform->setGeoTranslation( dataOrigin );
498 if ( mHideLastMarker && !lineData.vertices.isEmpty() )
499 lineData.vertices.pop_back();
501 mMarkerGeometry->setPositions( lineData.vertices );
502 mMarkerGeometryRenderer->setVertexCount( 4 );
503 mMarkerGeometryRenderer->setInstanceCount( lineData.vertices.count() );
504 mMarkerTransform->setGeoTranslation( dataOrigin );
511 tessellator.
setOrigin( mMapSettings->origin() );
514 if ( !tessellator.
error().isEmpty() )
519 const QByteArray vertexBuffer = tessellator.
vertexBuffer();
520 const QByteArray indexBuffer = tessellator.
indexBuffer();
524 mPolygonGeometry->setVertexBufferData( vertexBuffer, vertexCount, QVector<QgsFeatureId>(), QVector<uint>() );
525 mPolygonGeometry->setIndexBufferData( indexBuffer, indexCount );
526 mPolygonTransform->setGeoTranslation( mMapSettings->origin() );
530 mPolygonGeometry->setVertexBufferData( QByteArray(), 0, QVector<QgsFeatureId>(), QVector<uint>() );
531 mPolygonGeometry->setIndexBufferData( QByteArray(), 0 );
536void QgsRubberBand3D::updateMarkerMaterial()
538 if ( mMarkerEnabled )
540 if ( !mMarkerMaterial )
543 mMarkerEntity->addComponent( mMarkerMaterial );
545 QObject::connect( mEngine, &
QgsAbstract3DEngine::sizeChanged, mMarkerMaterial, [material = mMarkerMaterial, engine = mEngine] { material->setViewportSize( engine->size() ); } );
549 mMarkerMaterial->setViewportSize( mEngine->size() );
551 else if ( !mMarkerEnabled && mMarkerMaterial )
553 mMarkerEntity->removeComponent( mMarkerMaterial );
554 mMarkerMaterial->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
555 mMarkerMaterial->deleteLater();
556 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.
Entity that encapsulates our 3D scene - contains all other entities (such as terrain) as children.
static Qgs3DRenderContext fromMapSettings(const Qgs3DMapSettings *mapSettings)
Creates an initialized Qgs3DRenderContext instance from given Qgs3DMapSettings.
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 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.
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).
Material of the billboard rendering for points in 3D map view.
Point 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.
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)
constexpr QObjectUniquePtr< Tp > make_qobject_unique(Args &&...args)
Create an object owned by a QObjectUniquePtr.
Utility class for identifying a unique vertex within a geometry.