QGIS API Documentation 3.29.0-Master (19d7edcfed)
qgsvectorlayerelevationproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectorlayerelevationproperties.cpp
3 ---------------
4 begin : February 2022
5 copyright : (C) 2022 by Nyall Dawson
6 email : nyall dot dawson dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgslinesymbol.h"
20#include "qgsfillsymbol.h"
21#include "qgsmarkersymbol.h"
22#include "qgssymbollayerutils.h"
23#include "qgslinesymbollayer.h"
24#include "qgsfillsymbollayer.h"
26#include "qgsapplication.h"
28#include "qgsvectorlayer.h"
29
32{
34 setDefaultProfileLineSymbol( color );
35 setDefaultProfileFillSymbol( color );
36 setDefaultProfileMarkerSymbol( color );
37}
38
40
42{
43 // layer is always considered as having elevation -- even if no z values are present or any
44 // offset/extrusion etc is set, then we are still considering the features as sitting on the terrain
45 // height
46 return true;
47}
48
49QDomElement QgsVectorLayerElevationProperties::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context )
50{
51 QDomElement element = document.createElement( QStringLiteral( "elevation" ) );
52 writeCommonProperties( element, document, context );
53
54 element.setAttribute( QStringLiteral( "extrusionEnabled" ), mEnableExtrusion ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
55 element.setAttribute( QStringLiteral( "extrusion" ), qgsDoubleToString( mExtrusionHeight ) );
56 element.setAttribute( QStringLiteral( "clamping" ), qgsEnumValueToKey( mClamping ) );
57 element.setAttribute( QStringLiteral( "binding" ), qgsEnumValueToKey( mBinding ) );
58 element.setAttribute( QStringLiteral( "type" ), qgsEnumValueToKey( mType ) );
59 element.setAttribute( QStringLiteral( "symbology" ), qgsEnumValueToKey( mSymbology ) );
60 element.setAttribute( QStringLiteral( "respectLayerSymbol" ), mRespectLayerSymbology ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
61 element.setAttribute( QStringLiteral( "showMarkerSymbolInSurfacePlots" ), mShowMarkerSymbolInSurfacePlots ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
62
63 QDomElement profileLineSymbolElement = document.createElement( QStringLiteral( "profileLineSymbol" ) );
64 profileLineSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileLineSymbol.get(), document, context ) );
65 element.appendChild( profileLineSymbolElement );
66
67 QDomElement profileFillSymbolElement = document.createElement( QStringLiteral( "profileFillSymbol" ) );
68 profileFillSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileFillSymbol.get(), document, context ) );
69 element.appendChild( profileFillSymbolElement );
70
71 QDomElement profileMarkerSymbolElement = document.createElement( QStringLiteral( "profileMarkerSymbol" ) );
72 profileMarkerSymbolElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QString(), mProfileMarkerSymbol.get(), document, context ) );
73 element.appendChild( profileMarkerSymbolElement );
74
75 parentElement.appendChild( element );
76 return element;
77}
78
79bool QgsVectorLayerElevationProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
80{
81 const QDomElement elevationElement = element.firstChildElement( QStringLiteral( "elevation" ) ).toElement();
82 if ( elevationElement.isNull() )
83 return false;
84
85 readCommonProperties( elevationElement, context );
86
87 mClamping = qgsEnumKeyToValue( elevationElement.attribute( QStringLiteral( "clamping" ) ), Qgis::AltitudeClamping::Terrain );
88 mBinding = qgsEnumKeyToValue( elevationElement.attribute( QStringLiteral( "binding" ) ), Qgis::AltitudeBinding::Centroid );
89 mType = qgsEnumKeyToValue( elevationElement.attribute( QStringLiteral( "type" ) ), Qgis::VectorProfileType::IndividualFeatures );
90 mEnableExtrusion = elevationElement.attribute( QStringLiteral( "extrusionEnabled" ), QStringLiteral( "0" ) ).toInt();
91 mExtrusionHeight = elevationElement.attribute( QStringLiteral( "extrusion" ), QStringLiteral( "0" ) ).toDouble();
92 mSymbology = qgsEnumKeyToValue( elevationElement.attribute( QStringLiteral( "symbology" ) ), Qgis::ProfileSurfaceSymbology::Line );
93 mShowMarkerSymbolInSurfacePlots = elevationElement.attribute( QStringLiteral( "showMarkerSymbolInSurfacePlots" ), QStringLiteral( "0" ) ).toInt();
94
95 mRespectLayerSymbology = elevationElement.attribute( QStringLiteral( "respectLayerSymbol" ), QStringLiteral( "1" ) ).toInt();
96
98
99 const QDomElement profileLineSymbolElement = elevationElement.firstChildElement( QStringLiteral( "profileLineSymbol" ) ).firstChildElement( QStringLiteral( "symbol" ) );
100 mProfileLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsLineSymbol >( profileLineSymbolElement, context ) );
101 if ( !mProfileLineSymbol )
102 setDefaultProfileLineSymbol( color );
103
104 const QDomElement profileFillSymbolElement = elevationElement.firstChildElement( QStringLiteral( "profileFillSymbol" ) ).firstChildElement( QStringLiteral( "symbol" ) );
105 mProfileFillSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( profileFillSymbolElement, context ) );
106 if ( !mProfileFillSymbol )
107 setDefaultProfileFillSymbol( color );
108
109 const QDomElement profileMarkerSymbolElement = elevationElement.firstChildElement( QStringLiteral( "profileMarkerSymbol" ) ).firstChildElement( QStringLiteral( "symbol" ) );
110 mProfileMarkerSymbol.reset( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( profileMarkerSymbolElement, context ) );
111 if ( !mProfileMarkerSymbol )
112 setDefaultProfileMarkerSymbol( color );
113
114 return true;
115}
116
118{
119 QgsVectorLayer *vlayer = qobject_cast< QgsVectorLayer * >( layer );
120 if ( !vlayer )
121 return;
122
123 mZOffset = 0;
124 mZScale = 1;
125
126 mEnableExtrusion = false;
127 mExtrusionHeight = 0;
128
130
132
133 if ( QgsWkbTypes::hasZ( vlayer->wkbType() ) )
134 {
136 }
137 else
138 {
140 }
141}
142
144{
145 std::unique_ptr< QgsVectorLayerElevationProperties > res = std::make_unique< QgsVectorLayerElevationProperties >( nullptr );
146 res->setClamping( mClamping );
147 res->setBinding( mBinding );
148 res->setType( mType );
149 res->setExtrusionEnabled( mEnableExtrusion );
150 res->setExtrusionHeight( mExtrusionHeight );
151 res->setProfileLineSymbol( mProfileLineSymbol->clone() );
152 res->setProfileFillSymbol( mProfileFillSymbol->clone() );
153 res->setProfileMarkerSymbol( mProfileMarkerSymbol->clone() );
154 res->setRespectLayerSymbology( mRespectLayerSymbology );
155 res->setProfileSymbology( mSymbology );
156 res->setShowMarkerSymbolInSurfacePlots( mShowMarkerSymbolInSurfacePlots );
157 res->copyCommonProperties( this );
158 return res.release();
159}
160
162{
163 QStringList properties;
164
165 switch ( mClamping )
166 {
168 properties << tr( "Clamped to Terrain" );
169 break;
171 properties << tr( "Relative to Terrain" );
172 break;
174 properties << tr( "Absolute" );
175 break;
176 }
177
178 if ( mDataDefinedProperties.isActive( Property::ZOffset ) )
179 {
180 switch ( mDataDefinedProperties.property( Property::ZOffset ).propertyType() )
181 {
184 break;
186 properties << tr( "Offset: %1" ).arg( mDataDefinedProperties.property( Property::ZOffset ).field() );
187 break;
189 properties << tr( "Offset: %1" ).arg( mDataDefinedProperties.property( Property::ZOffset ).expressionString() );
190 break;
191 }
192 }
193 else
194 {
195 properties << tr( "Offset: %1" ).arg( mZOffset );
196 }
197
198 if ( mEnableExtrusion )
199 {
200 if ( mDataDefinedProperties.isActive( Property::ExtrusionHeight ) )
201 {
202 switch ( mDataDefinedProperties.property( Property::ExtrusionHeight ).propertyType() )
203 {
206 break;
208 properties << tr( "Extrusion: %1" ).arg( mDataDefinedProperties.property( Property::ExtrusionHeight ).field() );
209 break;
211 properties << tr( "Extrusion: %1" ).arg( mDataDefinedProperties.property( Property::ExtrusionHeight ).expressionString() );
212 break;
213 }
214 }
215 else
216 {
217 properties << tr( "Extrusion: %1" ).arg( mExtrusionHeight );
218 }
219 }
220
221 properties << tr( "Scale: %1" ).arg( mZScale );
222
223 return QStringLiteral( "<li>%1</li>" ).arg( properties.join( QLatin1String( "</li><li>" ) ) );
224}
225
227{
228 // TODO -- test actual layer z range
229 return true;
230}
231
233{
234 // TODO -- determine actual z range from layer statistics
235 return QgsDoubleRange();
236}
237
239{
240 // show by default if the features aren't just directly clamped onto the terrain with
241 // no other changes
242 return !qgsDoubleNear( mZOffset, 0 )
243 || !qgsDoubleNear( mZScale, 1 )
244 || mEnableExtrusion
245 || mClamping != Qgis::AltitudeClamping::Terrain;
246}
247
249{
250 if ( mClamping == clamping )
251 return;
252
253 mClamping = clamping;
254 emit changed();
256}
257
259{
260 if ( mBinding == binding )
261 return;
262
263 mBinding = binding;
264 emit changed();
266}
267
269{
270 if ( type == mType )
271 return;
272
273 mType = type;
274 emit changed();
276}
277
279{
280 if ( mEnableExtrusion == enabled )
281 return;
282
283 mEnableExtrusion = enabled;
284 emit changed();
286}
287
289{
290 if ( mExtrusionHeight == height )
291 return;
292
293 mExtrusionHeight = height;
294 emit changed();
296}
297
299{
300 if ( mRespectLayerSymbology == enabled )
301 return;
302
303 mRespectLayerSymbology = enabled;
304 emit changed();
306}
307
309{
310 return mProfileLineSymbol.get();
311}
312
314{
315 mProfileLineSymbol.reset( symbol );
316 emit changed();
318}
319
321{
322 return mProfileFillSymbol.get();
323}
324
326{
327 mProfileFillSymbol.reset( symbol );
328 emit changed();
330}
331
333{
334 return mProfileMarkerSymbol.get();
335}
336
338{
339 mProfileMarkerSymbol.reset( symbol );
340 emit changed();
342}
343
345{
346 if ( mSymbology == symbology )
347 return;
348
349 mSymbology = symbology;
350 emit changed();
352}
353
355{
356 if ( show == mShowMarkerSymbolInSurfacePlots )
357 return;
358
359 mShowMarkerSymbolInSurfacePlots = show;
360 emit changed();
362}
363
364void QgsVectorLayerElevationProperties::setDefaultProfileLineSymbol( const QColor &color )
365{
366 std::unique_ptr< QgsSimpleLineSymbolLayer > profileLineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( color, 0.6 );
367 mProfileLineSymbol = std::make_unique< QgsLineSymbol>( QgsSymbolLayerList( { profileLineLayer.release() } ) );
368}
369
370void QgsVectorLayerElevationProperties::setDefaultProfileMarkerSymbol( const QColor &color )
371{
372 std::unique_ptr< QgsSimpleMarkerSymbolLayer > profileMarkerLayer = std::make_unique< QgsSimpleMarkerSymbolLayer >( Qgis::MarkerShape::Diamond, 3 );
373 profileMarkerLayer->setColor( color );
374 profileMarkerLayer->setStrokeWidth( 0.2 );
375 profileMarkerLayer->setStrokeColor( color.darker( 140 ) );
376 mProfileMarkerSymbol = std::make_unique< QgsMarkerSymbol>( QgsSymbolLayerList( { profileMarkerLayer.release() } ) );
377}
378
379void QgsVectorLayerElevationProperties::setDefaultProfileFillSymbol( const QColor &color )
380{
381 std::unique_ptr< QgsSimpleFillSymbolLayer > profileFillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( color );
382 profileFillLayer->setStrokeWidth( 0.2 );
383 profileFillLayer->setStrokeColor( color.darker( 140 ) );
384 mProfileFillSymbol = std::make_unique< QgsFillSymbol>( QgsSymbolLayerList( { profileFillLayer.release() } ) );
385}
AltitudeClamping
Altitude clamping.
Definition: qgis.h:2189
@ Relative
Elevation is relative to terrain height (final elevation = terrain elevation + feature elevation)
@ Terrain
Elevation is clamped to terrain (final elevation = terrain elevation)
@ Absolute
Elevation is taken directly from feature and is independent of terrain height (final elevation = feat...
AltitudeBinding
Altitude binding.
Definition: qgis.h:2202
@ Centroid
Clamp just centroid of feature.
VectorProfileType
Types of elevation profiles to generate for vector sources.
Definition: qgis.h:2293
@ IndividualFeatures
Treat each feature as an individual object (eg buildings)
ProfileSurfaceSymbology
Surface symbology type for elevation profile plots.
Definition: qgis.h:2281
@ Line
The elevation surface will be rendered using a line symbol.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
QColor fetchRandomStyleColor() const
Returns a random color for use with a new symbol style (e.g.
QgsRange which stores a range of double values.
Definition: qgsrange.h:203
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:30
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgslinesymbol.h:30
Base class for storage of map layer elevation properties.
QgsPropertyCollection mDataDefinedProperties
Property collection for data defined elevation settings.
void writeCommonProperties(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context)
Writes common class properties to a DOM element, to be used later with readXml().
void profileGenerationPropertyChanged()
Emitted when any of the elevation properties which relate solely to generation of elevation profiles ...
void readCommonProperties(const QDomElement &element, const QgsReadWriteContext &context)
Reads common class properties from a DOM element previously written by writeXml().
void changed()
Emitted when any of the elevation properties have changed.
void profileRenderingPropertyChanged()
Emitted when any of the elevation properties which relate solely to presentation of elevation results...
Base class for all map layer types.
Definition: qgsmaplayer.h:73
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
void clear() override
Removes all properties from the collection.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
@ ExpressionBasedProperty
Expression based property (QgsExpressionBasedProperty)
Definition: qgsproperty.h:239
@ StaticProperty
Static property (QgsStaticProperty)
Definition: qgsproperty.h:237
@ FieldBasedProperty
Field based property (QgsFieldBasedProperty)
Definition: qgsproperty.h:238
@ InvalidProperty
Invalid (not set) property.
Definition: qgsproperty.h:236
QString expressionString() const
Returns the expression used for the property value.
QString field() const
Returns the current field name the property references.
Type propertyType() const
Returns the property type.
The class is used as a container of context for various read/write operations on other objects.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Vector layer specific subclass of QgsMapLayerElevationProperties.
QString htmlSummary() const override
Returns a HTML formatted summary of the properties.
void setDefaultsFromLayer(QgsMapLayer *layer) override
Sets default properties based on sensible choices for the given map layer.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the elevation properties from a DOM element previously written by writeXml().
QgsFillSymbol * profileFillSymbol() const
Returns the symbol used to render polygons for the layer in elevation profile plots.
void setProfileFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used to render polygons for the layer in elevation profile plots.
void setExtrusionHeight(double height)
Sets the feature extrusion height.
void setShowMarkerSymbolInSurfacePlots(bool show)
Sets whehter the marker symbol should also be shown in continuous surface plots.
void setBinding(Qgis::AltitudeBinding binding)
Sets the altitude binding method, which determines how altitude is bound to individual vertices in fe...
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
Qgis::VectorProfileType type() const
Returns the type of profile the layer represents.
QgsDoubleRange calculateZRange(QgsMapLayer *layer) const override
Attempts to calculate the overall elevation or z range for the specified layer, using the settings de...
bool isVisibleInZRange(const QgsDoubleRange &range) const override
Returns true if the layer should be visible and rendered for the specified z range.
QgsLineSymbol * profileLineSymbol() const
Returns the symbol used to render lines for the layer in elevation profile plots.
void setProfileSymbology(Qgis::ProfileSurfaceSymbology symbology)
Sets the symbology option used to render the vector profile in elevation profile plots.
void setProfileMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the marker symbol used to render points for the layer in elevation profile plots.
void setExtrusionEnabled(bool enabled)
Sets whether extrusion is enabled.
void setType(Qgis::VectorProfileType type)
Sets the type of profile the layer represents.
QgsVectorLayerElevationProperties * clone() const override
Creates a clone of the properties.
Qgis::AltitudeClamping clamping() const
Returns the altitude clamping method, which dictates how feature heights are interpreted with respect...
QgsVectorLayerElevationProperties(QObject *parent)
Constructor for QgsVectorLayerElevationProperties, with the specified parent object.
bool showByDefaultInElevationProfilePlots() const override
Returns true if the layer should be visible by default in newly created elevation profile plots.
QgsMarkerSymbol * profileMarkerSymbol() const
Returns the symbol used to render points for the layer in elevation profile plots.
Qgis::AltitudeBinding binding() const
Returns the altitude binding method, which determines how altitude is bound to individual vertices in...
void setProfileLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used to render lines for the layer in elevation profile plots.
bool hasElevation() const override
Returns true if the layer has an elevation or z component.
void setRespectLayerSymbology(bool enabled)
Sets whether layer symbology should be respected when rendering elevation profile plots.
void setClamping(Qgis::AltitudeClamping clamping)
Sets the altitude clamping method, which dictates how feature heights are interpreted with respect to...
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition: qgis.h:3300
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:3016
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition: qgis.h:3281
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:3077
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition: qgssymbol.h:29