QGIS API Documentation 3.28.14-Firenze (exported)
Loading...
Searching...
No Matches
qgsabstractprofilesurfacegenerator.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsabstractprofilegenerator.cpp
3 ---------------
4 begin : March 2022
5 copyright : (C) 2022 by Nyall Dawson
6 email : nyall dot dawson at gmail 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 ***************************************************************************/
18#include "qgsprofilesnapping.h"
19#include "qgsfillsymbol.h"
20#include "qgslinesymbol.h"
21
22#include <QPainterPath>
23#include <optional>
24
25//
26// QgsAbstractProfileSurfaceResults
27//
28
30
35
40
45
47{
48 QVector<QgsGeometry> res;
49 res.reserve( mRawPoints.size() );
50 for ( const QgsPoint &point : mRawPoints )
51 res.append( QgsGeometry( point.clone() ) );
52
53 return res;
54}
55
57{
58 // TODO -- consider an index if performance is an issue
60
61 double prevDistance = std::numeric_limits< double >::max();
62 double prevElevation = 0;
63 for ( auto it = mDistanceToHeightMap.constBegin(); it != mDistanceToHeightMap.constEnd(); ++it )
64 {
65 // find segment which corresponds to the given distance along curve
66 if ( it != mDistanceToHeightMap.constBegin() && prevDistance <= point.distance() && it.key() >= point.distance() )
67 {
68 const double dx = it.key() - prevDistance;
69 const double dy = it.value() - prevElevation;
70 const double snappedZ = ( dy / dx ) * ( point.distance() - prevDistance ) + prevElevation;
71
72 if ( std::fabs( point.elevation() - snappedZ ) > context.maximumSurfaceElevationDelta )
73 return QgsProfileSnapResult();
74
75 result.snappedPoint = QgsProfilePoint( point.distance(), snappedZ );
76 break;
77 }
78
79 prevDistance = it.key();
80 prevElevation = it.value();
81 }
82 return result;
83}
84
85QVector<QgsProfileIdentifyResults> QgsAbstractProfileSurfaceResults::identify( const QgsProfilePoint &point, const QgsProfileIdentifyContext &context )
86{
87 // TODO -- consider an index if performance is an issue
88 std::optional< QgsProfileIdentifyResults > result;
89
90 double prevDistance = std::numeric_limits< double >::max();
91 double prevElevation = 0;
92 for ( auto it = mDistanceToHeightMap.constBegin(); it != mDistanceToHeightMap.constEnd(); ++it )
93 {
94 // find segment which corresponds to the given distance along curve
95 if ( it != mDistanceToHeightMap.constBegin() && prevDistance <= point.distance() && it.key() >= point.distance() )
96 {
97 const double dx = it.key() - prevDistance;
98 const double dy = it.value() - prevElevation;
99 const double snappedZ = ( dy / dx ) * ( point.distance() - prevDistance ) + prevElevation;
100
101 if ( std::fabs( point.elevation() - snappedZ ) > context.maximumSurfaceElevationDelta )
102 return {};
103
104 result = QgsProfileIdentifyResults( nullptr,
105 {
106 QVariantMap(
107 {
108 {QStringLiteral( "distance" ), point.distance() },
109 {QStringLiteral( "elevation" ), snappedZ }
110 } )
111 } );
112 break;
113 }
114
115 prevDistance = it.key();
116 prevElevation = it.value();
117 }
118 if ( result.has_value() )
119 return {result.value()};
120 else
121 return {};
122}
123
125{
126 QPainter *painter = context.renderContext().painter();
127 if ( !painter )
128 return;
129
130 const QgsScopedQPainterState painterState( painter );
131
132 painter->setBrush( Qt::NoBrush );
133 painter->setPen( Qt::NoPen );
134
135 const double minDistance = context.distanceRange().lower();
136 const double maxDistance = context.distanceRange().upper();
137 const double minZ = context.elevationRange().lower();
138 const double maxZ = context.elevationRange().upper();
139
140 const QRectF visibleRegion( minDistance, minZ, maxDistance - minDistance, maxZ - minZ );
141 QPainterPath clipPath;
142 clipPath.addPolygon( context.worldTransform().map( visibleRegion ) );
143 painter->setClipPath( clipPath, Qt::ClipOperation::IntersectClip );
144
145 switch ( symbology )
146 {
148 mLineSymbol->startRender( context.renderContext() );
149 break;
151 mFillSymbol->startRender( context.renderContext() );
152 break;
153 }
154
155 QPolygonF currentLine;
156 double prevDistance = std::numeric_limits< double >::quiet_NaN();
157 double currentPartStartDistance = 0;
158 for ( auto pointIt = mDistanceToHeightMap.constBegin(); pointIt != mDistanceToHeightMap.constEnd(); ++pointIt )
159 {
160 if ( std::isnan( pointIt.value() ) )
161 {
162 if ( currentLine.length() > 1 )
163 {
164 switch ( symbology )
165 {
167 mLineSymbol->renderPolyline( currentLine, nullptr, context.renderContext() );
168 break;
170 currentLine.append( context.worldTransform().map( QPointF( prevDistance, minZ ) ) );
171 currentLine.append( context.worldTransform().map( QPointF( currentPartStartDistance, minZ ) ) );
172 currentLine.append( currentLine.at( 0 ) );
173 mFillSymbol->renderPolygon( currentLine, nullptr, nullptr, context.renderContext() );
174 break;
175 }
176 }
177 prevDistance = pointIt.key();
178 currentLine.clear();
179 continue;
180 }
181 if ( currentLine.length() < 1 )
182 {
183 currentPartStartDistance = pointIt.key();
184 }
185 currentLine.append( context.worldTransform().map( QPointF( pointIt.key(), pointIt.value() ) ) );
186 prevDistance = pointIt.key();
187 }
188 if ( currentLine.length() > 1 )
189 {
190 switch ( symbology )
191 {
193 mLineSymbol->renderPolyline( currentLine, nullptr, context.renderContext() );
194 break;
196 currentLine.append( context.worldTransform().map( QPointF( prevDistance, minZ ) ) );
197 currentLine.append( context.worldTransform().map( QPointF( currentPartStartDistance, minZ ) ) );
198 currentLine.append( currentLine.at( 0 ) );
199 mFillSymbol->renderPolygon( currentLine, nullptr, nullptr, context.renderContext() );
200 break;
201 }
202 }
203
204 switch ( symbology )
205 {
207 mLineSymbol->stopRender( context.renderContext() );
208 break;
210 mFillSymbol->stopRender( context.renderContext() );
211 break;
212 }
213}
214
215
217{
218 const QgsAbstractProfileSurfaceGenerator *surfaceGenerator = qgis::down_cast< const QgsAbstractProfileSurfaceGenerator * >( generator );
219
220 mLineSymbol.reset( surfaceGenerator->lineSymbol()->clone() );
221 mFillSymbol.reset( surfaceGenerator->fillSymbol()->clone() );
222 symbology = surfaceGenerator->symbology();
223}
224
225//
226// QgsAbstractProfileSurfaceGenerator
227//
228
230
235
240
ProfileSurfaceSymbology
Surface symbology type for elevation profile plots.
Definition qgis.h:2019
@ Line
The elevation surface will be rendered using a line symbol.
@ FillBelow
The elevation surface will be rendered using a fill symbol below the surface level.
Abstract base class for objects which generate elevation profiles.
Abstract base class for objects which generate elevation profiles which represent a continuous surfac...
QgsLineSymbol * lineSymbol() const
Returns the line symbol to be used for rendering the results.
Qgis::ProfileSurfaceSymbology symbology() const
Returns the symbology type for rendering the results.
QgsFillSymbol * fillSymbol() const
Returns the fill symbol to be used for rendering the results.
QgsPointSequence sampledPoints() const override
Returns a list of sampled points, with their calculated elevation as the point z value.
void renderResults(QgsProfileRenderContext &context) override
Renders the results to the specified context.
void copyPropertiesFromGenerator(const QgsAbstractProfileGenerator *generator) override
Copies properties from specified generator to the results object.
QVector< QgsGeometry > asGeometries() const override
Returns a list of geometries representing the calculated elevation results.
QVector< QgsProfileIdentifyResults > identify(const QgsProfilePoint &point, const QgsProfileIdentifyContext &context) override
Identify results visible at the specified profile point.
QgsProfileSnapResult snapPoint(const QgsProfilePoint &point, const QgsProfileSnapContext &context) override
Snaps a point to the generated elevation profile.
QgsDoubleRange zRange() const override
Returns the range of the retrieved elevation values.
QMap< double, double > distanceToHeightMap() const override
Returns the map of distance (chainage) to height.
QgsRange which stores a range of double values.
Definition qgsrange.h:203
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
A geometry is the spatial representation of a feature.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
Encapsulates the context of identifying profile results.
double maximumSurfaceElevationDelta
Maximum allowed snapping delta for the elevation values when identifying a continuous elevation surfa...
Stores identify results generated by a QgsAbstractProfileResults object.
Encapsulates a point on a distance-elevation profile.
double elevation() const
Returns the elevation of the point.
double distance() const
Returns the distance of the point.
Abstract base class for storage of elevation profiles.
const QTransform & worldTransform() const
Returns the transform from world coordinates to painter coordinates.
QgsDoubleRange elevationRange() const
Returns the range of elevations to include in the render.
QgsDoubleRange distanceRange() const
Returns the range of distances to include in the render.
QgsRenderContext & renderContext()
Returns a reference to the component QgsRenderContext.
Encapsulates the context of snapping a profile point.
double maximumSurfaceElevationDelta
Maximum allowed snapping delta for the elevation values when snapping to a continuous elevation surfa...
Encapsulates results of snapping a profile point.
QgsProfilePoint snappedPoint
Snapped point.
T lower() const
Returns the lower bound of the range.
Definition qgsrange.h:66
T upper() const
Returns the upper bound of the range.
Definition qgsrange.h:73
QPainter * painter()
Returns the destination QPainter for the render operation.
Scoped object for saving and restoring a QPainter object's state.
QVector< QgsPoint > QgsPointSequence