Skip to content

Commit

Permalink
cleanup and fix symbol nullptr bug
Browse files Browse the repository at this point in the history
  • Loading branch information
NEDJIMAbelgacem authored and wonder-sk committed Jan 13, 2021
1 parent e07a393 commit 59bb58f
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 39 deletions.
7 changes: 7 additions & 0 deletions python/core/auto_generated/geometry/qgsbox3d.sip.in
Expand Up @@ -10,6 +10,7 @@




class QgsBox3d
{
%Docstring
Expand Down Expand Up @@ -222,6 +223,12 @@ will be performed on the x/y extent of the box only.
QgsRectangle toRectangle() const;
%Docstring
Converts the box to a 2D rectangle.
%End

double distanceTo( const QVector3D &point ) const;
%Docstring
Returns the smallest distance between the box and the point ``point``
(returns 0 if the point is inside the box)
%End

bool operator==( const QgsBox3d &other ) const;
Expand Down
13 changes: 9 additions & 4 deletions src/3d/qgs3dmapscene.cpp
Expand Up @@ -41,6 +41,7 @@
#include <QOpenGLFunctions>
#include <QTimer>

#include "qgslogger.h"
#include "qgsapplication.h"
#include "qgsaabb.h"
#include "qgsabstract3dengine.h"
Expand Down Expand Up @@ -1113,17 +1114,21 @@ void Qgs3DMapScene::identifyPointCloudOnRay( QVector<QPair<QgsMapLayer *, QVecto

QRect rect = mCameraController->viewport();
int screenSizePx = std::max( rect.width(), rect.height() ); // TODO: is this correct? (see _sceneState)
float fov = mCameraController->camera()->fieldOfView();
double fov = mCameraController->camera()->fieldOfView();

for ( QgsMapLayer *layer : mMap.layers() )
{
if ( layer->type() != QgsMapLayerType::PointCloudLayer ) continue;
if ( layer->type() != QgsMapLayerType::PointCloudLayer )
continue;
if ( QgsPointCloudLayer *pc = dynamic_cast<QgsPointCloudLayer *>( layer ) )
{
QgsPointCloudLayer3DRenderer *renderer = dynamic_cast<QgsPointCloudLayer3DRenderer *>( pc->renderer3D() );
double maxScreenError = renderer->maximumScreenError();
const QgsPointCloud3DSymbol *symbol = renderer->symbol();
float pointSize = symbol->pointSize();
// Symbol can be null in case of no rendering enabled
if ( symbol == nullptr )
continue;
double maxScreenError = renderer->maximumScreenError();
double pointSize = symbol->pointSize();
double angle = pointSize / screenSizePx * mCameraController->camera()->fieldOfView();

// adjust ray to elevation properties
Expand Down
9 changes: 0 additions & 9 deletions src/3d/qgs3dmapscene.h
Expand Up @@ -60,15 +60,6 @@ class QgsPostprocessingEntity;

#define SIP_NO_FILE

//! Records some bits about the scene (context for update() method)
struct CameraState
{
QVector3D cameraPos; //!< Camera position
float cameraFov; //!< Field of view (in degrees)
int screenSizePx; //!< Size of the viewport in pixels
QMatrix4x4 viewProjectionMatrix; //!< For frustum culling
};

/**
* \ingroup 3d
* Entity that encapsulates our 3D scene - contains all other entities (such as terrain) as children.
Expand Down
9 changes: 9 additions & 0 deletions src/core/geometry/qgsbox3d.cpp
Expand Up @@ -118,6 +118,15 @@ bool QgsBox3d::contains( const QgsPoint &p ) const
return true;
}

double QgsBox3d::distanceTo( const QVector3D &point ) const
{
double dx = std::max( mBounds2d.xMinimum() - point.x(), std::max( 0., point.x() - mBounds2d.xMaximum() ) );
double dy = std::max( mBounds2d.yMinimum() - point.y(), std::max( 0., point.y() - mBounds2d.yMaximum() ) );
double dz = std::max( mZmin - point.z(), std::max( 0., point.z() - mZmax ) );
return sqrt( dx * dx + dy * dy + dz * dz );
}


bool QgsBox3d::operator==( const QgsBox3d &other ) const
{
return mBounds2d == other.mBounds2d &&
Expand Down
8 changes: 8 additions & 0 deletions src/core/geometry/qgsbox3d.h
Expand Up @@ -21,6 +21,8 @@
#include "qgis_core.h"
#include "qgsrectangle.h"

#include <QVector3D>

class QgsPoint;

/**
Expand Down Expand Up @@ -203,6 +205,12 @@ class CORE_EXPORT QgsBox3d
*/
QgsRectangle toRectangle() const { return mBounds2d; }

/**
* Returns the smallest distance between the box and the point \a point
* (returns 0 if the point is inside the box)
*/
double distanceTo( const QVector3D &point ) const;

bool operator==( const QgsBox3d &other ) const;

private:
Expand Down
13 changes: 5 additions & 8 deletions src/core/geometry/qgsray3d.cpp
Expand Up @@ -21,6 +21,11 @@ void QgsRay3D::setDirection( const QVector3D direction )
mDirection = direction;
}

QVector3D QgsRay3D::projectedPoint( const QVector3D &point ) const
{
return mOrigin + QVector3D::dotProduct( point - mOrigin, mDirection ) * mDirection;
}

bool QgsRay3D::intersectsWith( const QgsBox3d &box ) const
{
double tminX = box.xMinimum() - mOrigin.x(), tmaxX = box.xMaximum() - mOrigin.x();
Expand Down Expand Up @@ -78,11 +83,3 @@ double QgsRay3D::angleToPoint( const QVector3D &point ) const
QVector3D v2 = ( point - mOrigin ).normalized();
return qRadiansToDegrees( std::acos( std::abs( QVector3D::dotProduct( v1, v2 ) ) ) );
}

double QgsRay3D::distanceTo( const QgsBox3d &box ) const
{
double dx = std::max( box.xMinimum() - mOrigin.x(), std::max( 0., mOrigin.x() - box.xMaximum() ) );
double dy = std::max( box.yMinimum() - mOrigin.y(), std::max( 0., mOrigin.y() - box.yMaximum() ) );
double dz = std::max( box.zMinimum() - mOrigin.z(), std::max( 0., mOrigin.z() - box.zMaximum() ) );
return sqrt( dx * dx + dy * dy + dz * dz );
}
21 changes: 20 additions & 1 deletion src/core/geometry/qgsray3d.h
Expand Up @@ -5,21 +5,40 @@

#include <QVector3D>

/**
* \ingroup core
* A representation of a ray in 3D.
*
* A ray is composed of an origin point (the start of the ray) and a direction vector.
*
* \since QGIS 3.18
*/
class CORE_EXPORT QgsRay3D
{
public:
QgsRay3D( const QVector3D &origin, const QVector3D &direction );

//! Returns the origin of the ray
QVector3D origin() const { return mOrigin; }
//! Returns the direction of the ray
QVector3D direction() const { return mDirection; }

//! Sets the origin of the ray
void setOrigin( const QVector3D &origin );
//! Sets the direction of the ray
void setDirection( const QVector3D direction );

/**
* Returns the projection of the point on the ray
* (which is the closest point of the ray to \a point)
*/
QVector3D projectedPoint( const QVector3D &point ) const;
//! Checks whether the ray intersects with \a box
bool intersectsWith( const QgsBox3d &box ) const;
//! Checks whether the point is in front of the ray
bool isInFront( const QVector3D &point ) const;
//! Returns the angle between the ray and the vector from the ray's origin and the point \a point
double angleToPoint( const QVector3D &point ) const;
double distanceTo( const QgsBox3d &box ) const;

private:
QVector3D mOrigin;
Expand Down
25 changes: 8 additions & 17 deletions src/core/pointcloud/qgspointclouddataprovider.cpp
Expand Up @@ -411,13 +411,11 @@ QVector<IndexedPointCloudNode> QgsPointCloudDataProvider::traverseTree(

QVector<QVariantMap> QgsPointCloudDataProvider::getPointsOnRay( const QgsRay3D &ray, double maxScreenError, double cameraFov, int screenSizePx, double pointAngle, int pointsLimit )
{
QVector3D rayOrigin = ray.origin();
QVector3D rayDirection = ray.direction();
QVector<QVariantMap> points;
QgsPointCloudIndex *index = this->index();
IndexedPointCloudNode root = index->root();
QgsRectangle rootNodeExtentMapCoords = index->nodeMapExtent( root );
const float rootErrorInMapCoordinates = rootNodeExtentMapCoords.width() / index->span();
const double rootErrorInMapCoordinates = rootNodeExtentMapCoords.width() / index->span();

QVector<IndexedPointCloudNode> nodes = getNodesIntersectingWithRay( index, root, maxScreenError, rootErrorInMapCoordinates, cameraFov, screenSizePx, ray );

Expand Down Expand Up @@ -446,27 +444,20 @@ QVector<QVariantMap> QgsPointCloudDataProvider::getPointsOnRay( const QgsRay3D &
double x, y, z;
_pointXYZ( ptr, i, recordSize, xOffset, xType, yOffset, yType, zOffset, zType, index->scale(), index->offset(), x, y, z );
QVector3D point( x, y, z );
// project point on ray
QVector3D projectedPoint = rayOrigin + QgsVector3D::dotProduct( point - rayOrigin, rayDirection ) * rayDirection;
// check whether point is in front of the ray
bool isInFront = QgsVector3D::dotProduct( point - rayOrigin, rayDirection ) > 0.0;

if ( !isInFront )
// check whether point is in front of the ray
if ( !ray.isInFront( point ) )
continue;

// calculate the angle between the point and the projected point
QVector3D v1 = ( projectedPoint - rayOrigin ).normalized();
QVector3D v2 = ( point - rayOrigin ).normalized();
double angle = qRadiansToDegrees( std::acos( std::abs( QVector3D::dotProduct( v1, v2 ) ) ) );

if ( angle > pointAngle )
if ( ray.angleToPoint( point ) > pointAngle )
continue;

QVariantMap pointAttr = _attributeMap( ptr, i * recordSize, blockAttributes );
pointAttr[ QStringLiteral( "X" ) ] = x;
pointAttr[ QStringLiteral( "Y" ) ] = y;
pointAttr[ QStringLiteral( "Z" ) ] = z;
pointAttr[ QStringLiteral( "Distance to camera" ) ] = ( point - rayOrigin ).length();
pointAttr[ QStringLiteral( "Distance to camera" ) ] = ( point - ray.origin() ).length();
points.push_back( pointAttr );
}
}
Expand All @@ -486,8 +477,8 @@ QVector<IndexedPointCloudNode> QgsPointCloudDataProvider::getNodesIntersectingWi
QgsBox3d box( n2DExtent.xMinimum(), n2DExtent.yMinimum(), zRange.lower(), n2DExtent.xMaximum(), n2DExtent.yMaximum(), zRange.upper() );

// calculate screen space error:
float distance = ray.distanceTo( box );
float phi = nodeError * screenSizePx / ( 2 * distance * tan( cameraFov * M_PI / ( 2 * 180 ) ) );
double distance = box.distanceTo( ray.origin() );
double phi = nodeError * screenSizePx / ( 2 * distance * tan( cameraFov * M_PI / ( 2 * 180 ) ) );

if ( !ray.intersectsWith( box ) )
{
Expand All @@ -496,7 +487,7 @@ QVector<IndexedPointCloudNode> QgsPointCloudDataProvider::getNodesIntersectingWi

nodes.append( n );

float childrenError = nodeError / 2.0f;
double childrenError = nodeError / 2.0f;
if ( phi < maxError )
return nodes;

Expand Down

0 comments on commit 59bb58f

Please sign in to comment.