22#include "qgsvirtualpointcloudprovider.h"
24#include "moc_qgsvirtualpointcloudentity_p.cpp"
29QgsVirtualPointCloudEntity::QgsVirtualPointCloudEntity(
34 float maximumScreenSpaceError,
35 bool showBoundingBoxes,
40 : Qgs3DMapSceneEntity( map, nullptr )
42 , mCoordinateTransform( coordinateTransform )
43 , mZValueScale( zValueScale )
44 , mZValueOffset( zValueOffset )
45 , mPointBudget( pointBudget )
46 , mMaximumScreenSpaceError( maximumScreenSpaceError )
47 , mShowBoundingBoxes( showBoundingBoxes )
49 mSymbol.reset( symbol );
51 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
52 for (
int i = 0; i < subIndexes.size(); ++i )
54 const QgsPointCloudSubIndex &si = subIndexes.at( i );
57 mBboxes <<
QgsBox3D( intersection, si.zRange().lower(), si.zRange().upper() );
59 createChunkedEntityForSubIndex( i );
62 if ( provider()->overview() )
66 =
new QgsPointCloudLayerChunkedEntity( mapSettings(), mLayer, -2, mCoordinateTransform,
dynamic_cast<QgsPointCloud3DSymbol *
>( mSymbol->clone() ), mMaximumScreenSpaceError,
false, mZValueScale, mZValueOffset, mPointBudget );
67 mOverviewEntity->setParent(
this );
68 connect( mOverviewEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
69 connect( mOverviewEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
70 emit newEntityCreated( mOverviewEntity );
76 mBboxesEntity =
new QgsChunkBoundsEntity( boundsEntityOrigin,
this );
78 connect(
this, &QgsVirtualPointCloudEntity::subIndexNeedsLoading, provider(), &QgsVirtualPointCloudProvider::loadSubIndex, Qt::QueuedConnection );
79 connect( provider(), &QgsVirtualPointCloudProvider::subIndexLoaded,
this, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );
82QgsVirtualPointCloudEntity::~QgsVirtualPointCloudEntity()
84 qDeleteAll( mChunkedEntitiesMap );
85 mChunkedEntitiesMap.clear();
87 delete mOverviewEntity;
88 mOverviewEntity =
nullptr;
91QList<QgsChunkedEntity *> QgsVirtualPointCloudEntity::chunkedEntities()
const
93 return mChunkedEntitiesMap.values();
96QgsVirtualPointCloudProvider *QgsVirtualPointCloudEntity::provider()
const
98 return qobject_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() );
101void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex(
int i )
103 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
104 const QgsPointCloudSubIndex &si = subIndexes.at( i );
107 if ( !si.index() || mBboxes.at( i ).isEmpty() || !si.index().isValid() )
110 QgsPointCloudLayerChunkedEntity *newChunkedEntity
111 =
new QgsPointCloudLayerChunkedEntity( mapSettings(), mLayer, i, mCoordinateTransform,
static_cast<QgsPointCloud3DSymbol *
>( mSymbol->clone() ), mMaximumScreenSpaceError, mShowBoundingBoxes, mZValueScale, mZValueOffset, mPointBudget );
113 mChunkedEntitiesMap.insert( i, newChunkedEntity );
114 newChunkedEntity->setParent(
this );
115 connect( newChunkedEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
116 connect( newChunkedEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
117 emit newEntityCreated( newChunkedEntity );
120void QgsVirtualPointCloudEntity::handleSceneUpdate(
const SceneContext &sceneContext )
123 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
127 qsizetype subIndexesRendered = 0;
129 for (
int i = 0; i < subIndexes.size(); ++i )
134 bool needsUpdate = mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->needsUpdate();
136 const QgsBox3D &box3D = mBboxes.at( i );
138 if ( !needsUpdate && box3D.
isEmpty() )
146 constexpr int SPAN = 256;
147 const float epsilon =
static_cast<float>( std::min( box3D.
width(), box3D.
height() ) ) / SPAN;
148 const float distance =
static_cast<float>( box3D.
distanceTo( cameraPosMapCoords ) );
150 const double THRESHOLD = 0.2 / overviewSwitchingScale;
154 const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < static_cast<float>( THRESHOLD );
155 if ( !displayAsBbox )
157 subIndexesRendered += 1;
158 if ( !subIndexes.at( i ).index() )
159 emit subIndexNeedsLoading( i );
161 setRenderSubIndexAsBbox( i, displayAsBbox );
162 if ( !displayAsBbox && mChunkedEntitiesMap.contains( i ) )
163 mChunkedEntitiesMap[i]->handleSceneUpdate( sceneContext );
167 if ( provider()->overview()
172 if ( !mChunkedEntitiesMap.isEmpty() && subIndexesRendered == mChunkedEntitiesMap.size() )
173 mOverviewEntity->setEnabled(
false );
175 mOverviewEntity->setEnabled(
true );
176 mOverviewEntity->handleSceneUpdate( sceneContext );
180QgsRange<float> QgsVirtualPointCloudEntity::getNearFarPlaneRange(
const QMatrix4x4 &viewMatrix )
const
185 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
187 if ( entity->isEnabled() )
189 const QgsRange<float> range = entity->getNearFarPlaneRange( viewMatrix );
190 ffar = std::max( range.
upper(), ffar );
191 fnear = std::min( range.
lower(), fnear );
196 if ( fnear == 1e9 && ffar == 0 )
198 for (
const QgsBox3D &box : mBboxes )
204 fnear = std::min( fnear, bboxfnear );
205 ffar = std::max( ffar, bboxffar );
212int QgsVirtualPointCloudEntity::pendingJobsCount()
const
215 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
217 if ( entity->isEnabled() )
218 jobs += entity->pendingJobsCount();
223bool QgsVirtualPointCloudEntity::needsUpdate()
const
225 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
227 if ( entity->isEnabled() && entity->needsUpdate() )
233void QgsVirtualPointCloudEntity::updateBboxEntity()
235 QList<QgsBox3D> bboxes;
240 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
241 for (
int i = 0; i < subIndexes.size(); ++i )
243 if ( mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->isEnabled() )
246 if ( mBboxes.at( i ).isEmpty() )
249 bboxes << mBboxes.at( i );
253 mBboxesEntity->setBoxes( bboxes );
256void QgsVirtualPointCloudEntity::setRenderSubIndexAsBbox(
int i,
bool asBbox )
258 if ( !mChunkedEntitiesMap.contains( i ) )
261 mChunkedEntitiesMap[i]->setEnabled( !asBbox );
@ RenderOverviewAndExtents
Render point cloud extents over overview point cloud.
@ RenderOverview
Render overview point cloud when zoomed out.
QgsRectangle extent() const
Returns the 3D scene's 2D extent in the 3D scene's CRS.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
static bool isCullable(const QgsAABB &bbox, const QMatrix4x4 &viewProjectionMatrix)
Returns true if bbox is completely outside the current viewing volume.
static float screenSpaceError(float epsilon, float distance, int screenSize, float fov)
This routine approximately calculates how an error (epsilon) of an object in world coordinates at giv...
static QgsRectangle tryReprojectExtent2D(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs1, const QgsCoordinateReferenceSystem &crs2, const QgsCoordinateTransformContext &context)
Reprojects extent from crs1 to crs2 coordinate reference system with context context.
static void computeBoundingBoxNearFarPlanes(const QgsAABB &bbox, const QMatrix4x4 &viewMatrix, float &fnear, float &ffar)
This routine computes nearPlane farPlane from the closest and farthest corners point of bounding box ...
Axis-aligned bounding box - in world coords.
static QgsAABB fromBox3D(const QgsBox3D &box3D, const QgsVector3D &origin)
Constructs bounding box from QgsBox3D by subtracting origin 3D vector.
A 3-dimensional box composed of x, y, z coordinates.
Q_DECL_DEPRECATED double distanceTo(const QVector3D &point) const
Returns the smallest distance between the box and the point point (returns 0 if the point is inside t...
double width() const
Returns the width of the box.
double height() const
Returns the height of the box.
bool isEmpty() const
Returns true if the box is empty.
QgsCoordinateReferenceSystem crs
3D symbol that draws point cloud geometries as 3D objects.
3D renderer that renders all points from a point cloud layer.
double overviewSwitchingScale() const
Returns the overview switching scale.
Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const
Returns the renderer behavior when zoomed out.
Represents a map layer supporting display of point clouds.
A template based class for storing ranges (lower to upper values).
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
A rectangle specified with double values.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...