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)
void sizeChanged()
Emitted after a call to setSize()
virtual QSize size() const =0
Returns size of the engine's rendering area in pixels.
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 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())
Adds a message to the log instance (and creates it if necessary).
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.
Point geometry type, with support for z-dimension and m-values.
static QString encodePenStyle(Qt::PenStyle style)
Class that takes care of tessellation of polygons into triangles.
@ Triangles
Triangle based rendering (default)
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.