35#include <Qt3DCore/QEntity>
37#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
38#include <Qt3DRender/QAttribute>
39#include <Qt3DRender/QBuffer>
40#include <Qt3DRender/QGeometry>
42#include <Qt3DCore/QAttribute>
43#include <Qt3DCore/QBuffer>
44#include <Qt3DCore/QGeometry>
47#include <Qt3DRender/QGeometryRenderer>
55 : mMapSettings( &map )
57 , mGeometryType( geometryType )
59 switch ( mGeometryType )
62 setupMarker( parentEntity );
65 setupLine( parentEntity, engine );
66 setupMarker( parentEntity );
69 setupMarker( parentEntity );
70 setupLine( parentEntity, engine );
71 setupPolygon( parentEntity );
75 QgsDebugError(
"Unknown GeometryType used in QgsRubberband3D" );
80void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
82 mMarkerEntity =
new Qt3DCore::QEntity( parentEntity );
84 mMarkerGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
85 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
86 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
87 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
89 setMarkerType( mMarkerType );
90 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
93void QgsRubberBand3D::setupLine( Qt3DCore::QEntity *parentEntity,
QgsAbstract3DEngine *engine )
95 mLineEntity =
new Qt3DCore::QEntity( parentEntity );
97 QgsLineVertexData dummyLineData;
98 mLineGeometry = dummyLineData.createGeometry( mLineEntity );
100 Q_ASSERT( mLineGeometry->attributes().count() == 2 );
101 mPositionAttribute = mLineGeometry->attributes().at( 0 );
102 mIndexAttribute = mLineGeometry->attributes().at( 1 );
104 mLineGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
105 mLineGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
106 mLineGeometryRenderer->setGeometry( mLineGeometry );
107 mLineGeometryRenderer->setPrimitiveRestartEnabled(
true );
108 mLineGeometryRenderer->setRestartIndexValue( 0 );
110 mLineEntity->addComponent( mLineGeometryRenderer );
112 mLineMaterial =
new QgsLineMaterial;
113 mLineMaterial->setLineWidth( mWidth );
114 mLineMaterial->setLineColor( mColor );
117 mLineMaterial->setViewportSize( engine->
size() );
119 mLineMaterial->setViewportSize( engine->
size() );
121 mLineEntity->addComponent( mLineMaterial );
124void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity )
126 mPolygonEntity =
new Qt3DCore::QEntity( parentEntity );
130 Qt3DRender::QGeometryRenderer *polygonGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
131 polygonGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
132 polygonGeometryRenderer->setGeometry( mPolygonGeometry );
133 mPolygonEntity->addComponent( polygonGeometryRenderer );
138 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
140 mPolygonEntity->addComponent( mPolygonMaterial );
143void QgsRubberBand3D::removePoint(
int index )
145 if (
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
147 QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
148 const int vertexIndex = index < 0 ? lineString->
numPoints() - 1 + index : index;
156 else if (
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
158 const int vertexIndex = index < 0 ? lineString->
numPoints() + index : index;
169QgsRubberBand3D::~QgsRubberBand3D()
171 if ( mPolygonEntity )
172 delete mPolygonEntity;
176 delete mMarkerEntity;
180float QgsRubberBand3D::width()
const
185void QgsRubberBand3D::setWidth(
float width )
190 if ( isLineOrPolygon && mEdgesEnabled )
193 mLineMaterial->setLineWidth( width );
197 mMarkerSymbol->setSize( width );
198 updateMarkerMaterial();
201QColor QgsRubberBand3D::color()
const
206void QgsRubberBand3D::setColor(
const QColor color )
211 if ( mEdgesEnabled && isLineOrPolygon )
213 mLineMaterial->setLineColor( color );
216 if ( isLineOrPolygon )
218 mMarkerSymbol->setColor( color.lighter( 130 ) );
222 mMarkerSymbol->setColor( color );
225 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String(
"SimpleMarker" ) && !mOutlineColor.value() )
227 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
229 updateMarkerMaterial();
233 if ( mPolygonMaterial )
234 mPolygonEntity->removeComponent( mPolygonMaterial );
236 if ( mPolygonFillEnabled )
241 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
243 mPolygonEntity->addComponent( mPolygonMaterial );
248QColor QgsRubberBand3D::outlineColor()
const
250 return mOutlineColor;
253void QgsRubberBand3D::setOutlineColor(
const QColor color )
255 mOutlineColor = color;
257 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String(
"SimpleMarker" ) )
259 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
261 updateMarkerMaterial();
264void QgsRubberBand3D::setMarkerType(
const MarkerType marker )
266 mMarkerType = marker;
270 const QVariantMap props {
271 { QStringLiteral(
"color" ), lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
272 { QStringLiteral(
"size_unit" ), QStringLiteral(
"pixel" ) },
273 { QStringLiteral(
"size" ), QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
274 { QStringLiteral(
"outline_color" ), mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
276 { QStringLiteral(
"outline_width" ), QString::number( lineOrPolygon ? 0.5 : 1 ) },
277 { QStringLiteral(
"name" ), mMarkerType == Square ? QStringLiteral(
"square" ) : QStringLiteral(
"circle" ) }
281 updateMarkerMaterial();
284QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType()
const
289void QgsRubberBand3D::setMarkerOutlineStyle(
const Qt::PenStyle style )
291 mMarkerOutlineStyle = style;
292 setMarkerType( markerType() );
295Qt::PenStyle QgsRubberBand3D::markerOutlineStyle()
const
297 return mMarkerOutlineStyle;
300void QgsRubberBand3D::setMarkersEnabled(
const bool enable )
302 mMarkerEnabled = enable;
303 updateMarkerMaterial();
306bool QgsRubberBand3D::hasMarkersEnabled()
const
308 return mMarkerEnabled;
311void QgsRubberBand3D::setEdgesEnabled(
const bool enable )
313 mEdgesEnabled = enable;
317bool QgsRubberBand3D::hasEdgesEnabled()
const
319 return mEdgesEnabled;
322void QgsRubberBand3D::setFillEnabled(
const bool enable )
324 mPolygonFillEnabled = enable;
328bool QgsRubberBand3D::hasFillEnabled()
const
330 return mPolygonFillEnabled;
333void QgsRubberBand3D::reset()
335 mGeometry.set(
nullptr );
339void QgsRubberBand3D::addPoint(
const QgsPoint &pt )
341 if (
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
343 QgsLineString *exteriorRing = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
344 const int lastVertexIndex = exteriorRing->
numPoints() - 1;
347 else if (
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
356 else if ( !mGeometry.constGet() )
358 mGeometry.set(
new QgsLineString( QVector<QgsPoint> { pt } ) );
364void QgsRubberBand3D::setGeometry(
const QgsGeometry &geometry )
366 mGeometry = geometry;
367 mGeometryType = geometry.
type();
372void QgsRubberBand3D::removeLastPoint()
377void QgsRubberBand3D::removePenultimatePoint()
382void QgsRubberBand3D::moveLastPoint(
const QgsPoint &pt )
384 if (
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
386 QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
387 const int lastVertexIndex = lineString->
numPoints() - 2;
390 else if (
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
392 const int lastVertexIndex = lineString->
numPoints() - 1;
403void QgsRubberBand3D::updateGeometry()
405 QgsLineVertexData lineData;
406 lineData.withAdjacency =
true;
408 if (
const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( mGeometry.constGet() ) )
410 std::unique_ptr< QgsLineString > lineString( qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing()->clone() ) );
411 const int lastVertexIndex = lineString->
numPoints() - 1;
413 lineData.addLineString( *lineString, 0,
true );
415 else if (
const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( mGeometry.constGet() ) )
417 lineData.addLineString( *lineString, 0,
false );
423 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
424 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
425 mLineGeometryRenderer->setVertexCount( lineData.indexes.count() );
429 lineData.vertices.pop_front();
432 if ( mHideLastMarker && !lineData.vertices.isEmpty() )
433 lineData.vertices.pop_back();
435 mMarkerGeometry->setPoints( lineData.vertices );
436 mMarkerGeometryRenderer->setVertexCount( lineData.vertices.count() );
441 if (
const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( mGeometry.constGet() ) )
443 QgsTessellator tessellator( mMapSettings->origin().x(), mMapSettings->origin().y(),
true );
444 tessellator.setOutputZUp(
true );
445 tessellator.addPolygon( *polygon, 0 );
446 if ( !tessellator.error().isEmpty() )
451 const QByteArray data(
reinterpret_cast<const char *
>( tessellator.data().constData() ),
static_cast<int>( tessellator.data().count() *
sizeof(
float ) ) );
452 const int vertexCount = data.count() / tessellator.stride();
453 mPolygonGeometry->setData( data, vertexCount, QVector<QgsFeatureId>(), QVector<uint>() );
457 mPolygonGeometry->setData( QByteArray(), 0, QVector<QgsFeatureId>(), QVector<uint>() );
462void QgsRubberBand3D::updateMarkerMaterial()
464 if ( mMarkerEnabled )
468 mMarkerEntity->addComponent( mMarkerMaterial );
472 mMarkerMaterial->setViewportSize( mEngine->size() );
474 mMarkerMaterial->setViewportSize( mEngine->size() );
478 mMarkerEntity->removeComponent( mMarkerMaterial );
479 QObject::disconnect( mEngine,
nullptr, 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.
static Qgs3DRenderContext fromMapSettings(const Qgs3DMapSettings *mapSettings)
Creates an initialized Qgs3DRenderContext instance from given Qgs3DMapSettings.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
Base class for 3D engine implementation.
void sizeChanged()
Emitted after a call to setSize()
virtual QSize size() const =0
Returns size of the engine's rendering area in pixels.
Geometry of the billboard rendering for points in 3D map view.
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())
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.
@ Triangles
Triangle based rendering (default)
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.