More robust way to pick zoom level of a scene layer (2D)

For world-wide datasets like google 3d tiles or quantized mesh terrains,
when zoomed full, the 2D map canvas would fetch tiles at a much more
detailed zoom level than I would expect. It turned out this was because
of ellipsoidal distance calculation on full extent width, where we would
often calculate much shorter distances than we should.

To make it more robust, we use only one pixel distance at the center
of the map, which should avoid these issues.
This commit is contained in:
Martin Dobias 2025-06-24 21:38:35 +02:00 committed by Nyall Dawson
parent 85637da1f1
commit 37449ae90f

View File

@ -151,15 +151,17 @@ QgsTiledSceneRequest QgsTiledSceneLayerRenderer::createBaseRequest()
// calculate maximum screen error in METERS
const double maximumErrorPixels = context->convertToPainterUnits( mRenderer->maximumScreenError(), mRenderer->maximumScreenErrorUnit() );
// calculate width in meters across the middle of the map
// calculate width in meters across one pixel in the middle of the map
const double mapYCenter = 0.5 * ( mapExtent.yMinimum() + mapExtent.yMaximum() );
double mapWidthMeters = 0;
const double mapXCenter = 0.5 * ( mapExtent.xMinimum() + mapExtent.xMaximum() );
const double onePixelDistanceX = ( mapExtent.xMaximum() - mapExtent.xMinimum() ) / context->outputSize().width();
double mapMetersPerPixel = 0;
try
{
mapWidthMeters = context->distanceArea().measureLine(
QgsPointXY( mapExtent.xMinimum(), mapYCenter ),
QgsPointXY( mapExtent.xMaximum(), mapYCenter )
);
mapMetersPerPixel = context->distanceArea().measureLine(
QgsPointXY( mapXCenter, mapYCenter ),
QgsPointXY( mapXCenter + onePixelDistanceX, mapYCenter )
);
}
catch ( QgsCsException & )
{
@ -167,7 +169,6 @@ QgsTiledSceneRequest QgsTiledSceneLayerRenderer::createBaseRequest()
QgsDebugError( QStringLiteral( "An error occurred while calculating length" ) );
}
const double mapMetersPerPixel = mapWidthMeters / context->outputSize().width();
const double maximumErrorInMeters = maximumErrorPixels * mapMetersPerPixel;
QgsTiledSceneRequest request;