QGIS API Documentation 3.39.0-Master (d85f3c2a281)
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 <Qt3DRender/QMaterial>
43#include <QColor>
44
45
47
48
49QgsRubberBand3D::QgsRubberBand3D( Qgs3DMapSettings &map, QgsWindow3DEngine *engine, Qt3DCore::QEntity *parentEntity )
50{
51 mMapSettings = &map;
52 mEngine = engine;
53
54 // Rubberband line
55 mLineEntity = new Qt3DCore::QEntity( parentEntity );
56
57 QgsLineVertexData dummyLineData;
58 mGeometry = dummyLineData.createGeometry( mLineEntity );
59
60 Q_ASSERT( mGeometry->attributes().count() == 2 );
61 mPositionAttribute = mGeometry->attributes()[0];
62 mIndexAttribute = mGeometry->attributes()[1];
63
64 mGeomRenderer = new Qt3DRender::QGeometryRenderer;
65 mGeomRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
66 mGeomRenderer->setGeometry( mGeometry );
67 mGeomRenderer->setPrimitiveRestartEnabled( true );
68 mGeomRenderer->setRestartIndexValue( 0 );
69
70 mLineEntity->addComponent( mGeomRenderer );
71
72 mLineMaterial = new QgsLineMaterial;
73 mLineMaterial->setLineWidth( 3 );
74 mLineMaterial->setLineColor( Qt::red );
75
76 QObject::connect( engine, &QgsAbstract3DEngine::sizeChanged, mLineMaterial, [this, engine]
77 {
78 mLineMaterial->setViewportSize( engine->size() );
79 } );
80 mLineMaterial->setViewportSize( engine->size() );
81
82 mLineEntity->addComponent( mLineMaterial );
83
84 // Rubberband vertex markers
85 mMarkerEntity = new Qt3DCore::QEntity( parentEntity );
86 mMarkerGeometry = new QgsBillboardGeometry();
87 mMarkerGeometryRenderer = new Qt3DRender::QGeometryRenderer;
88 mMarkerGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
89 mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
90 mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );
91
92 const QVariantMap props
93 {
94 {QStringLiteral( "color" ), QStringLiteral( "red" ) },
95 {QStringLiteral( "size" ), 6 },
96 {QStringLiteral( "outline_color" ), QStringLiteral( "green" ) },
97 {QStringLiteral( "outline_width" ), 0.5 }
98 };
99
100 mMarkerSymbol = QgsMarkerSymbol::createSimple( props );
101 updateMarkerMaterial();
102 mMarkerEntity->addComponent( mMarkerGeometryRenderer );
103}
104
105QgsRubberBand3D::~QgsRubberBand3D()
106{
107 delete mLineEntity;
108 delete mMarkerEntity;
109 delete mMarkerSymbol;
110}
111
112float QgsRubberBand3D::width() const
113{
114 return mLineMaterial->lineWidth();
115}
116
117void QgsRubberBand3D::setWidth( float width )
118{
119 mLineMaterial->setLineWidth( width );
120 mMarkerSymbol->setSize( width );
121 updateMarkerMaterial();
122}
123
124QColor QgsRubberBand3D::color() const
125{
126 return mLineMaterial->lineColor();
127}
128
129void QgsRubberBand3D::setColor( QColor color )
130{
131 mLineMaterial->setLineColor( color );
132 mMarkerSymbol->setColor( color.lighter( 130 ) );
133 if ( mMarkerSymbol->symbolLayerCount() > 0 && mMarkerSymbol->symbolLayer( 0 )->layerType() == QLatin1String( "SimpleMarker" ) )
134 {
135 static_cast<QgsMarkerSymbolLayer *>( mMarkerSymbol->symbolLayer( 0 ) )->setStrokeColor( color );
136 }
137 updateMarkerMaterial();
138}
139
140void QgsRubberBand3D::reset()
141{
142 mLineString.clear();
143 mShowLastMarker = false;
144 updateGeometry();
145}
146
147void QgsRubberBand3D::addPoint( const QgsPoint &pt )
148{
149 mLineString.addVertex( pt );
150 updateGeometry();
151}
152
153void QgsRubberBand3D::removeLastPoint()
154{
155 const int lastVertexIndex = mLineString.numPoints() - 1;
156 mLineString.deleteVertex( QgsVertexId( 0, 0, lastVertexIndex ) );
157 updateGeometry();
158}
159
160void QgsRubberBand3D::moveLastPoint( const QgsPoint &pt )
161{
162 const int lastVertexIndex = mLineString.numPoints() - 1;
163 mLineString.moveVertex( QgsVertexId( 0, 0, lastVertexIndex ), pt );
164 updateGeometry();
165}
166
167void QgsRubberBand3D::updateGeometry()
168{
169 QgsLineVertexData lineData;
170 lineData.withAdjacency = true;
172 lineData.addLineString( mLineString );
173
174 mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
175 mIndexAttribute->buffer()->setData( lineData.createIndexBuffer() );
176 mGeomRenderer->setVertexCount( lineData.indexes.count() );
177
178 // first entry is empty for primitive restart
179 lineData.vertices.pop_front();
180
181 // we may not want a marker on the last point as it's tracked by the mouse cursor
182 if ( !mShowLastMarker && !lineData.vertices.isEmpty() )
183 lineData.vertices.pop_back();
184
185 mMarkerGeometry->setPoints( lineData.vertices );
186 mMarkerGeometryRenderer->setVertexCount( lineData.vertices.count() );
187}
188
189void QgsRubberBand3D::updateMarkerMaterial()
190{
191 delete mMarkerMaterial;
192 mMarkerMaterial = new QgsPoint3DBillboardMaterial();
193 mMarkerMaterial->setTexture2DFromSymbol( mMarkerSymbol, Qgs3DRenderContext::fromMapSettings( mMapSettings ) );
194 mMarkerEntity->addComponent( mMarkerMaterial );
195
196 //TODO: QgsAbstract3DEngine::sizeChanged should have const QSize &size param
197 QObject::connect( mEngine, &QgsAbstract3DEngine::sizeChanged, mMarkerMaterial, [this]
198 {
199 mMarkerMaterial->setViewportSize( mEngine->size() );
200 } );
201 mMarkerMaterial->setViewportSize( mEngine->size() );
202}
@ Absolute
Elevation is taken directly from feature and is independent of terrain height (final elevation = feat...
@ Vertex
Clamp every vertex of feature.
static Qgs3DRenderContext fromMapSettings(const Qgs3DMapSettings *mapSettings)
Creates an initialized Qgs3DRenderContext instance from given Qgs3DMapSettings.
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