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() )
65 mOverviewEntity =
new QgsPointCloudLayerChunkedEntity(
71 mMaximumScreenSpaceError,
77 mOverviewEntity->setParent(
this );
78 connect( mOverviewEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
79 connect( mOverviewEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
80 emit newEntityCreated( mOverviewEntity );
86 mBboxesEntity =
new QgsChunkBoundsEntity( boundsEntityOrigin,
this );
88 connect(
this, &QgsVirtualPointCloudEntity::subIndexNeedsLoading, provider(), &QgsVirtualPointCloudProvider::loadSubIndex, Qt::QueuedConnection );
89 connect( provider(), &QgsVirtualPointCloudProvider::subIndexLoaded,
this, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );
92QgsVirtualPointCloudEntity::~QgsVirtualPointCloudEntity()
94 qDeleteAll( mChunkedEntitiesMap );
95 mChunkedEntitiesMap.clear();
97 delete mOverviewEntity;
98 mOverviewEntity =
nullptr;
101QList<QgsChunkedEntity *> QgsVirtualPointCloudEntity::chunkedEntities()
const
103 return mChunkedEntitiesMap.values();
106QgsVirtualPointCloudProvider *QgsVirtualPointCloudEntity::provider()
const
108 return qobject_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() );
111void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex(
int i )
113 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
114 const QgsPointCloudSubIndex &si = subIndexes.at( i );
117 if ( !si.index() || mBboxes.at( i ).isEmpty() || !si.index().isValid() )
120 QgsPointCloudLayerChunkedEntity *newChunkedEntity =
new QgsPointCloudLayerChunkedEntity(
124 mCoordinateTransform,
126 mMaximumScreenSpaceError,
133 mChunkedEntitiesMap.insert( i, newChunkedEntity );
134 newChunkedEntity->setParent(
this );
135 connect( newChunkedEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
136 connect( newChunkedEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
137 emit newEntityCreated( newChunkedEntity );
140void QgsVirtualPointCloudEntity::handleSceneUpdate(
const SceneContext &sceneContext )
143 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
147 qsizetype subIndexesRendered = 0;
149 for (
int i = 0; i < subIndexes.size(); ++i )
154 bool needsUpdate = mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->needsUpdate();
156 const QgsBox3D &box3D = mBboxes.at( i );
158 if ( !needsUpdate && box3D.
isEmpty() )
166 constexpr int SPAN = 256;
167 const float epsilon =
static_cast<float>( std::min( box3D.
width(), box3D.
height() ) ) / SPAN;
168 const float distance =
static_cast<float>( box3D.
distanceTo( cameraPosMapCoords ) );
170 const double THRESHOLD = 0.2 / overviewSwitchingScale;
174 const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < static_cast<float>( THRESHOLD );
175 if ( !displayAsBbox )
177 subIndexesRendered += 1;
178 if ( !subIndexes.at( i ).index() )
179 emit subIndexNeedsLoading( i );
181 setRenderSubIndexAsBbox( i, displayAsBbox );
182 if ( !displayAsBbox && mChunkedEntitiesMap.contains( i ) )
183 mChunkedEntitiesMap[i]->handleSceneUpdate( sceneContext );
190 if ( !mChunkedEntitiesMap.isEmpty() && subIndexesRendered == mChunkedEntitiesMap.size() )
191 mOverviewEntity->setEnabled(
false );
193 mOverviewEntity->setEnabled(
true );
194 mOverviewEntity->handleSceneUpdate( sceneContext );
198QgsRange<float> QgsVirtualPointCloudEntity::getNearFarPlaneRange(
const QMatrix4x4 &viewMatrix )
const
203 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
205 if ( entity->isEnabled() )
207 const QgsRange<float> range = entity->getNearFarPlaneRange( viewMatrix );
208 ffar = std::max( range.
upper(), ffar );
209 fnear = std::min( range.
lower(), fnear );
214 if ( fnear == 1e9 && ffar == 0 )
216 for (
const QgsBox3D &box : mBboxes )
222 fnear = std::min( fnear, bboxfnear );
223 ffar = std::max( ffar, bboxffar );
230int QgsVirtualPointCloudEntity::pendingJobsCount()
const
233 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
235 if ( entity->isEnabled() )
236 jobs += entity->pendingJobsCount();
241bool QgsVirtualPointCloudEntity::needsUpdate()
const
243 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
245 if ( entity->isEnabled() && entity->needsUpdate() )
251void QgsVirtualPointCloudEntity::updateBboxEntity()
253 QList<QgsBox3D> bboxes;
258 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
259 for (
int i = 0; i < subIndexes.size(); ++i )
261 if ( mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->isEnabled() )
264 if ( mBboxes.at( i ).isEmpty() )
267 bboxes << mBboxes.at( i );
271 mBboxesEntity->setBoxes( bboxes );
274void QgsVirtualPointCloudEntity::setRenderSubIndexAsBbox(
int i,
bool asBbox )
276 if ( !mChunkedEntitiesMap.contains( i ) )
279 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...