17#include "qgsvirtualpointcloudprovider.h"
29 float maximumScreenSpaceError,
30 bool showBoundingBoxes,
34 : Qgs3DMapSceneEntity( nullptr )
37 , mCoordinateTransform( coordinateTransform )
38 , mZValueScale( zValueScale )
39 , mZValueOffset( zValueOffset )
40 , mPointBudget( pointBudget )
41 , mMaximumScreenSpaceError( maximumScreenSpaceError )
42 , mShowBoundingBoxes( showBoundingBoxes )
44 mSymbol.reset( symbol );
45 mBboxesEntity =
new QgsChunkBoundsEntity(
this );
47 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
48 for (
int i = 0; i < subIndexes.size(); ++i )
50 const QgsPointCloudSubIndex &si = subIndexes.at( i );
55 createChunkedEntityForSubIndex( i );
59 connect(
this, &QgsVirtualPointCloudEntity::subIndexNeedsLoading, provider(), &QgsVirtualPointCloudProvider::loadSubIndex, Qt::QueuedConnection );
60 connect( provider(), &QgsVirtualPointCloudProvider::subIndexLoaded,
this, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );
64QList<QgsChunkedEntity *> QgsVirtualPointCloudEntity::chunkedEntities()
const
66 return mChunkedEntitiesMap.values();
69QgsVirtualPointCloudProvider *QgsVirtualPointCloudEntity::provider()
const
71 return qobject_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() );
74QgsAABB QgsVirtualPointCloudEntity::boundingBox(
int i )
const
76 return mBboxes.at( i );
79void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex(
int i )
81 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
82 const QgsPointCloudSubIndex &si = subIndexes.at( i );
85 if ( !si.index() || mBboxes.at( i ).isEmpty() )
88 QgsPointCloudLayerChunkedEntity *newChunkedEntity =
new QgsPointCloudLayerChunkedEntity( si.index(),
92 mMaximumScreenSpaceError,
98 mChunkedEntitiesMap.insert( i, newChunkedEntity );
99 newChunkedEntity->setParent(
this );
100 connect( newChunkedEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
101 emit newEntityCreated( newChunkedEntity );
104void QgsVirtualPointCloudEntity::handleSceneUpdate(
const SceneState &state )
106 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
107 for (
int i = 0; i < subIndexes.size(); ++i )
109 const QgsAABB &bbox = mBboxes.at( i );
115 constexpr int SPAN = 256;
116 const float epsilon = std::min( bbox.
xExtent(), bbox.
yExtent() ) / SPAN;
119 constexpr float THRESHOLD = .2;
123 const bool displayAsBbox = state.cameraPos.isNull() || sse < THRESHOLD;
124 if ( !displayAsBbox && !subIndexes.at( i ).index() )
125 emit subIndexNeedsLoading( i );
127 setRenderSubIndexAsBbox( i, displayAsBbox );
128 if ( !displayAsBbox && mChunkedEntitiesMap.contains( i ) )
129 mChunkedEntitiesMap[i]->handleSceneUpdate( state );
134QgsRange<float> QgsVirtualPointCloudEntity::getNearFarPlaneRange(
const QMatrix4x4 &viewMatrix )
const
139 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
141 if ( entity->isEnabled() )
143 const QgsRange<float> range = entity->getNearFarPlaneRange( viewMatrix );
144 ffar = std::max( range.
upper(), ffar );
145 fnear = std::min( range.
lower(), fnear );
150 if ( fnear == 1e9 && ffar == 0 )
152 for (
const QgsAABB &bbox : mBboxes )
157 fnear = std::min( fnear, bboxfnear );
158 ffar = std::max( ffar, bboxffar );
165int QgsVirtualPointCloudEntity::pendingJobsCount()
const
168 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
170 if ( entity->isEnabled() )
171 jobs += entity->pendingJobsCount();
176bool QgsVirtualPointCloudEntity::needsUpdate()
const
178 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
180 if ( entity->isEnabled() && entity->needsUpdate() )
186void QgsVirtualPointCloudEntity::updateBboxEntity()
188 QList<QgsAABB> bboxes;
189 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
190 for (
int i = 0; i < subIndexes.size(); ++i )
192 if ( mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->isEnabled() )
195 if ( mBboxes.at( i ).isEmpty() )
198 bboxes << mBboxes.at( i );
201 mBboxesEntity->setBoxes( bboxes );
204void QgsVirtualPointCloudEntity::setRenderSubIndexAsBbox(
int i,
bool asBbox )
206 if ( !mChunkedEntitiesMap.contains( i ) )
209 mChunkedEntitiesMap[i]->setEnabled( !asBbox );
static QgsAABB mapToWorldExtent(const QgsRectangle &extent, double zMin, double zMax, const QgsVector3D &mapOrigin)
Converts map extent to axis aligned bounding box in 3D world coordinates.
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 ...
static float screenSpaceError(float epsilon, float distance, float screenSize, float fov)
This routine approximately calculates how an error (epsilon) of an object in world coordinates at giv...
float yExtent() const
Returns box width in Y axis.
float xExtent() const
Returns box width in X axis.
bool isEmpty() const
Returns true if any of xExtent(), yExtent() or zExtent() is zero, false otherwise.
float distanceFromPoint(float x, float y, float z) const
Returns shortest distance from the box to a point.
QgsCoordinateReferenceSystem crs
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.