Skip to content

Commit

Permalink
Fix crash when generating profile of 2d line using line as curve
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 4, 2023
1 parent 728e596 commit 40e9e1a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/core/vector/qgsvectorlayerprofilegenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ void QgsVectorLayerProfileResults::visitFeaturesAtPoint( const QgsProfilePoint &
const double snappedDistance = point.distance() < partBounds.xMinimum() ? partBounds.xMinimum()
: point.distance() > partBounds.xMaximum() ? partBounds.xMaximum() : point.distance();

const QgsGeometry cutLine( new QgsLineString( QgsPoint( snappedDistance, minZ ), QgsPoint( snappedDistance, maxZ ) ) );
const QgsGeometry cutLine( new QgsLineString( QgsPoint( snappedDistance, qgsDoubleNear( minZ, maxZ ) ? minZ - 1 : minZ ), QgsPoint( snappedDistance, maxZ ) ) );
QgsGeos cutLineGeos( cutLine.constGet() );

const QgsGeometry points( cutLineGeos.intersection( line ) );
Expand Down Expand Up @@ -948,7 +948,7 @@ bool QgsVectorLayerProfileGenerator::generateProfileForLines()

const double *inX = ls->xData();
const double *inY = ls->yData();
const double *inZ = ls->zData();
const double *inZ = ls->is3D() ? ls->zData() : nullptr;
double *outX = newX.data();
double *outY = newY.data();
double *outZ = newZ.data();
Expand All @@ -975,11 +975,11 @@ bool QgsVectorLayerProfileGenerator::generateProfileForLines()
const double distanceAlongOriginalGeometry = curveGeos.lineLocatePoint( QgsPoint( x, y ) );
std::unique_ptr< QgsPoint > closestOriginalPoint( curve->interpolatePoint( distanceAlongOriginalGeometry ) );

double z = *inZ++;
double z = inZ ? *inZ++ : 0;

*outX++ = x;
*outY++ = y;
*outZ++ = closestOriginalPoint->z();
*outZ++ = std::isnan( closestOriginalPoint->z() ) ? 0 : closestOriginalPoint->z();
if ( extZOut )
*extZOut++ = z + extrusion;

Expand Down
44 changes: 44 additions & 0 deletions tests/src/python/test_qgsvectorlayerprofilegenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,50 @@ def testLineGenerationAbsolute(self):
self.assertAlmostEqual(results.zRange().lower(), 27.7064, 2)
self.assertAlmostEqual(results.zRange().upper(), 51.7598, 2)

def testLineGenerationFollowingLinestringExactly(self):
vl = QgsVectorLayer('MultiLineString?crs=EPSG:3857', 'lines', 'memory')
self.assertTrue(vl.isValid())

for line in ['MultiLineString ((872381.44973557780031115 6035318.57090197317302227, 868258.19322114891838282 6039288.30190788581967354, 870254.02483185648452491 6048565.62906535062938929, 884224.8461068095639348 6045999.55985158402472734, 876087.99415546329692006 6035472.0964104887098074))']:
f = QgsFeature()
f.setGeometry(QgsGeometry.fromWkt(line))
self.assertTrue(vl.dataProvider().addFeature(f))

vl.elevationProperties().setClamping(Qgis.AltitudeClamping.Absolute)

curve = QgsLineString()
curve.fromWkt(
'LineString(872381.44973557780031115 6035318.57090197317302227, 868258.19322114891838282 6039288.30190788581967354, 870254.02483185648452491 6048565.62906535062938929, 884224.8461068095639348 6045999.55985158402472734, 876087.99415546329692006 6035472.0964104887098074)')
req = QgsProfileRequest(curve)
req.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))

generator = vl.createProfileGenerator(req)
self.assertTrue(generator.generateProfile())
results = generator.takeResults()

self.assertEqual(self.round_dict(results.distanceToHeightMap(), 1),
{0.0: 0.0, 5723.6: 0.0, 15213.2: 0.0, 29417.7: 0.0, 42723.2: 0.0})

self.assertAlmostEqual(results.zRange().lower(), 0.0, 2)
self.assertAlmostEqual(results.zRange().upper(), 0.0, 2)

# try with just a part of the original linestring as the capture curve
curve = QgsLineString()
curve.fromWkt(
'LineString (872381.44973557780031115 6035318.57090197317302227, 868258.19322114891838282 6039288.30190788581967354, 870254.02483185648452491 6048565.62906535062938929)')
req = QgsProfileRequest(curve)
req.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))

generator = vl.createProfileGenerator(req)
self.assertTrue(generator.generateProfile())
results = generator.takeResults()

self.assertEqual(self.round_dict(results.distanceToHeightMap(), 1),
{0.0: 0.0, 5723.6: 0.0, 15213.2: 0.0})

self.assertAlmostEqual(results.zRange().lower(), 0.0, 2)
self.assertAlmostEqual(results.zRange().upper(), 0.0, 2)

def testLineGenerationFollowingLinestringZExactly(self):
vl = QgsVectorLayer('MultiLineStringZ?crs=EPSG:3857', 'lines', 'memory')
self.assertTrue(vl.isValid())
Expand Down

0 comments on commit 40e9e1a

Please sign in to comment.