36#include <Qt3DCore/QEntity>
38#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
39#include <Qt3DRender/QAttribute>
40#include <Qt3DRender/QBuffer>
41#include <Qt3DRender/QGeometry>
43#include <Qt3DCore/QAttribute>
44#include <Qt3DCore/QBuffer>
45#include <Qt3DCore/QGeometry>
48#include <Qt3DRender/QGeometryRenderer>
56 : mMapSettings( &map )
58 , mGeometryType( geometryType )
60 switch ( mGeometryType )
63 setupMarker( parentEntity );
66 setupLine( parentEntity, engine );
67 setupMarker( parentEntity );
70 setupMarker( parentEntity );
71 setupLine( parentEntity, engine );
72 setupPolygon( parentEntity );
76 QgsDebugError(
"Unknown GeometryType used in QgsRubberband3D" );
81void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
83 mMarkerEntity =
new Qt3DCore::QEntity( parentEntity );
85 mMarkerGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
86 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
87 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
88 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
90 setMarkerType( mMarkerType );
91 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
93 mMarkerTransform =
new QgsGeoTransform;
94 mMarkerTransform->setOrigin( mMapSettings->origin() );
95 mMarkerEntity->addComponent( mMarkerTransform );
98void QgsRubberBand3D::setupLine( Qt3DCore::QEntity *parentEntity,
QgsAbstract3DEngine *engine )
100 mLineEntity =
new Qt3DCore::QEntity( parentEntity );
102 QgsLineVertexData dummyLineData;
103 mLineGeometry = dummyLineData.createGeometry( mLineEntity );
105 Q_ASSERT( mLineGeometry->attributes().count() == 2 );
106 mPositionAttribute = mLineGeometry->attributes().at( 0 );
107 mIndexAttribute = mLineGeometry->attributes().at( 1 );
109 mLineGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
110 mLineGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
111 mLineGeometryRenderer->setGeometry( mLineGeometry );
112 mLineGeometryRenderer->setPrimitiveRestartEnabled(
true );
113 mLineGeometryRenderer->setRestartIndexValue( 0 );
115 mLineEntity->addComponent( mLineGeometryRenderer );
117 mLineMaterial =
new QgsLineMaterial;
118 mLineMaterial->setLineWidth( mWidth );
119 mLineMaterial->setLineColor( mColor );
122 mLineMaterial->setViewportSize( engine->
size() );
124 mLineMaterial->setViewportSize( engine->
size() );
126 mLineEntity->addComponent( mLineMaterial );
128 mLineTransform =
new QgsGeoTransform( mLineEntity );
129 mLineTransform->setOrigin( mMapSettings->origin() );
130 mLineEntity->addComponent( mLineTransform );
133void QgsRubberBand3D::setupPolygon( Qt3DCore::QEntity *parentEntity )
135 mPolygonEntity =
new Qt3DCore::QEntity( parentEntity );
139 Qt3DRender::QGeometryRenderer *polygonGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
140 polygonGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
141 polygonGeometryRenderer->setGeometry( mPolygonGeometry );
142 mPolygonEntity->addComponent( polygonGeometryRenderer );
147 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
149 mPolygonEntity->addComponent( mPolygonMaterial );
151 mPolygonTransform =
new QgsGeoTransform;
152 mPolygonTransform->setOrigin( mMapSettings->origin() );
153 mPolygonEntity->addComponent( mPolygonTransform );
156void QgsRubberBand3D::removePoint(
int index )
158 if (
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
160 QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
161 const int vertexIndex = index < 0 ? lineString->
numPoints() - 1 + index : index;
169 else if (
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
171 const int vertexIndex = index < 0 ? lineString->
numPoints() + index : index;
182QgsRubberBand3D::~QgsRubberBand3D()
184 if ( mPolygonEntity )
185 delete mPolygonEntity;
189 delete mMarkerEntity;
193float QgsRubberBand3D::width()
const
198void QgsRubberBand3D::setWidth(
float width )
203 if ( isLineOrPolygon && mEdgesEnabled )
206 mLineMaterial->setLineWidth( width );
210 mMarkerSymbol->setSize( width );
211 updateMarkerMaterial();
214QColor QgsRubberBand3D::color()
const
219void QgsRubberBand3D::setColor(
const QColor color )
224 if ( mEdgesEnabled && isLineOrPolygon )
226 mLineMaterial->setLineColor( color );
229 if ( isLineOrPolygon )
231 mMarkerSymbol->setColor( color.lighter( 130 ) );
235 mMarkerSymbol->setColor( color );
238 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String(
"SimpleMarker" ) && !mOutlineColor.value() )
240 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
242 updateMarkerMaterial();
246 if ( mPolygonMaterial )
247 mPolygonEntity->removeComponent( mPolygonMaterial );
249 if ( mPolygonFillEnabled )
254 polygonMaterialSettings.
setOpacity( DEFAULT_POLYGON_OPACITY );
256 mPolygonEntity->addComponent( mPolygonMaterial );
261QColor QgsRubberBand3D::outlineColor()
const
263 return mOutlineColor;
266void QgsRubberBand3D::setOutlineColor(
const QColor color )
268 mOutlineColor = color;
270 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String(
"SimpleMarker" ) )
272 mMarkerSymbol->symbolLayer( 0 )->setStrokeColor( color );
274 updateMarkerMaterial();
277void QgsRubberBand3D::setMarkerType(
const MarkerType marker )
279 mMarkerType = marker;
283 const QVariantMap props {
284 { QStringLiteral(
"color" ), lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
285 { QStringLiteral(
"size_unit" ), QStringLiteral(
"pixel" ) },
286 { QStringLiteral(
"size" ), QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
287 { QStringLiteral(
"outline_color" ), mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
289 { QStringLiteral(
"outline_width" ), QString::number( lineOrPolygon ? 0.5 : 1 ) },
290 { QStringLiteral(
"name" ), mMarkerType == Square ? QStringLiteral(
"square" ) : QStringLiteral(
"circle" ) }
294 updateMarkerMaterial();
297QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType()
const
302void QgsRubberBand3D::setMarkerOutlineStyle(
const Qt::PenStyle style )
304 mMarkerOutlineStyle = style;
305 setMarkerType( markerType() );
308Qt::PenStyle QgsRubberBand3D::markerOutlineStyle()
const
310 return mMarkerOutlineStyle;
313void QgsRubberBand3D::setMarkersEnabled(
const bool enable )
315 mMarkerEnabled = enable;
316 updateMarkerMaterial();
319bool QgsRubberBand3D::hasMarkersEnabled()
const
321 return mMarkerEnabled;
324void QgsRubberBand3D::setEdgesEnabled(
const bool enable )
326 mEdgesEnabled = enable;
330bool QgsRubberBand3D::hasEdgesEnabled()
const
332 return mEdgesEnabled;
335void QgsRubberBand3D::setFillEnabled(
const bool enable )
337 mPolygonFillEnabled = enable;
341bool QgsRubberBand3D::hasFillEnabled()
const
343 return mPolygonFillEnabled;
346void QgsRubberBand3D::reset()
348 mGeometry.set(
nullptr );
352void QgsRubberBand3D::addPoint(
const QgsPoint &pt )
354 if (
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
356 QgsLineString *exteriorRing = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
357 const int lastVertexIndex = exteriorRing->
numPoints() - 1;
360 else if (
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
369 else if ( !mGeometry.constGet() )
371 mGeometry.set(
new QgsLineString( QVector<QgsPoint> { pt } ) );
377void QgsRubberBand3D::setGeometry(
const QgsGeometry &geometry )
379 mGeometry = geometry;
380 mGeometryType = geometry.
type();
385void QgsRubberBand3D::removeLastPoint()
390void QgsRubberBand3D::removePenultimatePoint()
395void QgsRubberBand3D::moveLastPoint(
const QgsPoint &pt )
397 if (
QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometry.get() ) )
399 QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing() );
400 const int lastVertexIndex = lineString->
numPoints() - 2;
403 else if (
QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( mGeometry.get() ) )
405 const int lastVertexIndex = lineString->
numPoints() - 1;
416void QgsRubberBand3D::updateGeometry()
419 const QgsBox3D box = mGeometry.constGet()->boundingBox3D();
422 QgsLineVertexData lineData;
423 lineData.withAdjacency =
true;
426 if (
const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( mGeometry.constGet() ) )
428 std::unique_ptr< QgsLineString > lineString( qgsgeometry_cast<QgsLineString *>( polygon->exteriorRing()->clone() ) );
429 const int lastVertexIndex = lineString->
numPoints() - 1;
431 lineData.addLineString( *lineString, 0,
true );
433 else if (
const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( mGeometry.constGet() ) )
435 lineData.addLineString( *lineString, 0,
false );
441 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
442 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
443 mLineGeometryRenderer->setVertexCount( lineData.indexes.count() );
444 mLineTransform->setGeoTranslation( dataOrigin );
448 lineData.vertices.pop_front();
451 if ( mHideLastMarker && !lineData.vertices.isEmpty() )
452 lineData.vertices.pop_back();
454 mMarkerGeometry->setPoints( lineData.vertices );
455 mMarkerGeometryRenderer->setVertexCount( lineData.vertices.count() );
456 mMarkerTransform->setGeoTranslation( dataOrigin );
460 if (
const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( mGeometry.constGet() ) )
464 const QgsVector3D polygonOrigin( mMapSettings->origin().x(), mMapSettings->origin().y(), 0 );
465 QgsTessellator tessellator( polygonOrigin.x(), polygonOrigin.y(),
true );
466 tessellator.setOutputZUp(
true );
467 tessellator.addPolygon( *polygon, 0 );
468 if ( !tessellator.error().isEmpty() )
473 const QByteArray data(
reinterpret_cast<const char *
>( tessellator.data().constData() ),
static_cast<int>( tessellator.data().count() *
sizeof(
float ) ) );
474 const int vertexCount = data.count() / tessellator.stride();
475 mPolygonGeometry->setData( data, vertexCount, QVector<QgsFeatureId>(), QVector<uint>() );
476 mPolygonTransform->setGeoTranslation( polygonOrigin );
480 mPolygonGeometry->setData( QByteArray(), 0, QVector<QgsFeatureId>(), QVector<uint>() );
485void QgsRubberBand3D::updateMarkerMaterial()
487 if ( mMarkerEnabled )
491 mMarkerEntity->addComponent( mMarkerMaterial );
495 mMarkerMaterial->setViewportSize( mEngine->size() );
497 mMarkerMaterial->setViewportSize( mEngine->size() );
501 mMarkerEntity->removeComponent( mMarkerMaterial );
502 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.
@ 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()
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 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())
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.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
@ Triangles
Triangle based rendering (default)
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.