mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
Nan z values should not be clipped from rendered geometries
Fixes #51796
This commit is contained in:
parent
65afa1c53b
commit
8f76a6a092
@ -566,9 +566,9 @@ inline bool QgsClipper::inside( double x, double y, double z, Boundary boundary,
|
||||
case YMin: // y > MIN_Y is inside
|
||||
return ( y > boundaryValue );
|
||||
case ZMax: // z < MAX_Z is inside
|
||||
return ( z < boundaryValue );
|
||||
return z < boundaryValue || std::isnan( z ) ;
|
||||
case ZMin: // z > MIN_Z is inside
|
||||
return ( z > boundaryValue );
|
||||
return z > boundaryValue || std::isnan( z );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ class TestQgsClipper: public QgsTest
|
||||
void basicWithZ();
|
||||
void basicWithZInf();
|
||||
void epsg4978LineRendering();
|
||||
void clipGeometryWithNaNZValues();
|
||||
|
||||
private:
|
||||
|
||||
@ -202,6 +203,50 @@ void TestQgsClipper::epsg4978LineRendering()
|
||||
QVERIFY( render2dCheck( "4978_2D_line_rendering", layerLines.get(), QgsRectangle( -2.5e7, -2.5e7, 2.5e7, 2.5e7 ) ) );
|
||||
}
|
||||
|
||||
void TestQgsClipper::clipGeometryWithNaNZValues()
|
||||
{
|
||||
// nan z values should not result in clipping
|
||||
QgsGeometry geom = QgsGeometry::fromWkt( QStringLiteral( "PolygonZ ((704425.82266869 7060014.33574043 19.51, 704439.59844559 7060023.73007711 19.69, 704441.6748229 7060020.65665367 19.63, 704428.333268 7060011.65915509 19.42, 704428.15434668 7060011.92446088 0, 704441.23037799 7060020.74289127 0, 704439.51320673 7060023.28462315 0, 704426.00295955 7060014.07136342 0, 704425.82266869 7060014.33574043 19.51))" ) );
|
||||
QgsLineString *exteriorRing = qgsgeometry_cast< QgsLineString * >( qgsgeometry_cast< QgsPolygon *>( geom.get() )->exteriorRing() );
|
||||
exteriorRing->setZAt( 4, std::numeric_limits<double>::quiet_NaN() );
|
||||
exteriorRing->setZAt( 5, std::numeric_limits<double>::quiet_NaN() );
|
||||
exteriorRing->setZAt( 6, std::numeric_limits<double>::quiet_NaN() );
|
||||
exteriorRing->setZAt( 7, std::numeric_limits<double>::quiet_NaN() );
|
||||
|
||||
QPolygonF polygon;
|
||||
polygon << QPointF( 10.4, 20.5 ) << QPointF( 20.2, 30.2 );
|
||||
|
||||
QVector< double > pointsX = exteriorRing->xVector();
|
||||
QVector< double > pointsY = exteriorRing->yVector();
|
||||
QVector< double > pointsZ = exteriorRing->zVector();
|
||||
QCOMPARE( pointsX.size(), 9 );
|
||||
|
||||
// 2d trim
|
||||
QgsRectangle clipRect( 704430.30, 7060007.72, 704456.51, 7060029.03 );
|
||||
QgsClipper::trimPolygon( pointsX, pointsY, pointsZ, clipRect );
|
||||
// one vertex should be clipped
|
||||
QCOMPARE( pointsX.size(), 8 );
|
||||
QCOMPARE( pointsY.size(), 8 );
|
||||
QCOMPARE( pointsZ.size(), 8 );
|
||||
QGSCOMPARENEAR( pointsX.at( 0 ), 704430.30, 0.01 );
|
||||
QGSCOMPARENEAR( pointsY.at( 0 ), 7060017.389, 0.01 );
|
||||
QGSCOMPARENEAR( pointsZ.at( 0 ), 19.568, 0.01 );
|
||||
|
||||
// 3d trim, clip box contains whole geometry
|
||||
pointsX = exteriorRing->xVector();
|
||||
pointsY = exteriorRing->yVector();
|
||||
pointsZ = exteriorRing->zVector();
|
||||
QgsBox3d clipRect3D( 704430.30, 7060007.72, 0, 704456.51, 7060029.03, 100 );
|
||||
QgsClipper::trimPolygon( pointsX, pointsY, pointsZ, clipRect3D );
|
||||
// still only one vertex should be clipped, the nan z values must remain
|
||||
QCOMPARE( pointsX.size(), 8 );
|
||||
QCOMPARE( pointsY.size(), 8 );
|
||||
QCOMPARE( pointsZ.size(), 8 );
|
||||
QGSCOMPARENEAR( pointsX.at( 0 ), 704430.30, 0.01 );
|
||||
QGSCOMPARENEAR( pointsY.at( 0 ), 7060017.389, 0.01 );
|
||||
QGSCOMPARENEAR( pointsZ.at( 0 ), 19.568, 0.01 );
|
||||
}
|
||||
|
||||
bool TestQgsClipper::render2dCheck( const QString &testName, QgsVectorLayer *layer, QgsRectangle extent )
|
||||
{
|
||||
const QString myTmpDir = QDir::tempPath() + '/';
|
||||
|
@ -483,6 +483,40 @@ class TestQgsGeometryGeneratorSymbolLayerV2(unittest.TestCase):
|
||||
self.report += renderchecker.report()
|
||||
self.assertTrue(res)
|
||||
|
||||
def test_clipped_results_with_z(self):
|
||||
"""
|
||||
See https://github.com/qgis/QGIS/issues/51796
|
||||
"""
|
||||
lines = QgsVectorLayer('LineString?crs=epsg:2154', 'Lines', 'memory')
|
||||
self.assertTrue(lines.isValid())
|
||||
f = QgsFeature()
|
||||
f.setGeometry(QgsGeometry.fromWkt('LineStringZ (704425.82266868802253157 7060014.33574043028056622 19.51000000000000156, 704439.59844558802433312 7060023.7300771102309227 19.69000000000000128, 704441.67482289997860789 7060020.65665366966277361 19.62999999999999901, 704428.333267995971255 7060011.65915509033948183 19.42000000000000171)'))
|
||||
lines.dataProvider().addFeature(f)
|
||||
|
||||
subsymbol = QgsFillSymbol.createSimple({'color': '#0000ff', 'line_style': 'no'})
|
||||
|
||||
parent_generator = QgsGeometryGeneratorSymbolLayer.create(
|
||||
{'geometryModifier': 'single_sided_buffer($geometry,-0.32, 1, 2)'})
|
||||
parent_generator.setSymbolType(QgsSymbol.Fill)
|
||||
|
||||
parent_generator.setSubSymbol(subsymbol)
|
||||
|
||||
geom_symbol = QgsLineSymbol()
|
||||
geom_symbol.changeSymbolLayer(0, parent_generator)
|
||||
lines.renderer().setSymbol(geom_symbol)
|
||||
|
||||
mapsettings = QgsMapSettings(self.mapsettings)
|
||||
mapsettings.setDestinationCrs(lines.crs())
|
||||
mapsettings.setExtent(QgsRectangle(704433.77, 7060006.64, 704454.78, 7060027.95))
|
||||
mapsettings.setLayers([lines])
|
||||
|
||||
renderchecker = QgsMultiRenderChecker()
|
||||
renderchecker.setMapSettings(mapsettings)
|
||||
renderchecker.setControlName('expected_geometrygenerator_z_clipping')
|
||||
res = renderchecker.runTest('geometrygenerator_z_clipping')
|
||||
self.report += renderchecker.report()
|
||||
self.assertTrue(res)
|
||||
|
||||
def imageCheck(self, name, reference_image, image):
|
||||
self.report += f"<h2>Render {name}</h2>\n"
|
||||
temp_dir = QDir.tempPath() + '/'
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 3.4 MiB |
Loading…
x
Reference in New Issue
Block a user