Skip to content

Commit

Permalink
zoom extents zooms to mMap.extent(), always above terrain and point c…
Browse files Browse the repository at this point in the history
…louds
  • Loading branch information
uclaros authored and nyalldawson committed Jan 24, 2023
1 parent adec09d commit 0f1cd83
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 74 deletions.
53 changes: 27 additions & 26 deletions src/3d/qgs3dmapscene.cpp
Expand Up @@ -250,11 +250,13 @@ Qgs3DMapScene::Qgs3DMapScene( Qgs3DMapSettings &map, QgsAbstract3DEngine *engine

void Qgs3DMapScene::viewZoomFull()
{
QgsRectangle extent = sceneExtent();
float side = std::max( extent.width(), extent.height() );
float a = side / 2.0f / std::sin( qDegreesToRadians( cameraController()->camera()->fieldOfView() ) / 2.0f );
// Note: the 1.5 multiplication is to move the view upwards to look better
mCameraController->resetView( 1.5 * std::sqrt( a * a - side * side ) ); // assuming FOV being 45 degrees
const QgsDoubleRange yRange = elevationRange();
const QgsRectangle extent = sceneExtent();
const double side = std::max( extent.width(), extent.height() );
double d = side / 2 / std::tan( qDegreesToRadians( cameraController()->camera()->fieldOfView() / 2 ) );
d += yRange.upper();
mCameraController->resetView( ( float )d );
return;
}

void Qgs3DMapScene::setViewFrom2DExtent( const QgsRectangle &extent )
Expand Down Expand Up @@ -1219,35 +1221,34 @@ QVector<const QgsChunkNode *> Qgs3DMapScene::getLayerActiveChunkNodes( QgsMapLay

QgsRectangle Qgs3DMapScene::sceneExtent()
{
QgsRectangle extent;
extent.setMinimal();
return mMap.extent();
}

for ( auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); it++ )
QgsDoubleRange Qgs3DMapScene::elevationRange() const
{
double yMin = std::numeric_limits< double >::max();
double yMax = std::numeric_limits< double >::lowest();
if ( mMap.terrainRenderingEnabled() && mTerrain )
{
QgsMapLayer *layer = it.key();
Qt3DCore::QEntity *layerEntity = it.value();
QgsChunkedEntity *c = qobject_cast<QgsChunkedEntity *>( layerEntity );
if ( !c )
continue;
QgsChunkNode *chunkNode = c->rootNode();
QgsAABB bbox = chunkNode->bbox();
QgsRectangle layerExtent = Qgs3DUtils::worldToLayerExtent( bbox, layer->crs(), mMap.origin(), mMap.crs(), mMap.transformContext() );
extent.combineExtentWith( layerExtent );
const QgsAABB bbox = mTerrain->rootNode()->bbox();
yMin = std::min( yMin, ( double )bbox.yMin );
yMax = std::max( yMax, ( double )bbox.yMax );
}

if ( mMap.terrainRenderingEnabled() )
for ( auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); it++ )
{
if ( QgsTerrainGenerator *terrainGenerator = mMap.terrainGenerator() )
QgsMapLayer *layer = it.key();
if ( layer->type() == QgsMapLayerType::PointCloudLayer )
{
QgsRectangle terrainExtent = terrainGenerator->rootChunkExtent();
QgsCoordinateTransform terrainToMapTransform( terrainGenerator->crs(), mMap.crs(), QgsProject::instance() );
terrainToMapTransform.setBallparkTransformsAreAppropriate( true );
terrainExtent = terrainToMapTransform.transformBoundingBox( terrainExtent );
extent.combineExtentWith( terrainExtent );
QgsPointCloudLayer *pcl = qobject_cast< QgsPointCloudLayer *>( layer );
QgsDoubleRange zRange = pcl->elevationProperties()->calculateZRange( pcl );
yMin = std::min( yMin, zRange.lower() );
yMax = std::max( yMax, zRange.upper() );
}
}

return extent;
const QgsDoubleRange yRange( std::min( yMin, std::numeric_limits<double>::max() ),
std::max( yMax, std::numeric_limits<double>::lowest() ) );
return yRange;
}

void Qgs3DMapScene::addCameraRotationCenterEntity( QgsCameraController *controller )
Expand Down
9 changes: 9 additions & 0 deletions src/3d/qgs3dmapscene.h
Expand Up @@ -58,6 +58,7 @@ class Qgs3DMapExportSettings;
class QgsShadowRenderingFrameGraph;
class QgsPostprocessingEntity;
class QgsChunkNode;
class QgsDoubleRange;

#define SIP_NO_FILE

Expand Down Expand Up @@ -143,6 +144,14 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
*/
QgsRectangle sceneExtent();

/**
* Returns the scene's elevation range
* \note Only terrain and point cloud layers are taken into account
*
* \since QGIS 3.30
*/
QgsDoubleRange elevationRange() const;

/**
* Returns the 3D axis object
*
Expand Down
47 changes: 1 addition & 46 deletions src/app/3d/qgs3dmapcanvas.cpp
Expand Up @@ -163,53 +163,8 @@ QgsCameraController *Qgs3DMapCanvas::cameraController()
return mScene ? mScene->cameraController() : nullptr;
}

void Qgs3DMapCanvas::resetView( bool resetExtent )
void Qgs3DMapCanvas::resetView()
{
if ( resetExtent )
{
if ( map()->terrainRenderingEnabled()
&& map()->terrainGenerator()
&& ( map()->terrainGenerator()->type() == QgsTerrainGenerator::Flat ||
map()->terrainGenerator()->type() == QgsTerrainGenerator::Online ) )
{
const QgsReferencedRectangle extent = QgsProject::instance()->viewSettings()->fullExtent();
QgsCoordinateTransform ct( extent.crs(), map()->crs(), QgsProject::instance()->transformContext() );
ct.setBallparkTransformsAreAppropriate( true );
QgsRectangle rect;
try
{
rect = ct.transformBoundingBox( extent );
}
catch ( QgsCsException & )
{
rect = extent;
}
map()->terrainGenerator()->setExtent( rect );

const QgsRectangle te = mScene->sceneExtent();
const QgsPointXY center = te.center();
map()->setOrigin( QgsVector3D( center.x(), center.y(), 0 ) );
}
if ( !map()->terrainRenderingEnabled() || !map()->terrainGenerator() )
{
const QgsReferencedRectangle extent = QgsProject::instance()->viewSettings()->fullExtent();
QgsCoordinateTransform ct( extent.crs(), map()->crs(), QgsProject::instance()->transformContext() );
ct.setBallparkTransformsAreAppropriate( true );
QgsRectangle rect;
try
{
rect = ct.transformBoundingBox( extent );
}
catch ( QgsCsException & )
{
rect = extent;
}

const QgsPointXY center = rect.center();
map()->setOrigin( QgsVector3D( center.x(), center.y(), 0 ) );
}
}

mScene->viewZoomFull();
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/3d/qgs3dmapcanvas.h
Expand Up @@ -63,7 +63,7 @@ class Qgs3DMapCanvas : public QWidget
QgsCameraController *cameraController();

//! Resets camera position to the default: looking down at the origin of world coordinates
void resetView( bool resetExtent = false );
void resetView();

//! Sets camera position to look down at the given point (in map coordinates) in given distance from plane with zero elevation
void setViewFromTop( const QgsPointXY &center, float distance, float rotation = 0 );
Expand Down
2 changes: 1 addition & 1 deletion src/app/3d/qgs3dmapcanvaswidget.cpp
Expand Up @@ -392,7 +392,7 @@ void Qgs3DMapCanvasWidget::setMainCanvas( QgsMapCanvas *canvas )

void Qgs3DMapCanvasWidget::resetView()
{
mCanvas->resetView( true );
mCanvas->resetView();
}

void Qgs3DMapCanvasWidget::configure()
Expand Down

0 comments on commit 0f1cd83

Please sign in to comment.