17#include "moc_qgsvirtualpointcloudentity_p.cpp"
18#include "qgsvirtualpointcloudprovider.h"
26QgsVirtualPointCloudEntity::QgsVirtualPointCloudEntity(
31 float maximumScreenSpaceError,
32 bool showBoundingBoxes,
37 : Qgs3DMapSceneEntity( map, nullptr )
39 , mCoordinateTransform( coordinateTransform )
40 , mZValueScale( zValueScale )
41 , mZValueOffset( zValueOffset )
42 , mPointBudget( pointBudget )
43 , mMaximumScreenSpaceError( maximumScreenSpaceError )
44 , mShowBoundingBoxes( showBoundingBoxes )
46 mSymbol.reset( symbol );
48 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
49 for (
int i = 0; i < subIndexes.size(); ++i )
51 const QgsPointCloudSubIndex &si = subIndexes.at( i );
54 mBboxes <<
QgsBox3D( intersection, si.zRange().lower(), si.zRange().upper() );
56 createChunkedEntityForSubIndex( i );
59 if ( provider()->overview() )
61 mOverviewEntity =
new QgsPointCloudLayerChunkedEntity(
64 provider()->overview(),
67 mMaximumScreenSpaceError,
73 mOverviewEntity->setParent(
this );
74 connect( mOverviewEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
75 connect( mOverviewEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
76 emit newEntityCreated( mOverviewEntity );
82 mBboxesEntity =
new QgsChunkBoundsEntity( boundsEntityOrigin,
this );
84 connect(
this, &QgsVirtualPointCloudEntity::subIndexNeedsLoading, provider(), &QgsVirtualPointCloudProvider::loadSubIndex, Qt::QueuedConnection );
85 connect( provider(), &QgsVirtualPointCloudProvider::subIndexLoaded,
this, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );
88QList<QgsChunkedEntity *> QgsVirtualPointCloudEntity::chunkedEntities()
const
90 return mChunkedEntitiesMap.values();
93QgsVirtualPointCloudProvider *QgsVirtualPointCloudEntity::provider()
const
95 return qobject_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() );
98void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex(
int i )
100 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
101 const QgsPointCloudSubIndex &si = subIndexes.at( i );
104 if ( !si.index() || mBboxes.at( i ).isEmpty() || !si.index().isValid() )
107 QgsPointCloudLayerChunkedEntity *newChunkedEntity =
new QgsPointCloudLayerChunkedEntity(
111 mCoordinateTransform,
113 mMaximumScreenSpaceError,
120 mChunkedEntitiesMap.insert( i, newChunkedEntity );
121 newChunkedEntity->setParent(
this );
122 connect( newChunkedEntity, &QgsChunkedEntity::pendingJobsCountChanged,
this, &Qgs3DMapSceneEntity::pendingJobsCountChanged );
123 connect( newChunkedEntity, &QgsChunkedEntity::newEntityCreated,
this, &Qgs3DMapSceneEntity::newEntityCreated );
124 emit newEntityCreated( newChunkedEntity );
127void QgsVirtualPointCloudEntity::handleSceneUpdate(
const SceneContext &sceneContext )
130 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
131 for (
int i = 0; i < subIndexes.size(); ++i )
136 bool needsUpdate = mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->needsUpdate();
138 const QgsBox3D &box3D = mBboxes.at( i );
140 if ( !needsUpdate && box3D.
isEmpty() )
148 constexpr int SPAN = 256;
149 const float epsilon =
static_cast<float>( std::min( box3D.
width(), box3D.
height() ) ) / SPAN;
150 const float distance =
static_cast<float>( box3D.
distanceTo( cameraPosMapCoords ) );
152 constexpr float THRESHOLD = .2;
156 const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < THRESHOLD;
157 if ( !displayAsBbox && !subIndexes.at( i ).index() )
158 emit subIndexNeedsLoading( i );
160 setRenderSubIndexAsBbox( i, displayAsBbox );
161 if ( !displayAsBbox && mChunkedEntitiesMap.contains( i ) )
162 mChunkedEntitiesMap[i]->handleSceneUpdate( sceneContext );
169 mOverviewEntity->handleSceneUpdate( sceneContext );
173QgsRange<float> QgsVirtualPointCloudEntity::getNearFarPlaneRange(
const QMatrix4x4 &viewMatrix )
const
178 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
180 if ( entity->isEnabled() )
182 const QgsRange<float> range = entity->getNearFarPlaneRange( viewMatrix );
183 ffar = std::max( range.
upper(), ffar );
184 fnear = std::min( range.
lower(), fnear );
189 if ( fnear == 1e9 && ffar == 0 )
191 for (
const QgsBox3D &box : mBboxes )
197 fnear = std::min( fnear, bboxfnear );
198 ffar = std::max( ffar, bboxffar );
205int QgsVirtualPointCloudEntity::pendingJobsCount()
const
208 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
210 if ( entity->isEnabled() )
211 jobs += entity->pendingJobsCount();
216bool QgsVirtualPointCloudEntity::needsUpdate()
const
218 for ( QgsChunkedEntity *entity : mChunkedEntitiesMap )
220 if ( entity->isEnabled() && entity->needsUpdate() )
226void QgsVirtualPointCloudEntity::updateBboxEntity()
228 QList<QgsBox3D> bboxes;
233 const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
234 for (
int i = 0; i < subIndexes.size(); ++i )
236 if ( mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->isEnabled() )
239 if ( mBboxes.at( i ).isEmpty() )
242 bboxes << mBboxes.at( i );
246 mBboxesEntity->setBoxes( bboxes );
249void QgsVirtualPointCloudEntity::setRenderSubIndexAsBbox(
int i,
bool asBbox )
251 if ( !mChunkedEntitiesMap.contains( i ) )
254 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 ...
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 renderer that renders all points from a point cloud layer
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.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...