Skip to content

Commit

Permalink
Add 3D VPC unit tests, fix VPC test data
Browse files Browse the repository at this point in the history
  • Loading branch information
Withalion committed Jan 17, 2025
1 parent ed511b9 commit 72f6178
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 1,018 deletions.
23 changes: 13 additions & 10 deletions src/3d/qgsvirtualpointcloudentity_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,20 @@ void QgsVirtualPointCloudEntity::handleSceneUpdate( const SceneContext &sceneCon
}
updateBboxEntity();

// reuse the same logic for showing bounding boxes as above
const QgsRectangle mapExtent = Qgs3DUtils::tryReprojectExtent2D( mMapSettings->extent(), mMapSettings->crs(), mLayer->crs(), mMapSettings->transformContext() );
const QgsAABB overviewBBox = Qgs3DUtils::mapToWorldExtent( provider()->overview().extent().intersect( mapExtent ), provider()->overview().zMin(), provider()->overview().zMax(), mMapSettings->origin() );
const float epsilon = std::min( overviewBBox.xExtent(), overviewBBox.yExtent() ) / 256;
const float distance = overviewBBox.distanceFromPoint( sceneContext.cameraPos );
const float sse = Qgs3DUtils::screenSpaceError( epsilon, distance, sceneContext.screenSizePx, sceneContext.cameraFov );
const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < .2;
const auto rendererBehavior = dynamic_cast<QgsPointCloudLayer3DRenderer *>( mLayer->renderer3D() )->zoomOutBehavior();
if ( !displayAsBbox && ( rendererBehavior == Qgis::PointCloudZoomOutRenderBehavior::RenderOverview || rendererBehavior == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) )
if ( provider()->overview() )
{
mOverviewEntity->handleSceneUpdate( sceneContext );
// reuse the same logic for showing bounding boxes as above
const QgsRectangle mapExtent = Qgs3DUtils::tryReprojectExtent2D( mMapSettings->extent(), mMapSettings->crs(), mLayer->crs(), mMapSettings->transformContext() );
const QgsAABB overviewBBox = Qgs3DUtils::mapToWorldExtent( provider()->overview().extent().intersect( mapExtent ), provider()->overview().zMin(), provider()->overview().zMax(), mMapSettings->origin() );
const float epsilon = std::min( overviewBBox.xExtent(), overviewBBox.yExtent() ) / 256;
const float distance = overviewBBox.distanceFromPoint( sceneContext.cameraPos );
const float sse = Qgs3DUtils::screenSpaceError( epsilon, distance, sceneContext.screenSizePx, sceneContext.cameraFov );
const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < .2;
const auto rendererBehavior = dynamic_cast<QgsPointCloudLayer3DRenderer *>( mLayer->renderer3D() )->zoomOutBehavior();
if ( !displayAsBbox && ( rendererBehavior == Qgis::PointCloudZoomOutRenderBehavior::RenderOverview || rendererBehavior == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) )
{
mOverviewEntity->handleSceneUpdate( sceneContext );
}
}
}

Expand Down
87 changes: 84 additions & 3 deletions tests/src/3d/testqgspointcloud3drendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
#include "qgs3dmapsettings.h"
#include "qgs3dmapscene.h"

#include <QFileInfo>
#include <QDir>

class TestQgsPointCloud3DRendering : public QgsTest
{
Q_OBJECT
Expand All @@ -58,10 +55,14 @@ class TestQgsPointCloud3DRendering : public QgsTest
void testPointCloudFilteredClassification();
void testPointCloudFilteredSceneExtent();

void testPointCloud3DExtents();
void testPointCloud3DOverview();


private:
std::unique_ptr<QgsProject> mProject;
QgsPointCloudLayer *mLayer;
QgsPointCloudLayer *mVpcLayer;
};

//runs before all tests
Expand All @@ -79,6 +80,9 @@ void TestQgsPointCloud3DRendering::initTestCase()
mLayer = new QgsPointCloudLayer( dataDir + "/point_clouds/ept/sunshine-coast-laz/ept.json", "test", "ept" );
QVERIFY( mLayer->isValid() );
mProject->addMapLayer( mLayer );
mVpcLayer = new QgsPointCloudLayer( dataDir + "/point_clouds/virtual/sunshine-coast/combined-with-overview.vpc", "test", "vpc" );
QVERIFY( mVpcLayer->isValid() );
mProject->addMapLayer( mVpcLayer );
mProject->setCrs( mLayer->crs() );

// set a default 3D renderer
Expand Down Expand Up @@ -522,5 +526,82 @@ void TestQgsPointCloud3DRendering::testPointCloudFilteredSceneExtent()
QGSVERIFYIMAGECHECK( "pointcloud_3d_filtered_scene_extent", "pointcloud_3d_filtered_scene_extent", img, QString(), 80, QSize( 0, 0 ), 15 );
}

void TestQgsPointCloud3DRendering::testPointCloud3DExtents()
{
mProject->setCrs( mVpcLayer->crs() );

Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( mVpcLayer->extent() );
map->setLayers( QList<QgsMapLayer *>() << mVpcLayer );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );

QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );

QgsClassificationPointCloud3DSymbol *symbol = new QgsClassificationPointCloud3DSymbol();
symbol->setAttribute( QStringLiteral( "Classification" ) );
symbol->setCategoriesList( QgsPointCloudClassifiedRenderer::defaultCategories() );
symbol->setPointSize( 10 );

QgsPointCloudLayer3DRenderer *renderer = new QgsPointCloudLayer3DRenderer();
renderer->setSymbol( symbol );
mVpcLayer->setRenderer3D( renderer );

scene->cameraController()->resetView( 90 );
Qgs3DUtils::captureSceneImage( engine, scene );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
const QImage img = Qgs3DUtils::captureSceneImage( engine, scene );

QGSVERIFYIMAGECHECK( "virtual_pointcloud_3d_extents", "virtual_pointcloud_3d_extents", img, QString(), 40, QSize( 0, 0 ), 55 );
}

void TestQgsPointCloud3DRendering::testPointCloud3DOverview()
{
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( mVpcLayer->extent() );
map->setLayers( QList<QgsMapLayer *>() << mVpcLayer );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );

QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );

//Classification symbol
QgsClassificationPointCloud3DSymbol *symbol = new QgsClassificationPointCloud3DSymbol();
symbol->setAttribute( QStringLiteral( "Classification" ) );
symbol->setCategoriesList( QgsPointCloudClassifiedRenderer::defaultCategories() );
symbol->setPointSize( 3 );

mVpcLayer->setRenderer3D( nullptr );
QgsPointCloudLayer3DRenderer *renderer = new QgsPointCloudLayer3DRenderer();
renderer->setSymbol( symbol );
renderer->setZoomOutBehavior( Qgis::PointCloudZoomOutRenderBehavior::RenderOverview );
mVpcLayer->setRenderer3D( renderer );

scene->cameraController()->resetView( 120 );
Qgs3DUtils::captureSceneImage( engine, scene );
// There is a bug in overview rendering, which doesn't render overview right away, it needs to get out of camera view
// and back in. Then it renders correctly
scene->cameraController()->moveView( mVpcLayer->extent().width(), mVpcLayer->extent().height() );
scene->cameraController()->resetView( 120 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
const QImage img = Qgs3DUtils::captureSceneImage( engine, scene );

QGSVERIFYIMAGECHECK( "virtual_pointcloud_3d_overview", "virtual_pointcloud_3d_overview", img, QString(), 20, QSize( 0, 0 ), 15 );
}

QGSTEST_MAIN( TestQgsPointCloud3DRendering )
#include "testqgspointcloud3drendering.moc"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified ...rer/expected_classified_render_overview/expected_classified_render_overview.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/testdata/point_clouds/virtual/sunshine-coast/0-0.copc.laz
Binary file not shown.
Binary file modified tests/testdata/point_clouds/virtual/sunshine-coast/0-1.copc.laz
Binary file not shown.
Binary file modified tests/testdata/point_clouds/virtual/sunshine-coast/1-0.copc.laz
Binary file not shown.
Binary file modified tests/testdata/point_clouds/virtual/sunshine-coast/1-1.copc.laz
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 72f6178

Please sign in to comment.