QGIS API Documentation 3.41.0-Master (d2aaa9c6e02)
Loading...
Searching...
No Matches
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#include "qgs3dmapsettings.h"
28
29#include <Qt3DCore/QEntity>
30
31#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
32#include <Qt3DRender/QAttribute>
33#include <Qt3DRender/QBuffer>
34#include <Qt3DRender/QGeometry>
35#else
36#include <Qt3DCore/QAttribute>
37#include <Qt3DCore/QBuffer>
38#include <Qt3DCore/QGeometry>
39#endif
40
41#include <Qt3DRender/QGeometryRenderer>
42#include <QColor>
43
44
46
47
48QgsRubberBand3D::QgsRubberBand3D( Qgs3DMapSettings &map, QgsWindow3DEngine *engine, Qt3DCore::QEntity *parentEntity, Qgis::GeometryType geometryType )
49 : mMapSettings( &map )
50 , mEngine( engine )
51 , mGeometryType( geometryType )
52{
53 if ( mGeometryType == Qgis::GeometryType::Line || mGeometryType == Qgis::GeometryType::Polygon )
54 {
55 // Rubberband line
56 mLineEntity = new Qt3DCore::QEntity( parentEntity );
57
58 QgsLineVertexData dummyLineData;
59 mGeometry = dummyLineData.createGeometry( mLineEntity );
60
61 Q_ASSERT( mGeometry->attributes().count() == 2 );
62 mPositionAttribute = mGeometry->attributes().at( 0 );
63 mIndexAttribute = mGeometry->attributes().at( 1 );
64
65 mLineGeomRenderer = new Qt3DRender::QGeometryRenderer;
66 mLineGeomRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
67 mLineGeomRenderer->setGeometry( mGeometry );
68 mLineGeomRenderer->setPrimitiveRestartEnabled( true );
69 mLineGeomRenderer->setRestartIndexValue( 0 );
70
71 mLineEntity->addComponent( mLineGeomRenderer );
72
73 mLineMaterial = new QgsLineMaterial;
74 mLineMaterial->setLineWidth( mWidth );
75 mLineMaterial->setLineColor( mColor );
76
77 QObject::connect( engine, &QgsAbstract3DEngine::sizeChanged, mLineMaterial, [this, engine] {
78 mLineMaterial->setViewportSize( engine->size() );
79 } );
80 mLineMaterial->setViewportSize( engine->size() );
81
82 mLineEntity->addComponent( mLineMaterial );
83 }
84
85 // Rubberband vertex markers
86 mMarkerEntity = new Qt3DCore::QEntity( parentEntity );
87 mMarkerGeometry = new QgsBillboardGeometry();
88 mMarkerGeometryRenderer = new Qt3DRender::QGeometryRenderer;
89 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
90 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
91 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
92
93 setMarkerType( mMarkerType );
94 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
95}
96
97QgsRubberBand3D::~QgsRubberBand3D()
98{
99 if ( mLineEntity )
100 mLineEntity->deleteLater();
101 mMarkerEntity->deleteLater();
102}
103
104float QgsRubberBand3D::width() const
105{
106 return mWidth;
107}
108
109void QgsRubberBand3D::setWidth( float width )
110{
111 mWidth = width;
112
113 if ( mGeometryType == Qgis::GeometryType::Line || mGeometryType == Qgis::GeometryType::Polygon )
114 {
115 // when highlighting lines, the vertex markers should be wider
116 mLineMaterial->setLineWidth( width );
117 width *= 3;
118 }
119
120 mMarkerSymbol->setSize( width );
121 updateMarkerMaterial();
122}
123
124QColor QgsRubberBand3D::color() const
125{
126 return mColor;
127}
128
129void QgsRubberBand3D::setColor( QColor color )
130{
131 mColor = color;
132
133 if ( mGeometryType == Qgis::GeometryType::Line || mGeometryType == Qgis::GeometryType::Polygon )
134 {
135 mLineMaterial->setLineColor( color );
136 mMarkerSymbol->setColor( color.lighter( 130 ) );
137 }
138 else
139 {
140 mMarkerSymbol->setColor( color );
141 }
142
143 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String( "SimpleMarker" ) )
144 {
145 static_cast<QgsMarkerSymbolLayer *>( mMarkerSymbol->symbolLayer( 0 ) )->setStrokeColor( color );
146 }
147 updateMarkerMaterial();
148}
149
150void QgsRubberBand3D::setMarkerType( MarkerType marker )
151{
152 mMarkerType = marker;
153
154 const bool lineOrPolygon = mGeometryType == Qgis::GeometryType::Line || mGeometryType == Qgis::GeometryType::Polygon;
155
156 const QVariantMap props {
157 { QStringLiteral( "color" ), lineOrPolygon ? mColor.lighter( 130 ).name() : mColor.name() },
158 { QStringLiteral( "size_unit" ), QStringLiteral( "pixel" ) },
159 { QStringLiteral( "size" ), QString::number( lineOrPolygon ? mWidth * 3.f : mWidth ) },
160 { QStringLiteral( "outline_color" ), mColor.name() },
161 { QStringLiteral( "outline_width" ), QString::number( lineOrPolygon ? 0.5 : 1 ) },
162 { QStringLiteral( "name" ), mMarkerType == Square ? QStringLiteral( "square" ) : QStringLiteral( "circle" ) }
163 };
164
165 mMarkerSymbol.reset( QgsMarkerSymbol::createSimple( props ) );
166 updateMarkerMaterial();
167}
168
169QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType() const
170{
171 return mMarkerType;
172}
173
174void QgsRubberBand3D::reset()
175{
176 mLineString.clear();
177 updateGeometry();
178}
179
180void QgsRubberBand3D::addPoint( const QgsPoint &pt )
181{
182 mLineString.addVertex( pt );
183 updateGeometry();
184}
185
186void QgsRubberBand3D::setPoints( const QgsLineString &points )
187{
188 mLineString = points;
189 updateGeometry();
190}
191
192void QgsRubberBand3D::removeLastPoint()
193{
194 const int lastVertexIndex = mLineString.numPoints() - 1;
195 mLineString.deleteVertex( QgsVertexId( 0, 0, lastVertexIndex ) );
196 updateGeometry();
197}
198
199void QgsRubberBand3D::moveLastPoint( const QgsPoint &pt )
200{
201 const int lastVertexIndex = mLineString.numPoints() - 1;
202 mLineString.moveVertex( QgsVertexId( 0, 0, lastVertexIndex ), pt );
203 updateGeometry();
204}
205
206void QgsRubberBand3D::updateGeometry()
207{
208 QgsLineVertexData lineData;
209 lineData.withAdjacency = true;
211 const bool closed = mGeometryType == Qgis::GeometryType::Polygon;
212 lineData.addLineString( mLineString, 0, closed );
213
214 if ( mGeometryType == Qgis::GeometryType::Line || mGeometryType == Qgis::GeometryType::Polygon )
215 {
216 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
217 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
218 mLineGeomRenderer->setVertexCount( lineData.indexes.count() );
219 }
220
221 // first entry is empty for primitive restart
222 lineData.vertices.pop_front();
223
224 // we may not want a marker on the last point as it's tracked by the mouse cursor
225 if ( mHideLastMarker && !lineData.vertices.isEmpty() )
226 lineData.vertices.pop_back();
227
228 mMarkerGeometry->setPoints( lineData.vertices );
229 mMarkerGeometryRenderer->setVertexCount( lineData.vertices.count() );
230}
231
232void QgsRubberBand3D::updateMarkerMaterial()
233{
234 mMarkerMaterial = new QgsPoint3DBillboardMaterial();
235 mMarkerMaterial->setTexture2DFromSymbol( mMarkerSymbol.get(), Qgs3DRenderContext::fromMapSettings( mMapSettings ) );
236 mMarkerEntity->addComponent( mMarkerMaterial );
237
238 //TODO: QgsAbstract3DEngine::sizeChanged should have const QSize &size param
239 QObject::connect( mEngine, &QgsAbstract3DEngine::sizeChanged, mMarkerMaterial, [this] {
240 mMarkerMaterial->setViewportSize( mEngine->size() );
241 } );
242 mMarkerMaterial->setViewportSize( mEngine->size() );
243}
@ 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.
Definition qgis.h:337
@ Polygon
Polygons.
@ 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()
Line string geometry type, with support for z-dimension and m-values.
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