21#include "qgsvirtualpointcloudprovider.h"
23#include "moc_qgsvirtualpointcloudentity_p.cpp"
28QgsVirtualPointCloudEntity::QgsVirtualPointCloudEntity(
33 float maximumScreenSpaceError,
34 bool showBoundingBoxes,
39 : Qgs3DMapSceneEntity( map, nullptr )
41 , mCoordinateTransform( coordinateTransform )
42 , mZValueScale( zValueScale )
43 , mZValueOffset( zValueOffset )
44 , mPointBudget( pointBudget )
45 , mMaximumScreenSpaceError( maximumScreenSpaceError )
46 , mShowBoundingBoxes( showBoundingBoxes )
48 mSymbol.reset( symbol );
50 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
51 for (
int i = 0; i < subIndexes.size(); ++i )
53 const QgsPointCloudSubIndex &si = subIndexes.at( i );
56 mBboxes <<
QgsBox3D( intersection, si.zRange().lower(), si.zRange().upper() );
58 createChunkedEntityForSubIndex( i );
61 if ( provider()->overview() )
64 mOverviewEntity =
new QgsPointCloudLayerChunkedEntity(
70 mMaximumScreenSpaceError,
76 mOverviewEntity->setParent(
this );
77 connect( mOverviewEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
78 connect( mOverviewEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
79 emit newEntityCreated( mOverviewEntity );
85 mBboxesEntity =
new QgsChunkBoundsEntity( boundsEntityOrigin,
this );
87 connect(
this, &QgsVirtualPointCloudEntity::subIndexNeedsLoading, provider(), &QgsVirtualPointCloudProvider::loadSubIndex, Qt::QueuedConnection );
88 connect( provider(), &QgsVirtualPointCloudProvider::subIndexLoaded,
this, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );
91QgsVirtualPointCloudEntity::~QgsVirtualPointCloudEntity()
93 qDeleteAll( mChunkedEntitiesMap );
94 mChunkedEntitiesMap.clear();
96 delete mOverviewEntity;
97 mOverviewEntity =
nullptr;
100QList<QgsChunkedEntity *> QgsVirtualPointCloudEntity::chunkedEntities()
const
102 return mChunkedEntitiesMap.values();
105QgsVirtualPointCloudProvider *QgsVirtualPointCloudEntity::provider()
const
107 return qobject_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() );
110void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex(
int i )
112 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
113 const QgsPointCloudSubIndex &si = subIndexes.at( i );
116 if ( !si.index() || mBboxes.at( i ).isEmpty() || !si.index().isValid() )
119 QgsPointCloudLayerChunkedEntity *newChunkedEntity =
new QgsPointCloudLayerChunkedEntity(
123 mCoordinateTransform,
125 mMaximumScreenSpaceError,
132 mChunkedEntitiesMap.insert( i, newChunkedEntity );
133 newChunkedEntity->setParent(
this );
134 connect( newChunkedEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
135 connect( newChunkedEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
136 emit newEntityCreated( newChunkedEntity );
139void QgsVirtualPointCloudEntity::handleSceneUpdate(
const SceneContext &sceneContext )
142 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
146 qsizetype subIndexesRendered = 0;
148 for (
int i = 0; i < subIndexes.size(); ++i )
153 bool needsUpdate = mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->needsUpdate();
155 const QgsBox3D &box3D = mBboxes.at( i );
157 if ( !needsUpdate && box3D.
isEmpty() )
165 constexpr int SPAN = 256;
166 const float epsilon =
static_cast<float>( std::min( box3D.
width(), box3D.
height() ) ) / SPAN;
167 const float distance =
static_cast<float>( box3D.
distanceTo( cameraPosMapCoords ) );
169 const double THRESHOLD = 0.2 / overviewSwitchingScale;
173 const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < static_cast<float>( THRESHOLD );
174 if ( !displayAsBbox )
176 subIndexesRendered += 1;
177 if ( !subIndexes.at( i ).index() )
178 emit subIndexNeedsLoading( i );
180 setRenderSubIndexAsBbox( i, displayAsBbox );
181 if ( !displayAsBbox && mChunkedEntitiesMap.contains( i ) )
182 mChunkedEntitiesMap[i]->handleSceneUpdate( sceneContext );
189 if ( !mChunkedEntitiesMap.isEmpty() && subIndexesRendered == mChunkedEntitiesMap.size() )
190 mOverviewEntity->setEnabled(
false );
192 mOverviewEntity->setEnabled(
true );
193 mOverviewEntity->handleSceneUpdate( sceneContext );
197QgsRange<float> QgsVirtualPointCloudEntity::getNearFarPlaneRange(
const QMatrix4x4 &viewMatrix )
const
202 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
204 if ( entity->isEnabled() )
206 const QgsRange<float> range = entity->getNearFarPlaneRange( viewMatrix );
207 ffar = std::max( range.
upper(), ffar );
208 fnear = std::min( range.
lower(), fnear );
213 if ( fnear == 1e9 && ffar == 0 )
215 for (
const QgsBox3D &box : mBboxes )
221 fnear = std::min( fnear, bboxfnear );
222 ffar = std::max( ffar, bboxffar );
229int QgsVirtualPointCloudEntity::pendingJobsCount()
const
232 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
234 if ( entity->isEnabled() )
235 jobs += entity->pendingJobsCount();
240bool QgsVirtualPointCloudEntity::needsUpdate()
const
242 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
244 if ( entity->isEnabled() && entity->needsUpdate() )
250void QgsVirtualPointCloudEntity::updateBboxEntity()
252 QList<QgsBox3D> bboxes;
257 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
258 for (
int i = 0; i < subIndexes.size(); ++i )
260 if ( mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->isEnabled() )
263 if ( mBboxes.at( i ).isEmpty() )
266 bboxes << mBboxes.at( i );
270 mBboxesEntity->setBoxes( bboxes );
273void QgsVirtualPointCloudEntity::setRenderSubIndexAsBbox(
int i,
bool asBbox )
275 if ( !mChunkedEntitiesMap.contains( i ) )
278 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...