QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsrubberband3d.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrubberband3d.cpp
3 --------------------------------------
4 Date : June 2021
5 Copyright : (C) 2021 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsrubberband3d.h"
17
20#include "qgsmarkersymbol.h"
21#include "qgswindow3dengine.h"
22#include "qgslinevertexdata_p.h"
23#include "qgslinematerial_p.h"
24#include "qgsvertexid.h"
25#include "qgslinestring.h"
26#include "qgssymbollayer.h"
27
28#include <Qt3DCore/QEntity>
29
30#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
31#include <Qt3DRender/QAttribute>
32#include <Qt3DRender/QBuffer>
33#include <Qt3DRender/QGeometry>
34#else
35#include <Qt3DCore/QAttribute>
36#include <Qt3DCore/QBuffer>
37#include <Qt3DCore/QGeometry>
38#endif
39
40#include <Qt3DRender/QGeometryRenderer>
41#include <Qt3DRender/QMaterial>
42#include <QColor>
43
44
46
47
48QgsRubberBand3D::QgsRubberBand3D( Qgs3DMapSettings &map, QgsWindow3DEngine *engine, Qt3DCore::QEntity *parentEntity )
49{
50 mMapSettings = &map;
51 mEngine = engine;
52
53 // Rubberband line
54 mLineEntity = new Qt3DCore::QEntity( parentEntity );
55
56 QgsLineVertexData dummyLineData;
57 mGeometry = dummyLineData.createGeometry( mLineEntity );
58
59 Q_ASSERT( mGeometry->attributes().count() == 2 );
60 mPositionAttribute = mGeometry->attributes()[0];
61 mIndexAttribute = mGeometry->attributes()[1];
62
63 mGeomRenderer = new Qt3DRender::QGeometryRenderer;
64 mGeomRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
65 mGeomRenderer->setGeometry( mGeometry );
66 mGeomRenderer->setPrimitiveRestartEnabled( true );
67 mGeomRenderer->setRestartIndexValue( 0 );
68
69 mLineEntity->addComponent( mGeomRenderer );
70
71 mLineMaterial = new QgsLineMaterial;
72 mLineMaterial->setLineWidth( 3 );
73 mLineMaterial->setLineColor( Qt::red );
74
75 QObject::connect( engine, &QgsAbstract3DEngine::sizeChanged, mLineMaterial, [this, engine]
76 {
77 mLineMaterial->setViewportSize( engine->size() );
78 } );
79 mLineMaterial->setViewportSize( engine->size() );
80
81 mLineEntity->addComponent( mLineMaterial );
82
83 // Rubberband vertex markers
84 mMarkerEntity = new Qt3DCore::QEntity( parentEntity );
85 mMarkerGeometry = new QgsBillboardGeometry();
86 mMarkerGeometryRenderer = new Qt3DRender::QGeometryRenderer;
87 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
88 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
89 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
90
91 const QVariantMap props
92 {
93 {QStringLiteral( "color" ), QStringLiteral( "red" ) },
94 {QStringLiteral( "size" ), 6 },
95 {QStringLiteral( "outline_color" ), QStringLiteral( "green" ) },
96 {QStringLiteral( "outline_width" ), 0.5 }
97 };
98
99 mMarkerSymbol = QgsMarkerSymbol::createSimple( props );
100 updateMarkerMaterial();
101 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
102}
103
104QgsRubberBand3D::~QgsRubberBand3D()
105{
106 delete mLineEntity;
107 delete mMarkerEntity;
108 delete mMarkerSymbol;
109}
110
111float QgsRubberBand3D::width() const
112{
113 return mLineMaterial->lineWidth();
114}
115
116void QgsRubberBand3D::setWidth( float width )
117{
118 mLineMaterial->setLineWidth( width );
119 mMarkerSymbol->setSize( width );
120 updateMarkerMaterial();
121}
122
123QColor QgsRubberBand3D::color() const
124{
125 return mLineMaterial->lineColor();
126}
127
128void QgsRubberBand3D::setColor( QColor color )
129{
130 mLineMaterial->setLineColor( color );
131 mMarkerSymbol->setColor( color.lighter( 130 ) );
132 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String( "SimpleMarker" ) )
133 {
134 static_cast<QgsMarkerSymbolLayer *>( mMarkerSymbol->symbolLayer( 0 ) )->setStrokeColor( color );
135 }
136 updateMarkerMaterial();
137}
138
139void QgsRubberBand3D::reset()
140{
141 mLineString.clear();
142 mShowLastMarker = false;
143 updateGeometry();
144}
145
146void QgsRubberBand3D::addPoint( const QgsPoint &pt )
147{
148 mLineString.addVertex( pt );
149 updateGeometry();
150}
151
152void QgsRubberBand3D::removeLastPoint()
153{
154 const int lastVertexIndex = mLineString.numPoints() - 1;
155 mLineString.deleteVertex( QgsVertexId( 0, 0, lastVertexIndex ) );
156 updateGeometry();
157}
158
159void QgsRubberBand3D::moveLastPoint( const QgsPoint &pt )
160{
161 const int lastVertexIndex = mLineString.numPoints() - 1;
162 mLineString.moveVertex( QgsVertexId( 0, 0, lastVertexIndex ), pt );
163 updateGeometry();
164}
165
166void QgsRubberBand3D::updateGeometry()
167{
168 QgsLineVertexData lineData;
169 lineData.withAdjacency = true;
170 lineData.init( Qgis::AltitudeClamping::Absolute, Qgis::AltitudeBinding::Vertex, 0, mMapSettings );
171 lineData.addLineString( mLineString );
172
173 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
174 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
175 mGeomRenderer->setVertexCount( lineData.indexes.count() );
176
177 // first entry is empty for primitive restart
178 lineData.vertices.pop_front();
179
180 // we may not want a marker on the last point as it's tracked by the mouse cursor
181 if ( !mShowLastMarker && !lineData.vertices.isEmpty() )
182 lineData.vertices.pop_back();
183
184 mMarkerGeometry->setPoints( lineData.vertices );
185 mMarkerGeometryRenderer->setVertexCount( lineData.vertices.count() );
186}
187
188void QgsRubberBand3D::updateMarkerMaterial()
189{
190 delete mMarkerMaterial;
191 mMarkerMaterial = new QgsPoint3DBillboardMaterial();
192 mMarkerMaterial->setTexture2DFromSymbol( mMarkerSymbol, *mMapSettings );
193 mMarkerEntity->addComponent( mMarkerMaterial );
194
195 //TODO: QgsAbstract3DEngine::sizeChanged should have const QSize &size param
196 QObject::connect( mEngine, &QgsAbstract3DEngine::sizeChanged, mMarkerMaterial, [this]
197 {
198 mMarkerMaterial->setViewportSize( mEngine->size() );
199 } );
200 mMarkerMaterial->setViewportSize( mEngine->size() );
201}
@ Absolute
Elevation is taken directly from feature and is independent of terrain height (final elevation = feat...
@ Vertex
Clamp every vertex of feature.
void sizeChanged()
Emitted after a call to setSize()
Abstract base class for marker symbol layers.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
QSize size() const override
Returns size of the engine's rendering area in pixels.
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30