46 return QStringLiteral(
"vector" );
51 QVector<QgsGeometry> res;
55 for (
const Feature &feature : it.value() )
57 res.append( feature.geometry );
69 return asIndividualFeatures(
type, feedback );
84 return snapPointToIndividualFeatures( point, context );
100 visitFeaturesInRange( distanceRange, elevationRange, visitFeature );
104 QVector< QVariantMap> idsList;
105 for (
auto it = ids.constBegin(); it != ids.constEnd(); ++it )
106 idsList.append( QVariantMap( {{QStringLiteral(
"id" ), *it}} ) );
113 QHash< QgsFeatureId, QVariantMap >
features;
114 auto visitFeature = [&
features](
QgsFeatureId featureId,
double delta,
double distance,
double elevation )
116 auto it =
features.find( featureId );
119 features[ featureId ] = QVariantMap( {{QStringLiteral(
"id" ), featureId },
120 {QStringLiteral(
"delta" ), delta },
121 {QStringLiteral(
"distance" ), distance },
122 {QStringLiteral(
"elevation" ), elevation }
127 const double currentDelta = it.value().value( QStringLiteral(
"delta" ) ).toDouble();
128 if ( delta < currentDelta )
130 *it = QVariantMap( {{QStringLiteral(
"id" ), featureId },
131 {QStringLiteral(
"delta" ), delta },
132 {QStringLiteral(
"distance" ), distance },
133 {QStringLiteral(
"elevation" ), elevation }
141 QVector< QVariantMap> attributes;
143 attributes.append( *it );
145 QVector<QgsProfileIdentifyResults> res;
147 if ( !attributes.empty() )
153 res.reserve( surfaceResults.size() );
166 double bestSnapDistance = std::numeric_limits< double >::max();
168 auto visitFeature = [&bestSnapDistance, &res](
QgsFeatureId,
double delta,
double distance,
double elevation )
170 if ( distance < bestSnapDistance )
172 bestSnapDistance = delta;
182void QgsVectorLayerProfileResults::visitFeaturesAtPoint(
const QgsProfilePoint &point,
double maximumPointDistanceDelta,
double maximumPointElevationDelta,
double maximumSurfaceElevationDelta,
const std::function<
void(
QgsFeatureId,
double delta,
double distance,
double elevation ) > &visitor,
bool visitWithin )
190 for (
const Feature &feature : it.value() )
192 const QgsRectangle featureBounds = feature.crossSectionGeometry.boundingBox();
193 if ( ( featureBounds.
xMinimum() - maximumPointDistanceDelta <= point.
distance() ) && ( featureBounds.
xMaximum() + maximumPointDistanceDelta >= point.
distance() ) )
195 switch ( feature.crossSectionGeometry.type() )
199 for (
auto partIt = feature.crossSectionGeometry.const_parts_begin(); partIt != feature.crossSectionGeometry.const_parts_end(); ++partIt )
201 if (
const QgsPoint *candidatePoint = qgsgeometry_cast< const QgsPoint * >( *partIt ) )
203 const double snapDistanceDelta = std::fabs( point.
distance() - candidatePoint->x() );
204 if ( snapDistanceDelta > maximumPointDistanceDelta )
207 const double snapHeightDelta = std::fabs( point.
elevation() - candidatePoint->y() );
208 if ( snapHeightDelta > maximumPointElevationDelta )
211 const double snapDistance = candidatePoint->distance( targetPoint );
212 visitor( feature.featureId, snapDistance, candidatePoint->x(), candidatePoint->y() );
220 for (
auto partIt = feature.crossSectionGeometry.const_parts_begin(); partIt != feature.crossSectionGeometry.const_parts_end(); ++partIt )
222 if (
const QgsCurve *line = qgsgeometry_cast< const QgsCurve * >( *partIt ) )
225 if (
const QgsLineString *lineString = qgsgeometry_cast< const QgsLineString * >( line ) )
227 if ( lineString->numPoints() == 2 &&
qgsDoubleNear( lineString->pointN( 0 ).x(), lineString->pointN( 1 ).x() ) )
229 const double snapDistanceDelta = std::fabs( point.
distance() - lineString->pointN( 0 ).x() );
230 if ( snapDistanceDelta > maximumPointDistanceDelta )
233 const double snapHeightDelta = std::fabs( point.
elevation() - lineString->pointN( 0 ).y() );
234 if ( snapHeightDelta <= maximumPointElevationDelta )
236 const double snapDistanceP1 = lineString->pointN( 0 ).distance( targetPoint );
237 visitor( feature.featureId, snapDistanceP1, lineString->pointN( 0 ).x(), lineString->pointN( 0 ).y() );
240 const double snapHeightDelta2 = std::fabs( point.
elevation() - lineString->pointN( 1 ).y() );
241 if ( snapHeightDelta2 <= maximumPointElevationDelta )
243 const double snapDistanceP2 = lineString->pointN( 1 ).distance( targetPoint );
244 visitor( feature.featureId, snapDistanceP2, lineString->pointN( 1 ).x(), lineString->pointN( 1 ).y() );
249 double elevation1 = lineString->pointN( 0 ).y();
250 double elevation2 = lineString->pointN( 1 ).y();
251 if ( elevation1 > elevation2 )
252 std::swap( elevation1, elevation2 );
256 const double snapDistance = std::fabs( lineString->pointN( 0 ).x() - point.
distance() );
257 visitor( feature.featureId, snapDistance, lineString->pointN( 0 ).x(), point.
elevation() );
264 const QgsRectangle partBounds = ( *partIt )->boundingBox();
272 QgsGeos cutLineGeos( cutLine.constGet() );
274 const QgsGeometry points( cutLineGeos.intersection( line ) );
276 for (
auto vertexIt = points.vertices_begin(); vertexIt != points.vertices_end(); ++vertexIt )
278 const double snapHeightDelta = std::fabs( point.
elevation() - ( *vertexIt ).y() );
279 if ( snapHeightDelta > maximumSurfaceElevationDelta )
282 const double snapDistance = ( *vertexIt ).distance( targetPoint );
283 visitor( feature.featureId, snapDistance, ( *vertexIt ).x(), ( *vertexIt ).y() );
300 for (
auto partIt = feature.crossSectionGeometry.const_parts_begin(); partIt != feature.crossSectionGeometry.const_parts_end(); ++partIt )
302 if (
const QgsCurve *exterior = qgsgeometry_cast< const QgsPolygon * >( *partIt )->exteriorRing() )
304 const QgsRectangle partBounds = ( *partIt )->boundingBox();
312 QgsGeos cutLineGeos( cutLine.constGet() );
314 const QgsGeometry points( cutLineGeos.intersection( exterior ) );
315 for (
auto vertexIt = points.vertices_begin(); vertexIt != points.vertices_end(); ++vertexIt )
317 const double snapHeightDelta = std::fabs( point.
elevation() - ( *vertexIt ).y() );
318 if ( snapHeightDelta > maximumSurfaceElevationDelta )
321 const double snapDistance = ( *vertexIt ).distance( targetPoint );
322 visitor( feature.featureId, snapDistance, ( *vertexIt ).x(), ( *vertexIt ).y() );
343 profileRangeGeos.prepareGeometry();
347 for (
const Feature &feature : it.value() )
349 if ( feature.crossSectionGeometry.boundingBoxIntersects( profileRange ) )
351 switch ( feature.crossSectionGeometry.type() )
355 for (
auto partIt = feature.crossSectionGeometry.const_parts_begin(); partIt != feature.crossSectionGeometry.const_parts_end(); ++partIt )
357 if (
const QgsPoint *candidatePoint = qgsgeometry_cast< const QgsPoint * >( *partIt ) )
359 if ( profileRange.contains( candidatePoint->x(), candidatePoint->y() ) )
361 visitor( feature.featureId );
371 if ( profileRangeGeos.intersects( feature.crossSectionGeometry.constGet() ) )
373 visitor( feature.featureId );
393 renderResultsAsIndividualFeatures( context );
398 renderMarkersOverContinuousSurfacePlot( context );
411 painter->setBrush( Qt::NoBrush );
412 painter->setPen( Qt::NoPen );
419 const QRectF visibleRegion( minDistance,
minZ, maxDistance - minDistance,
maxZ -
minZ );
420 QPainterPath clipPath;
421 clipPath.addPolygon( context.
worldTransform().map( visibleRegion ) );
422 painter->setClipPath( clipPath, Qt::ClipOperation::IntersectClip );
424 const QgsRectangle clipPathRect( clipPath.boundingRect() );
428 if ( profileFeature.crossSectionGeometry.isEmpty() )
431 QgsGeometry transformed = profileFeature.crossSectionGeometry;
438 switch ( transformed.
type() )
442 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( transformed.
constGet() ) )
444 markerSymbol->renderPoint( QPointF( point->x(), point->y() ),
nullptr, context.
renderContext() );
446 else if (
const QgsMultiPoint *multipoint = qgsgeometry_cast< const QgsMultiPoint * >( transformed.
constGet() ) )
448 const int numGeometries = multipoint->numGeometries();
449 for (
int i = 0; i < numGeometries; ++i )
451 markerSymbol->renderPoint( QPointF( multipoint->pointN( i )->x(), multipoint->pointN( i )->y() ),
nullptr, context.
renderContext() );
459 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( transformed.
constGet() ) )
461 lineSymbol->renderPolyline( line->asQPolygonF(),
nullptr, context.
renderContext() );
463 else if (
const QgsMultiLineString *multiLinestring = qgsgeometry_cast< const QgsMultiLineString * >( transformed.
constGet() ) )
465 const int numGeometries = multiLinestring->numGeometries();
466 for (
int i = 0; i < numGeometries; ++i )
468 lineSymbol->renderPolyline( multiLinestring->lineStringN( i )->asQPolygonF(),
nullptr, context.
renderContext() );
476 if (
const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( transformed.
constGet() ) )
478 if (
const QgsCurve *exterior = polygon->exteriorRing() )
479 fillSymbol->renderPolygon( exterior->asQPolygonF(),
nullptr,
nullptr, context.
renderContext() );
481 else if (
const QgsMultiPolygon *multiPolygon = qgsgeometry_cast< const QgsMultiPolygon * >( transformed.
constGet() ) )
483 const int numGeometries = multiPolygon->numGeometries();
484 for (
int i = 0; i < numGeometries; ++i )
486 fillSymbol->renderPolygon( multiPolygon->polygonN( i )->exteriorRing()->asQPolygonF(),
nullptr,
nullptr, context.
renderContext() );
503 std::unique_ptr< QgsFeatureRenderer > renderer(
mLayer->renderer()->clone() );
508 QSet<QString> attributes = renderer->usedAttributes( context.
renderContext() );
510 std::unique_ptr< QgsMarkerSymbol > marker(
mMarkerSymbol->clone() );
511 std::unique_ptr< QgsLineSymbol > line(
mLineSymbol->clone() );
512 std::unique_ptr< QgsFillSymbol > fill(
mFillSymbol->clone() );
513 attributes.unite( marker->usedAttributes( context.
renderContext() ) );
514 attributes.unite( line->usedAttributes( context.
renderContext() ) );
515 attributes.unite( fill->usedAttributes( context.
renderContext() ) );
525 if ( !rendererSymbol )
529 marker->setOpacity( rendererSymbol->
opacity() );
530 line->setColor( rendererSymbol->
color() );
531 line->setOpacity( rendererSymbol->
opacity() );
532 fill->setColor( rendererSymbol->
color() );
533 fill->setOpacity( rendererSymbol->
opacity() );
539 const QVector< Feature > profileFeatures =
features.value( feature.
id() );
540 for (
const Feature &profileFeature : profileFeatures )
542 renderResult( profileFeature,
557 QSet<QString> attributes;
572 const QVector< Feature > profileFeatures =
features.value( feature.
id() );
573 for (
const Feature &profileFeature : profileFeatures )
592 painter->setBrush( Qt::NoBrush );
593 painter->setPen( Qt::NoPen );
600 const QRectF visibleRegion( minDistance,
minZ, maxDistance - minDistance,
maxZ -
minZ );
601 QPainterPath clipPath;
602 clipPath.addPolygon( context.
worldTransform().map( visibleRegion ) );
603 painter->setClipPath( clipPath, Qt::ClipOperation::IntersectClip );
609 if ( std::isnan( pointIt.value() ) )
619 QVector<QgsAbstractProfileResults::Feature> res;
626 for (
const Feature &feature : it.value() )
633 outFeature.
attributes = {{QStringLiteral(
"id" ), feature.featureId }};
641 outFeature.
geometry = feature.crossSectionGeometry;
658 mId = vlGenerator->mId;
661 mMarkerSymbol.reset( vlGenerator->mProfileMarkerSymbol->clone() );
673 , mProfileCurve( request.profileCurve() ? request.profileCurve()->clone() : nullptr )
674 , mTerrainProvider( request.terrainProvider() ? request.terrainProvider()->clone() : nullptr )
675 , mTolerance( request.tolerance() )
676 , mSourceCrs( layer->
crs() )
677 , mTargetCrs( request.
crs() )
678 , mTransformContext( request.transformContext() )
679 , mExtent( layer->extent() )
681 , mOffset( layer->elevationProperties()->zOffset() )
682 , mScale( layer->elevationProperties()->zScale() )
688 , mExpressionContext( request.expressionContext() )
689 , mFields( layer->fields() )
690 , mDataDefinedProperties( layer->elevationProperties()->dataDefinedProperties() )
691 , mWkbType( layer->wkbType() )
697 if ( mTerrainProvider )
698 mTerrainProvider->prepare();
702 mProfileCurve->dropZValue();
720 if ( !mProfileCurve || mFeedback->isCanceled() )
724 mTransformedCurve.reset( mProfileCurve->clone() );
726 if ( mTerrainProvider )
727 mTargetToTerrainProviderTransform =
QgsCoordinateTransform( mTargetCrs, mTerrainProvider->crs(), mTransformContext );
735 QgsDebugError( QStringLiteral(
"Error transforming profile line to vector CRS" ) );
739 const QgsRectangle profileCurveBoundingBox = mTransformedCurve->boundingBox();
740 if ( !profileCurveBoundingBox.
intersects( mExtent ) )
743 if ( mFeedback->isCanceled() )
746 mResults = std::make_unique< QgsVectorLayerProfileResults >();
747 mResults->mLayer = mLayer;
748 mResults->copyPropertiesFromGenerator(
this );
750 mProfileCurveEngine.reset(
new QgsGeos( mProfileCurve.get() ) );
751 mProfileCurveEngine->prepareGeometry();
753 if ( mTolerance == 0.0 )
755 mProfileBufferedCurve = std::unique_ptr<QgsAbstractGeometry>( mProfileCurve->clone() );
762 mProfileBufferedCurveEngine.reset(
new QgsGeos( mProfileBufferedCurve.get() ) );
763 mProfileBufferedCurveEngine->prepareGeometry();
765 mDataDefinedProperties.
prepare( mExpressionContext );
767 if ( mFeedback->isCanceled() )
773 if ( !generateProfileForPoints() )
778 if ( !generateProfileForLines() )
783 if ( !generateProfileForPolygons() )
797 return mResults.release();
802 return mFeedback.get();
805bool QgsVectorLayerProfileGenerator::generateProfileForPoints()
820 while ( !mFeedback->isCanceled() && it.
nextFeature( feature ) )
827 if ( mProfileBufferedCurveEngine->intersects( *it ) )
829 processIntersectionPoint( qgsgeometry_cast< const QgsPoint * >( *it ), feature );
833 return !mFeedback->isCanceled();
836void QgsVectorLayerProfileGenerator::processIntersectionPoint(
const QgsPoint *point,
const QgsFeature &feature )
841 const double height = featureZToHeight( point->
x(), point->
y(), point->
z(), offset );
842 mResults->mRawPoints.append(
QgsPoint( point->
x(), point->
y(), height ) );
843 mResults->minZ = std::min( mResults->minZ, height );
844 mResults->maxZ = std::max( mResults->maxZ, height );
846 const double distanceAlongProfileCurve = mProfileCurveEngine->lineLocatePoint( *point, &error );
847 mResults->mDistanceToHeightMap.insert( distanceAlongProfileCurve, height );
851 if ( mExtrusionEnabled )
856 QgsPoint( point->
x(), point->
y(), height + extrusion ) ) );
858 QgsPoint( distanceAlongProfileCurve, height + extrusion ) ) );
859 mResults->minZ = std::min( mResults->minZ, height + extrusion );
860 mResults->maxZ = std::max( mResults->maxZ, height + extrusion );
868 mResults->features[resultFeature.
featureId].append( resultFeature );
871void QgsVectorLayerProfileGenerator::processIntersectionCurve(
const QgsLineString *intersectionCurve,
const QgsFeature &feature )
877 double maxDistanceAlongProfileCurve = std::numeric_limits<double>::lowest();
882 const int numPoints = intersectionCurve->
numPoints();
883 QVector< double > newX( numPoints );
884 QVector< double > newY( numPoints );
885 QVector< double > newZ( numPoints );
886 QVector< double > newDistance( numPoints );
888 const double *inX = intersectionCurve->
xData();
889 const double *inY = intersectionCurve->
yData();
890 const double *inZ = intersectionCurve->
is3D() ? intersectionCurve->
zData() :
nullptr;
891 double *outX = newX.data();
892 double *outY = newY.data();
893 double *outZ = newZ.data();
894 double *outDistance = newDistance.data();
896 QVector< double > extrudedZ;
897 double *extZOut =
nullptr;
898 if ( mExtrusionEnabled )
900 extrudedZ.resize( numPoints );
901 extZOut = extrudedZ.data();
904 for (
int i = 0 ; ! mFeedback->isCanceled() && i < numPoints; ++i )
906 QgsPoint intersectionPoint( *inX, *inY, ( inZ ? *inZ : std::numeric_limits<double>::quiet_NaN() ) );
908 const double height = featureZToHeight( intersectionPoint.x(), intersectionPoint.y(), intersectionPoint.z(), offset );
909 const double distanceAlongProfileCurve = mProfileCurveEngine->lineLocatePoint( intersectionPoint, &error );
911 maxDistanceAlongProfileCurve = std::max( maxDistanceAlongProfileCurve, distanceAlongProfileCurve );
913 mResults->mRawPoints.append(
QgsPoint( intersectionPoint.x(), intersectionPoint.y(), height ) );
914 mResults->minZ = std::min( mResults->minZ, height );
915 mResults->maxZ = std::max( mResults->maxZ, height );
917 mResults->mDistanceToHeightMap.insert( distanceAlongProfileCurve, height );
918 *outDistance++ = distanceAlongProfileCurve;
920 *outX++ = intersectionPoint.x();
921 *outY++ = intersectionPoint.y();
924 *extZOut++ = height + extrusion;
926 if ( mExtrusionEnabled )
928 mResults->minZ = std::min( mResults->minZ, height + extrusion );
929 mResults->maxZ = std::max( mResults->maxZ, height + extrusion );
937 mResults->mDistanceToHeightMap.insert( maxDistanceAlongProfileCurve + 0.000001, std::numeric_limits<double>::quiet_NaN() );
939 if ( mFeedback->isCanceled() )
943 if ( mExtrusionEnabled )
945 std::unique_ptr< QgsLineString > ring = std::make_unique< QgsLineString >( newX, newY, newZ );
946 std::unique_ptr< QgsLineString > extrudedRing = std::make_unique< QgsLineString >( newX, newY, extrudedZ );
947 std::unique_ptr< QgsLineString > reversedExtrusion( extrudedRing->reversed() );
948 ring->append( reversedExtrusion.get() );
952 std::unique_ptr< QgsLineString > distanceVHeightRing = std::make_unique< QgsLineString >( newDistance, newZ );
953 std::unique_ptr< QgsLineString > extrudedDistanceVHeightRing = std::make_unique< QgsLineString >( newDistance, extrudedZ );
954 std::unique_ptr< QgsLineString > reversedDistanceVHeightExtrusion( extrudedDistanceVHeightRing->reversed() );
955 distanceVHeightRing->append( reversedDistanceVHeightExtrusion.get() );
956 distanceVHeightRing->close();
965 mResults->features[resultFeature.
featureId].append( resultFeature );
968bool QgsVectorLayerProfileGenerator::generateProfileForLines()
973 if ( mTolerance > 0 )
984 auto processCurve = [
this](
const QgsFeature & feature,
const QgsCurve * featGeomPart )
987 std::unique_ptr< QgsAbstractGeometry > intersection( mProfileBufferedCurveEngine->intersection( featGeomPart, &error ) );
991 if ( mFeedback->isCanceled() )
996 if ( intersection->isEmpty() )
998 intersection.reset( featGeomPart->clone() );
1001 QgsGeos featGeomPartGeos( featGeomPart );
1002 featGeomPartGeos.prepareGeometry();
1004 for (
auto it = intersection->const_parts_begin();
1005 !mFeedback->isCanceled() && it != intersection->const_parts_end();
1008 if (
const QgsPoint *intersectionPoint = qgsgeometry_cast< const QgsPoint * >( *it ) )
1012 const double distance = featGeomPartGeos.lineLocatePoint( *intersectionPoint, &error );
1013 std::unique_ptr< QgsPoint > interpolatedPoint( featGeomPart->interpolatePoint( distance ) );
1015 processIntersectionPoint( interpolatedPoint.get(), feature );
1017 else if (
const QgsLineString *intersectionCurve = qgsgeometry_cast< const QgsLineString * >( *it ) )
1019 processIntersectionCurve( intersectionCurve, feature );
1026 while ( !mFeedback->isCanceled() && it.
nextFeature( feature ) )
1033 if ( mProfileBufferedCurveEngine->intersects( *it ) )
1035 processCurve( feature, qgsgeometry_cast< const QgsCurve * >( *it ) );
1040 return !mFeedback->isCanceled();
1043QgsPoint QgsVectorLayerProfileGenerator::interpolatePointOnTriangle(
const QgsPolygon *triangle,
double x,
double y )
const
1050 const double z = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, p1.
z(), p2.
z(), p3.
z(),
QgsPointXY( x, y ) );
1054void QgsVectorLayerProfileGenerator::processTriangleIntersectForPoint(
const QgsPolygon *triangle,
const QgsPoint *p, QVector< QgsGeometry > &transformedParts, QVector< QgsGeometry > &crossSectionParts )
1056 const QgsPoint interpolatedPoint = interpolatePointOnTriangle( triangle, p->
x(), p->
y() );
1057 mResults->mRawPoints.append( interpolatedPoint );
1058 mResults->minZ = std::min( mResults->minZ, interpolatedPoint.
z() );
1059 mResults->maxZ = std::max( mResults->maxZ, interpolatedPoint.
z() );
1062 const double distance = mProfileCurveEngine->lineLocatePoint( *p, &lastError );
1063 mResults->mDistanceToHeightMap.insert( distance, interpolatedPoint.
z() );
1065 if ( mExtrusionEnabled )
1070 QgsPoint( interpolatedPoint.
x(), interpolatedPoint.
y(), interpolatedPoint.
z() + extrusion ) ) ) );
1072 QgsPoint( distance, interpolatedPoint.
z() + extrusion ) ) ) );
1073 mResults->minZ = std::min( mResults->minZ, interpolatedPoint.
z() + extrusion );
1074 mResults->maxZ = std::max( mResults->maxZ, interpolatedPoint.
z() + extrusion );
1083void QgsVectorLayerProfileGenerator::processTriangleIntersectForLine(
const QgsPolygon *triangle,
const QgsLineString *intersectionLine, QVector< QgsGeometry > &transformedParts, QVector< QgsGeometry > &crossSectionParts )
1088 int numPoints = intersectionLine->
numPoints();
1089 QVector< double > newX( numPoints );
1090 QVector< double > newY( numPoints );
1091 QVector< double > newZ( numPoints );
1092 QVector< double > newDistance( numPoints );
1094 const double *inX = intersectionLine->
xData();
1095 const double *inY = intersectionLine->
yData();
1096 const double *inZ = intersectionLine->
is3D() ? intersectionLine->
zData() :
nullptr;
1097 double *outX = newX.data();
1098 double *outY = newY.data();
1099 double *outZ = newZ.data();
1100 double *outDistance = newDistance.data();
1102 double lastDistanceAlongProfileCurve = 0.0;
1103 QVector< double > extrudedZ;
1104 double *extZOut =
nullptr;
1105 double extrusion = 0;
1107 if ( mExtrusionEnabled )
1109 extrudedZ.resize( numPoints );
1110 extZOut = extrudedZ.data();
1116 for (
int i = 0 ; ! mFeedback->isCanceled() && i < numPoints; ++i )
1120 double z = inZ ? *inZ++ : 0;
1122 QgsPoint interpolatedPoint( x, y, z );
1128 interpolatedPoint = interpolatePointOnTriangle( triangle, x, y );
1130 double tempOutZ = std::isnan( interpolatedPoint.
z() ) ? 0.0 : interpolatedPoint.
z();
1133 if ( mExtrusionEnabled )
1134 *extZOut++ = tempOutZ + extrusion;
1136 mResults->mRawPoints.append( interpolatedPoint );
1137 mResults->minZ = std::min( mResults->minZ, interpolatedPoint.
z() );
1138 mResults->maxZ = std::max( mResults->maxZ, interpolatedPoint.
z() );
1139 if ( mExtrusionEnabled )
1141 mResults->minZ = std::min( mResults->minZ, interpolatedPoint.
z() + extrusion );
1142 mResults->maxZ = std::max( mResults->maxZ, interpolatedPoint.
z() + extrusion );
1145 const double distance = mProfileCurveEngine->lineLocatePoint( interpolatedPoint, &lastError );
1146 *outDistance++ = distance;
1148 mResults->mDistanceToHeightMap.insert( distance, interpolatedPoint.
z() );
1149 lastDistanceAlongProfileCurve = distance;
1153 mResults->mDistanceToHeightMap.insert( lastDistanceAlongProfileCurve + 0.000001, std::numeric_limits<double>::quiet_NaN() );
1155 if ( mFeedback->isCanceled() )
1158 if ( mExtrusionEnabled )
1160 std::unique_ptr< QgsLineString > ring = std::make_unique< QgsLineString >( newX, newY, newZ );
1161 std::unique_ptr< QgsLineString > extrudedRing = std::make_unique< QgsLineString >( newX, newY, extrudedZ );
1162 std::unique_ptr< QgsLineString > reversedExtrusion( extrudedRing->reversed() );
1163 ring->append( reversedExtrusion.get() );
1167 std::unique_ptr< QgsLineString > distanceVHeightRing = std::make_unique< QgsLineString >( newDistance, newZ );
1168 std::unique_ptr< QgsLineString > extrudedDistanceVHeightRing = std::make_unique< QgsLineString >( newDistance, extrudedZ );
1169 std::unique_ptr< QgsLineString > reversedDistanceVHeightExtrusion( extrudedDistanceVHeightRing->reversed() );
1170 distanceVHeightRing->append( reversedDistanceVHeightExtrusion.get() );
1171 distanceVHeightRing->close();
1181void QgsVectorLayerProfileGenerator::processTriangleIntersectForPolygon(
const QgsPolygon *sourcePolygon,
const QgsPolygon *intersectionPolygon, QVector< QgsGeometry > &transformedParts, QVector< QgsGeometry > &crossSectionParts )
1183 bool oldExtrusion = mExtrusionEnabled;
1216 mExtrusionEnabled =
false;
1217 if ( mProfileBufferedCurveEngine->contains( sourcePolygon ) )
1221 QgsLineString *exteriorLine = qgsgeometry_cast<QgsLineString *>( exterior );
1222 processTriangleIntersectForLine( sourcePolygon, exteriorLine, transformedParts, crossSectionParts );
1227 processTriangleIntersectForLine( sourcePolygon, interiorLine, transformedParts, crossSectionParts );
1235 QgsLineString *exteriorLine = qgsgeometry_cast<QgsLineString *>( exterior )->
clone();
1237 processTriangleIntersectForLine( sourcePolygon, exteriorLine, transformedParts, crossSectionParts );
1238 delete exteriorLine;
1243 if ( mProfileBufferedCurveEngine->contains( interiorLine ) )
1245 processTriangleIntersectForLine( sourcePolygon, interiorLine, transformedParts, crossSectionParts );
1249 interiorLine = qgsgeometry_cast<QgsLineString *>( intersectionPolygon->
interiorRing( i ) )->
clone();
1251 processTriangleIntersectForLine( sourcePolygon, interiorLine, transformedParts, crossSectionParts );
1252 delete interiorLine;
1257 mExtrusionEnabled = oldExtrusion;
1260bool QgsVectorLayerProfileGenerator::generateProfileForPolygons()
1265 if ( mTolerance > 0 )
1276 std::function< void(
const QgsPolygon *triangle,
const QgsAbstractGeometry *intersect, QVector< QgsGeometry > &, QVector< QgsGeometry > & ) > processTriangleLineIntersect;
1277 processTriangleLineIntersect = [
this](
const QgsPolygon * triangle,
const QgsAbstractGeometry * intersection, QVector< QgsGeometry > &transformedParts, QVector< QgsGeometry > &crossSectionParts )
1279 for (
auto it = intersection->const_parts_begin();
1280 ! mFeedback->isCanceled() && it != intersection->const_parts_end();
1287 if (
const QgsPoint *p = qgsgeometry_cast< const QgsPoint * >( *it ) )
1289 processTriangleIntersectForPoint( triangle, p, transformedParts, crossSectionParts );
1294 if (
const QgsLineString *intersectionLine = qgsgeometry_cast< const QgsLineString * >( *it ) )
1296 processTriangleIntersectForLine( triangle, intersectionLine, transformedParts, crossSectionParts );
1301 if (
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon * >( *it ) )
1303 processTriangleIntersectForPolygon( triangle, poly, transformedParts, crossSectionParts );
1314 auto triangleIsCollinearInXYPlane = [](
const QgsPolygon * polygon )->
bool
1316 const QgsLineString *ring = qgsgeometry_cast< const QgsLineString * >( polygon->exteriorRing() );
1318 ring->
xAt( 1 ), ring->
yAt( 1 ),
1319 ring->
xAt( 2 ), ring->
yAt( 2 ), 0.005 );
1322 auto processPolygon = [
this, &processTriangleLineIntersect, &triangleIsCollinearInXYPlane](
const QgsCurvePolygon * polygon, QVector< QgsGeometry > &transformedParts, QVector< QgsGeometry > &crossSectionParts,
double offset,
bool & wasCollinear )
1324 std::unique_ptr< QgsPolygon > clampedPolygon;
1325 if (
const QgsPolygon *p = qgsgeometry_cast< const QgsPolygon * >( polygon ) )
1327 clampedPolygon.reset( p->
clone() );
1331 clampedPolygon.reset( qgsgeometry_cast< QgsPolygon * >( polygon->segmentize() ) );
1333 clampAltitudes( clampedPolygon.get(), offset );
1335 if ( mFeedback->isCanceled() )
1338 if ( mTolerance > 0.0 )
1341 if ( mProfileBufferedCurveEngine->intersects( clampedPolygon.get(), &error ) )
1343 std::unique_ptr< QgsAbstractGeometry > intersection;
1344 intersection.reset( mProfileBufferedCurveEngine->intersection( clampedPolygon.get(), &error ) );
1345 if ( error.isEmpty() )
1347 processTriangleLineIntersect( clampedPolygon.get(), intersection.get(), transformedParts, crossSectionParts );
1354 QgsLineString *ring = qgsgeometry_cast< QgsLineString * >( clampedPolygon->exteriorRing() );
1356 QVector< double > newX( numPoints );
1357 QVector< double > newY( numPoints );
1358 QVector< double > newZ( numPoints );
1359 double *outX = newX.data();
1360 double *outY = newY.data();
1361 double *outZ = newZ.data();
1363 const double *inX = ring->
xData();
1364 const double *inY = ring->
yData();
1365 const double *inZ = ring->
zData();
1366 for (
int i = 0 ; ! mFeedback->isCanceled() && i < ring->numPoints() - 1; ++i )
1368 *outX++ = inX[i] + i * 1.0e-9;
1369 *outY++ = inY[i] + i * 1.0e-9;
1372 std::unique_ptr< QgsPolygon > shiftedPoly;
1375 intersection.reset( mProfileBufferedCurveEngine->intersection( shiftedPoly.get(), &error ) );
1376 if ( intersection.get() )
1377 processTriangleLineIntersect( clampedPolygon.get(), intersection.get(), transformedParts, crossSectionParts );
1379 QgsDebugMsgLevel( QStringLiteral(
"processPolygon after shift bad geom! error: %1" ).arg( error ), 0 );
1387 if ( clampedPolygon->numInteriorRings() == 0 && clampedPolygon->exteriorRing() && clampedPolygon->exteriorRing()->numPoints() == 4 && clampedPolygon->exteriorRing()->isClosed() )
1390 std::unique_ptr< QgsMultiPolygon > multiPolygon = std::make_unique< QgsMultiPolygon >();
1391 multiPolygon->addGeometry( clampedPolygon.release() );
1392 tessellation =
QgsGeometry( std::move( multiPolygon ) );
1396 const QgsRectangle bounds = clampedPolygon->boundingBox();
1398 t.addPolygon( *clampedPolygon, 0 );
1401 if ( mFeedback->isCanceled() )
1408 const int numTriangles = qgsgeometry_cast< const QgsMultiPolygon * >( tessellation.
constGet() )->numGeometries();
1409 for (
int i = 0; ! mFeedback->isCanceled() && i < numTriangles; ++i )
1411 const QgsPolygon *triangle = qgsgeometry_cast< const QgsPolygon * >( qgsgeometry_cast< const QgsMultiPolygon * >( tessellation.
constGet() )->geometryN( i ) );
1413 if ( triangleIsCollinearInXYPlane( triangle ) )
1415 wasCollinear =
true;
1416 const QgsLineString *ring = qgsgeometry_cast< const QgsLineString * >( polygon->exteriorRing() );
1419 if (
const QgsLineString *ls = qgsgeometry_cast< const QgsLineString * >( mProfileCurve.get() ) )
1421 for (
int curveSegmentIndex = 0; curveSegmentIndex < mProfileCurve->numPoints() - 1; ++curveSegmentIndex )
1423 const QgsPoint p1 = ls->pointN( curveSegmentIndex );
1424 const QgsPoint p2 = ls->pointN( curveSegmentIndex + 1 );
1427 double minZ = std::numeric_limits< double >::max();
1428 double maxZ = std::numeric_limits< double >::lowest();
1430 for (
auto vertexPair : std::array<std::pair<int, int>, 3> {{ { 0, 1}, {1, 2}, {2, 0} }} )
1432 bool isIntersection =
false;
1436 const double intersectionZ = ring->
zAt( vertexPair.first ) + ( ring->
zAt( vertexPair.second ) - ring->
zAt( vertexPair.first ) ) * fraction;
1437 minZ = std::min( minZ, intersectionZ );
1438 maxZ = std::max( maxZ, intersectionZ );
1442 if ( !intersectionPoint.
isEmpty() )
1445 mResults->mRawPoints.append( intersectionPoint );
1446 mResults->minZ = std::min( mResults->minZ, minZ );
1447 mResults->maxZ = std::max( mResults->maxZ, maxZ );
1449 const double distance = mProfileCurveEngine->lineLocatePoint( intersectionPoint, &lastError );
1451 crossSectionParts.append(
QgsGeometry(
new QgsLineString( QVector< double > {distance, distance}, QVector< double > {minZ, maxZ} ) ) );
1453 mResults->mDistanceToHeightMap.insert( distance, minZ );
1454 mResults->mDistanceToHeightMap.insert( distance, maxZ );
1461 QgsDebugError( QStringLiteral(
"Collinear triangles with curved profile lines are not supported yet" ) );
1467 if ( mProfileBufferedCurveEngine->intersects( triangle, &error ) )
1469 std::unique_ptr< QgsAbstractGeometry > intersection( mProfileBufferedCurveEngine->intersection( triangle, &error ) );
1470 processTriangleLineIntersect( triangle, intersection.get(), transformedParts, crossSectionParts );
1480 while ( ! mFeedback->isCanceled() && it.
nextFeature( feature ) )
1482 if ( !mProfileBufferedCurveEngine->intersects( feature.
geometry().
constGet() ) )
1489 QVector< QgsGeometry > transformedParts;
1490 QVector< QgsGeometry > crossSectionParts;
1491 bool wasCollinear =
false;
1496 if ( mProfileBufferedCurveEngine->intersects( *it ) )
1498 processPolygon( qgsgeometry_cast< const QgsCurvePolygon * >( *it ), transformedParts, crossSectionParts, offset, wasCollinear );
1502 if ( mFeedback->isCanceled() )
1509 if ( !crossSectionParts.empty() )
1511 if ( !wasCollinear )
1532 mResults->features[resultFeature.
featureId].append( resultFeature );
1537double QgsVectorLayerProfileGenerator::terrainHeight(
double x,
double y )
1539 if ( !mTerrainProvider )
1540 return std::numeric_limits<double>::quiet_NaN();
1550 return std::numeric_limits<double>::quiet_NaN();
1553 return mTerrainProvider->heightAt( x, y );
1556double QgsVectorLayerProfileGenerator::featureZToHeight(
double x,
double y,
double z,
double offset )
1558 switch ( mClamping )
1566 const double terrainZ = terrainHeight( x, y );
1567 if ( !std::isnan( terrainZ ) )
1569 switch ( mClamping )
1572 if ( std::isnan( z ) )
1590 return ( std::isnan( z ) ? 0 : z ) * mScale + offset;
1597 if ( mFeedback->isCanceled() )
1600 double terrainZ = 0;
1601 switch ( mClamping )
1610 pt.
setX( lineString->
xAt( i ) );
1611 pt.
setY( lineString->
yAt( i ) );
1619 terrainZ = terrainHeight( pt.
x(), pt.
y() );
1629 switch ( mClamping )
1633 geomZ = lineString->
zAt( i );
1640 const double z = ( terrainZ + ( std::isnan( geomZ ) ? 0 : geomZ ) ) * mScale + offset;
1641 lineString->
setZAt( i, z );
1645bool QgsVectorLayerProfileGenerator::clampAltitudes(
QgsPolygon *polygon,
double offset )
1647 if ( !polygon->
is3D() )
1662 QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( curve );
1666 clampAltitudes( lineString,
centroid, offset );
1670 if ( mFeedback->isCanceled() )
1674 QgsLineString *lineString = qgsgeometry_cast<QgsLineString *>( curve );
1678 clampAltitudes( lineString,
centroid, offset );
@ 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...
VertexType
Types of vertex.
@ Round
Use rounded joins.
@ Centroid
Clamp just centroid of feature.
@ Vertex
Clamp every vertex of feature.
@ Flat
Flat cap (in line with start/end of line)
@ ContinuousSurface
The features should be treated as representing values on a continuous surface (eg contour lines)
@ IndividualFeatures
Treat each feature as an individual object (eg buildings)
ProfileExportType
Types of export for elevation profiles.
@ Profile2D
Export profiles as 2D profile lines, with elevation stored in exported geometry Y dimension and dista...
@ Features3D
Export profiles as 3D features, with elevation values stored in exported geometry Z values.
@ DistanceVsElevationTable
Export profiles as a table of sampled distance vs elevation values.
@ Reverse
Reverse/inverse transform (from destination to source)
Abstract base class for all geometries.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual QgsPoint centroid() const
Returns the centroid of the geometry.
Abstract base class for objects which generate elevation profiles.
Abstract base class for storage of elevation profiles.
Abstract base class for objects which generate elevation profiles which represent a continuous surfac...
std::unique_ptr< QgsLineSymbol > mLineSymbol
Qgis::ProfileSurfaceSymbology mSymbology
std::unique_ptr< QgsFillSymbol > mFillSymbol
std::unique_ptr< QgsFillSymbol > mFillSymbol
QMap< double, double > mDistanceToHeightMap
std::unique_ptr< QgsLineSymbol > mLineSymbol
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< QgsAbstractProfileResults::Feature > asFeatures(Qgis::ProfileExportType type, QgsFeedback *feedback=nullptr) const override
Returns a list of features 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.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual int numPoints() const =0
Returns the number of points in the curve.
virtual bool pointAt(int node, QgsPoint &point, Qgis::VertexType &type) const =0
Returns the point and vertex id of a point within the curve.
QgsRange which stores a range of double values.
RAII class to pop scope from an expression context on destruction.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QgsFeatureRequest & setDistanceWithin(const QgsGeometry &geometry, double distance)
Sets a reference geometry and a maximum distance from this geometry to retrieve features within.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static double pointFractionAlongLine(double x1, double y1, double x2, double y2, double px, double py)
Given the line (x1, y1) to (x2, y2) and a point (px, py) returns the fraction of the line length at w...
static bool pointsAreCollinear(double x1, double y1, double x2, double y2, double x3, double y3, double epsilon)
Given the points (x1, y1), (x2, y2) and (x3, y3) returns true if these points can be considered colli...
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
Qgis::GeometryOperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
Does vector analysis using the geos library and handles import, export, exception handling*.
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
void setZAt(int index, double z)
Sets the z-coordinate of the specified node in the line string.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
double zAt(int index) const override
Returns the z-coordinate of the specified node in the line string.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
A line symbol type, for rendering LineString and MultiLineString geometries.
@ ExtrusionHeight
Z offset.
A marker symbol type, for rendering Point and MultiPoint geometries.
Multi line string geometry collection.
Multi point geometry collection.
Multi polygon geometry collection.
A class to represent a 2D point.
void setY(double y)
Sets the y value of the point.
void set(double x, double y)
Sets the x and y value of the point.
void setX(double x)
Sets the x value of the point.
Point geometry type, with support for z-dimension and m-values.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
bool isEmpty() const override
Returns true if the geometry is empty.
Encapsulates the context in which an elevation profile is to be generated.
Encapsulates the context of identifying profile results.
double maximumPointElevationDelta
Maximum allowed snapping delta for the elevation values when identifying a point.
double maximumPointDistanceDelta
Maximum allowed snapping delta for the distance values when identifying a point.
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 properties and constraints relating to fetching elevation profiles from different source...
Encapsulates the context of snapping a profile point.
double maximumPointDistanceDelta
Maximum allowed snapping delta for the distance values when snapping to a point.
double maximumSurfaceElevationDelta
Maximum allowed snapping delta for the elevation values when snapping to a continuous elevation surfa...
double maximumPointElevationDelta
Maximum allowed snapping delta for the elevation values when snapping to a point.
Encapsulates results of snapping a profile point.
QgsProfilePoint snappedPoint
Snapped point.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const final
Prepares the collection against a specified expression context.
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const final
Returns the set of any fields referenced by the active properties from the collection.
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
Scoped object for saving and restoring a QPainter object's state.
Abstract base class for all rendered symbols.
void setColor(const QColor &color) const
Sets the color for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
Class that takes care of tessellation of polygons into triangles.
Vector layer specific subclass of QgsMapLayerElevationProperties.
Partial snapshot of vector layer's state (only the members necessary for access to features)
Implementation of QgsAbstractProfileGenerator for vector layers.
QgsAbstractProfileResults * takeResults() override
Takes results from the generator.
bool generateProfile(const QgsProfileGenerationContext &context=QgsProfileGenerationContext()) override
Generate the profile (based on data stored in the class).
QString sourceId() const override
Returns a unique identifier representing the source of the profile.
~QgsVectorLayerProfileGenerator() override
QgsFeedback * feedback() const override
Access to feedback object of the generator (may be nullptr)
QgsVectorLayerProfileGenerator(QgsVectorLayer *layer, const QgsProfileRequest &request)
Constructor for QgsVectorLayerProfileGenerator.
QVector< QgsProfileIdentifyResults > identify(const QgsProfilePoint &point, const QgsProfileIdentifyContext &context) override
Identify results visible at the specified profile point.
Qgis::VectorProfileType profileType
std::unique_ptr< QgsMarkerSymbol > mMarkerSymbol
bool respectLayerSymbology
bool mShowMarkerSymbolInSurfacePlots
QVector< QgsGeometry > asGeometries() const override
Returns a list of geometries representing the calculated elevation results.
QPointer< QgsVectorLayer > mLayer
void renderResults(QgsProfileRenderContext &context) override
Renders the results to the specified context.
QVector< QgsAbstractProfileResults::Feature > asFeatures(Qgis::ProfileExportType type, QgsFeedback *feedback=nullptr) const override
Returns a list of features representing the calculated elevation results.
QgsProfileSnapResult snapPoint(const QgsProfilePoint &point, const QgsProfileSnapContext &context) override
Snaps a point to the generated elevation profile.
QString type() const override
Returns the unique string identifier for the results type.
QHash< QgsFeatureId, QVector< Feature > > features
void copyPropertiesFromGenerator(const QgsAbstractProfileGenerator *generator) override
Copies properties from specified generator to the results object.
Represents a vector layer which manages a vector based data sets.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
#define BUILTIN_UNREACHABLE
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
const QgsCoordinateReferenceSystem & crs
Encapsulates information about a feature exported from the profile results.
QString layerIdentifier
Identifier for grouping output features.
QVariantMap attributes
Exported attributes.
QgsGeometry geometry
Exported geometry.
QgsGeometry crossSectionGeometry
Cross section distance vs height geometry for feature.
QgsFeatureId featureId
Original feature ID.
QgsGeometry geometry
Feature's geometry with any terrain height adjustment and extrusion applied.
Utility class for identifying a unique vertex within a geometry.