QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgselevationprofile.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgselevationprofile.cpp
3 ------------------
4 Date : July 2025
5 Copyright : (C) 2025 Nyall Dawson
6 Email : nyall dot dawson 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#include "qgselevationprofile.h"
16
17#include "qgscurve.h"
18#include "qgslayertree.h"
19#include "qgslinesymbol.h"
20#include "qgsproject.h"
21#include "qgssymbollayerutils.h"
22
23#include <QString>
24
25#include "moc_qgselevationprofile.cpp"
26
27using namespace Qt::StringLiterals;
28
30 : mProject( project )
31 , mLayerTree( std::make_unique< QgsLayerTree >() )
32{
33 setupLayerTreeConnections();
34}
35
37
38QDomElement QgsElevationProfile::writeXml( QDomDocument &document, const QgsReadWriteContext &context ) const
39{
40 QDomElement profileElem = document.createElement( u"ElevationProfile"_s );
41 profileElem.setAttribute( u"name"_s, mName );
42
43 profileElem.setAttribute( u"distanceUnit"_s, qgsEnumValueToKey( mDistanceUnit ) );
44
45 profileElem.setAttribute( u"tolerance"_s, mTolerance );
46 if ( mLockAxisScales )
47 profileElem.setAttribute( u"lockAxisScales"_s, u"1"_s );
48
49 if ( mCrs.isValid() )
50 {
51 QDomElement crsElem = document.createElement( u"crs"_s );
52 mCrs.writeXml( crsElem, document );
53 profileElem.appendChild( crsElem );
54 }
55 if ( mProfileCurve )
56 {
57 QDomElement curveElem = document.createElement( u"curve"_s );
58 curveElem.appendChild( document.createTextNode( mProfileCurve->asWkt( ) ) );
59 profileElem.appendChild( curveElem );
60 }
61
62 if ( !mUseProjectLayerTree )
63 {
64 mLayerTree->writeXml( profileElem, context );
65 }
66 else
67 {
68 profileElem.setAttribute( u"useProjectLayerTree"_s, u"1"_s );
69 }
70
71 if ( mSubsectionsSymbol )
72 {
73 QDomElement subsectionsElement = document.createElement( u"subsections"_s );
74 const QDomElement symbolElement = QgsSymbolLayerUtils::saveSymbol( u"subsections"_s, mSubsectionsSymbol.get(), document, context );
75 subsectionsElement.appendChild( symbolElement );
76 profileElem.appendChild( subsectionsElement );
77 }
78
79 return profileElem;
80}
81
82bool QgsElevationProfile::readXml( const QDomElement &element, const QDomDocument &, const QgsReadWriteContext &context )
83{
84 if ( element.nodeName() != "ElevationProfile"_L1 )
85 {
86 return false;
87 }
88
89 setName( element.attribute( u"name"_s ) );
90
91 const QDomNodeList crsNodeList = element.elementsByTagName( u"crs"_s );
93 if ( !crsNodeList.isEmpty() )
94 {
95 const QDomElement crsElem = crsNodeList.at( 0 ).toElement();
96 crs.readXml( crsElem );
97 }
98 mCrs = crs;
99
100 setDistanceUnit( qgsEnumKeyToValue( element.attribute( u"distanceUnit"_s ), mCrs.mapUnits() ) );
101
102 const QDomNodeList curveNodeList = element.elementsByTagName( u"curve"_s );
103 if ( !curveNodeList.isEmpty() )
104 {
105 const QDomElement curveElem = curveNodeList.at( 0 ).toElement();
106 const QgsGeometry curve = QgsGeometry::fromWkt( curveElem.text() );
107 // clang-tidy false positive
108 // NOLINTBEGIN(bugprone-branch-clone)
109 if ( const QgsCurve *curveGeom = qgsgeometry_cast< const QgsCurve * >( curve.constGet() ) )
110 {
111 mProfileCurve.reset( curveGeom->clone() );
112 }
113 else
114 {
115 mProfileCurve.reset();
116 }
117 // NOLINTEND(bugprone-branch-clone)
118 }
119
120 mTolerance = element.attribute( u"tolerance"_s ).toDouble();
121 mLockAxisScales = element.attribute( u"lockAxisScales"_s, u"0"_s ).toInt();
122
123 setUseProjectLayerTree( element.attribute( u"useProjectLayerTree"_s, u"0"_s ).toInt() );
124 if ( !mUseProjectLayerTree )
125 {
126 const QDomElement layerTreeElem = element.firstChildElement( u"layer-tree-group"_s );
127 mLayerTree = QgsLayerTree::readXml( layerTreeElem, context );
128 setupLayerTreeConnections();
129 }
130
131 const QDomElement subsectionsElement = element.firstChildElement( u"subsections"_s );
132 const QDomElement symbolsElement = subsectionsElement.firstChildElement( u"symbol"_s );
133 if ( !symbolsElement.isNull() )
134 {
135 std::unique_ptr< QgsLineSymbol > subSectionsSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol >( symbolsElement, context );
136 if ( subSectionsSymbol )
137 {
138 setSubsectionsSymbol( subSectionsSymbol.release() );
139 }
140 }
141
142 return true;
143}
144
146{
147 mLayerTree->resolveReferences( project );
148}
149
151{
152 return QIcon();
153}
154
156{
157 return !mUseProjectLayerTree ? mLayerTree.get() : nullptr;
158}
159
161{
162 if ( mCrs == crs )
163 return;
164
165 mCrs = crs;
166 dirtyProject();
167}
168
173
175{
176 if ( curve == mProfileCurve.get() )
177 return;
178 mProfileCurve.reset( curve );
179 dirtyProject();
180}
181
183{
184 return mProfileCurve.get();
185}
186
188{
189 if ( qgsDoubleNear( tolerance, mTolerance ) )
190 return;
191
192 mTolerance = tolerance;
193 dirtyProject();
194}
195
197{
198 return mTolerance;
199}
200
202{
203 return mLockAxisScales;
204}
205
207{
208 return mDistanceUnit;
209}
210
212{
213 if ( lock == mLockAxisScales )
214 return;
215
216 mLockAxisScales = lock;
217 dirtyProject();
218}
219
221{
222 if ( mDistanceUnit == unit )
223 return;
224
225 mDistanceUnit = unit;
226 dirtyProject();
227}
228
230{
231 if ( mUseProjectLayerTree == useProjectTree )
232 return;
233
234 mUseProjectLayerTree = useProjectTree;
235 emit useProjectLayerTreeChanged( mUseProjectLayerTree );
236 dirtyProject();
237}
238
239void QgsElevationProfile::dirtyProject()
240{
241 if ( mProject )
242 mProject->setDirty();
243}
244
245void QgsElevationProfile::setupLayerTreeConnections()
246{
247 connect( mLayerTree.get(), &QgsLayerTree::layerOrderChanged, this, &QgsElevationProfile::dirtyProject );
248 connect( mLayerTree.get(), &QgsLayerTree::visibilityChanged, this, &QgsElevationProfile::dirtyProject );
249 connect( mLayerTree.get(), &QgsLayerTree::nameChanged, this, &QgsElevationProfile::dirtyProject );
250}
251
253{
254 return mSubsectionsSymbol.get();
255}
256
258{
259 if ( symbol == mSubsectionsSymbol.get() )
260 return;
261
262 mSubsectionsSymbol.reset( symbol );
263 dirtyProject();
264}
265
266void QgsElevationProfile::setName( const QString &name )
267{
268 if ( name == mName )
269 return;
270
271 mName = name;
272 dirtyProject();
273 emit nameChanged( mName );
274}
DistanceUnit
Units of distance.
Definition qgis.h:5085
Represents a coordinate reference system (CRS).
Abstract base class for curved geometry type.
Definition qgscurve.h:36
void useProjectLayerTreeChanged(bool useProjectTree)
Emitted when the use project layer tree property is changed.
void setName(const QString &name)
Sets the profile's unique name.
QgsCoordinateReferenceSystem crs() const
Returns the crs associated with the profile's map coordinates.
QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns the profiles's state encapsulated in a DOM element.
double tolerance() const
Returns the tolerance of the profile (in crs() units).
void setLockAxisScales(bool lock)
Sets whether the distance and elevation scales are locked to each other.
QgsElevationProfile(QgsProject *project)
Constructor for QgsElevationProfile.
QgsLineSymbol * subsectionsSymbol()
Returns the symbol used to draw the subsections.
void setSubsectionsSymbol(QgsLineSymbol *symbol)
Sets the symbol used to draw the subsections.
void nameChanged(const QString &newName)
Emitted when the profile is renamed.
void setDistanceUnit(Qgis::DistanceUnit unit)
Sets the distance unit used by the profile.
QgsCurve * profileCurve() const
Returns the profile curve.
void resolveReferences(const QgsProject *project)
After reading settings from XML, resolves references to any layers in a project that have been read a...
void setTolerance(double tolerance)
Sets the profile tolerance (in crs() units).
QIcon icon() const
Returns the icon to use for the elevation profile.
bool lockAxisScales() const
Returns true if the distance and elevation scales are locked to each other.
QString name() const
Returns the profile's unique name.
void setUseProjectLayerTree(bool useProjectTree)
Sets whether the profile should always use the project's layer tree.
Qgis::DistanceUnit distanceUnit() const
Returns the distance unit used by the profile.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs associated with the profile's map coordinates.
QgsLayerTree * layerTree()
Returns the layer tree used by the profile.
void setProfileCurve(QgsCurve *curve)
Sets the profile curve.
bool readXml(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context)
Sets the profiles's state from a DOM element.
~QgsElevationProfile() override
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
void nameChanged(QgsLayerTreeNode *node, QString name)
Emitted when the name of the node is changed.
void visibilityChanged(QgsLayerTreeNode *node)
Emitted when check state of a node within the tree has been changed.
Namespace with helper functions for layer tree operations.
static std::unique_ptr< QgsLayerTree > readXml(const QDomElement &element, const QgsReadWriteContext &context)
Load the layer tree from an XML element.
void layerOrderChanged()
Emitted when the layer order has changed.
A line symbol type, for rendering LineString and MultiLineString geometries.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:112
A container for the context for various read/write operations on objects.
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
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:7110
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7091
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6900
T qgsgeometry_cast(QgsAbstractGeometry *geom)