Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3D] Add support for a rotated 3d scene - pointcloud support #57618

Closed
wants to merge 8 commits into from
29 changes: 28 additions & 1 deletion python/3d/auto_generated/qgs3dmapsettings.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,14 @@ Resolves references to other objects (map layers) after the call to :py:func:`~Q

QgsRectangle extent() const;
%Docstring
Returns the 3D scene's 2D extent in the 3D scene's CRS
Returns the 3D scene's 2D bounding box of the extent in the 3D scene's CRS.
If the 3D scene is not rotated, this is similar to :py:func:`~Qgs3DMapSettings.rotatedExtent`. Otherwise, this
is the bounding box of :py:func:`~Qgs3DMapSettings.rotatedExtent`.

.. seealso:: :py:func:`crs`

.. seealso:: :py:func:`rotatedExtent`

.. versionadded:: 3.30
%End

Expand Down Expand Up @@ -83,6 +87,29 @@ to improve the precision.
QgsVector3D origin() const;
%Docstring
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
%End

void setZRotation( double rotation );
%Docstring
Sets the z rotation of the 3d scene

:param rotation: the z rotation in degrees clockwise from North

.. versionadded:: 3.40
%End

double zRotation() const;
%Docstring
Returns the z rotation of the 3d scene in degrees clockwise from North.

.. versionadded:: 3.40
%End

QgsGeometry rotatedExtent() const;
%Docstring
Returns the 3D scene's 2D geometry in the 3D scene's CRS.

.. versionadded:: 3.40
%End

QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords ) const;
Expand Down
29 changes: 28 additions & 1 deletion python/PyQt6/3d/auto_generated/qgs3dmapsettings.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,14 @@ Resolves references to other objects (map layers) after the call to :py:func:`~Q

QgsRectangle extent() const;
%Docstring
Returns the 3D scene's 2D extent in the 3D scene's CRS
Returns the 3D scene's 2D bounding box of the extent in the 3D scene's CRS.
If the 3D scene is not rotated, this is similar to :py:func:`~Qgs3DMapSettings.rotatedExtent`. Otherwise, this
is the bounding box of :py:func:`~Qgs3DMapSettings.rotatedExtent`.

.. seealso:: :py:func:`crs`

.. seealso:: :py:func:`rotatedExtent`

.. versionadded:: 3.30
%End

Expand Down Expand Up @@ -83,6 +87,29 @@ to improve the precision.
QgsVector3D origin() const;
%Docstring
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
%End

void setZRotation( double rotation );
%Docstring
Sets the z rotation of the 3d scene

:param rotation: the z rotation in degrees clockwise from North

.. versionadded:: 3.40
%End

double zRotation() const;
%Docstring
Returns the z rotation of the 3d scene in degrees clockwise from North.

.. versionadded:: 3.40
%End

QgsGeometry rotatedExtent() const;
%Docstring
Returns the 3D scene's 2D geometry in the 3D scene's CRS.

.. versionadded:: 3.40
%End

QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords ) const;
Expand Down
57 changes: 52 additions & 5 deletions src/3d/qgs3dmapsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "qgs3dutils.h"
#include "qgsflatterraingenerator.h"
#include "qgsdemterraingenerator.h"
#include "qgsgeometry.h"
#include "qgsmeshterraingenerator.h"
#include "qgsonlineterraingenerator.h"
#include "qgsprojectviewsettings.h"
Expand Down Expand Up @@ -98,8 +99,11 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
, m3dAxisSettings( other.m3dAxisSettings )
, mIsDebugOverlayEnabled( other.mIsDebugOverlayEnabled )
, mExtent( other.mExtent )
, mZRotation( other.mZRotation )
, mShowExtentIn2DView( other.mShowExtentIn2DView )
{
updateRotatedExtent();

for ( QgsLightSource *source : std::as_const( other.mLightSources ) )
{
if ( source )
Expand Down Expand Up @@ -136,12 +140,14 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
elemExtent.attribute( QStringLiteral( "xMax" ) ).toDouble(),
elemExtent.attribute( QStringLiteral( "yMax" ) ).toDouble() );

mZRotation = elemExtent.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0.0" ) ).toDouble();
mShowExtentIn2DView = elemExtent.attribute( QStringLiteral( "showIn2dView" ), QStringLiteral( "0" ) ).toInt();
}
else
{
mExtent = QgsProject::instance()->viewSettings()->fullExtent();
}
updateRotatedExtent();

QDomElement elemCamera = elem.firstChildElement( QStringLiteral( "camera" ) );
if ( !elemCamera.isNull() )
Expand Down Expand Up @@ -330,6 +336,7 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
elemExtent.setAttribute( QStringLiteral( "yMin" ), mExtent.yMinimum() );
elemExtent.setAttribute( QStringLiteral( "xMax" ), mExtent.xMaximum() );
elemExtent.setAttribute( QStringLiteral( "yMax" ), mExtent.yMaximum() );
elemExtent.setAttribute( QStringLiteral( "rotation" ), mZRotation );
elemExtent.setAttribute( QStringLiteral( "showIn2dView" ), mShowExtentIn2DView );
elem.appendChild( elemExtent );

Expand Down Expand Up @@ -469,11 +476,28 @@ void Qgs3DMapSettings::setExtent( const QgsRectangle &extent )
mExtent = extent;
const QgsPointXY center = mExtent.center();
setOrigin( QgsVector3D( center.x(), center.y(), 0 ) );
if ( mTerrainGenerator )
updateRotatedExtent();
}

void Qgs3DMapSettings::setZRotation( double rotation )
{
if ( rotation == mZRotation )
{
QgsRectangle terrainExtent = Qgs3DUtils::tryReprojectExtent2D( mExtent, mCrs, mTerrainGenerator->crs(), mTransformContext );
mTerrainGenerator->setExtent( terrainExtent );
return;
}

mZRotation = rotation;
updateRotatedExtent();
}

void Qgs3DMapSettings::updateRotatedExtent()
{
mRotatedExtent = QgsGeometry::fromRect( mExtent );
mRotatedExtent.rotate( mZRotation, mExtent.center() );
mRotatedExtentBBox.setNull();

updateTerrainGeneratorExtent();

emit extentChanged();
}

Expand Down Expand Up @@ -675,9 +699,8 @@ void Qgs3DMapSettings::setTerrainGenerator( QgsTerrainGenerator *gen )
disconnect( mTerrainGenerator.get(), &QgsTerrainGenerator::terrainChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );
}

QgsRectangle terrainExtent = Qgs3DUtils::tryReprojectExtent2D( mExtent, mCrs, gen->crs(), mTransformContext );
gen->setExtent( terrainExtent );
mTerrainGenerator.reset( gen );
updateTerrainGeneratorExtent();
connect( mTerrainGenerator.get(), &QgsTerrainGenerator::terrainChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );

emit terrainGeneratorChanged();
Expand Down Expand Up @@ -1019,3 +1042,27 @@ void Qgs3DMapSettings::setShowExtentIn2DView( bool show )
mShowExtentIn2DView = show;
emit showExtentIn2DViewChanged();
}

void Qgs3DMapSettings::updateTerrainGeneratorExtent()
{
if ( mTerrainGenerator )
{
QgsRectangle terrainExtent = Qgs3DUtils::tryReprojectExtent2D( extent(), mCrs, mTerrainGenerator->crs(), mTransformContext );
mTerrainGenerator->setExtent( terrainExtent );
}
}

QgsGeometry Qgs3DMapSettings::rotatedExtent() const
{
return mRotatedExtent;
}

QgsRectangle Qgs3DMapSettings::extent() const
{
if ( mRotatedExtentBBox.isNull() )
{
mRotatedExtentBBox = rotatedExtent().boundingBox();
}

return mRotatedExtentBBox;
}
43 changes: 40 additions & 3 deletions src/3d/qgs3dmapsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsmaplayerref.h"
#include "qgsphongmaterialsettings.h"
#include "qgsrectangle.h"
#include "qgsterraingenerator.h"
#include "qgsvector3d.h"
#include "qgs3daxissettings.h"
Expand Down Expand Up @@ -68,12 +69,15 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
void resolveReferences( const QgsProject &project );

/**
* Returns the 3D scene's 2D extent in the 3D scene's CRS
* Returns the 3D scene's 2D bounding box of the extent in the 3D scene's CRS.
* If the 3D scene is not rotated, this is similar to rotatedExtent(). Otherwise, this
* is the bounding box of rotatedExtent().
*
* \see crs()
* \see rotatedExtent()
* \since QGIS 3.30
*/
QgsRectangle extent() const { return mExtent; }
QgsRectangle extent() const;

/**
* Sets the 3D scene's 2D \a extent in the 3D scene's CRS, while also setting the scene's origin to the extent's center
Expand Down Expand Up @@ -101,6 +105,28 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
//! Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
QgsVector3D origin() const { return mOrigin; }

/**
* Sets the z rotation of the 3d scene
*
* \param rotation the z rotation in degrees clockwise from North
* \since QGIS 3.40
*/
void setZRotation( double rotation );

/**
* Returns the z rotation of the 3d scene in degrees clockwise from North.
*
* \since QGIS 3.40
*/
double zRotation() const { return mZRotation; }

/**
* Returns the 3D scene's 2D geometry in the 3D scene's CRS.
*
* \since QGIS 3.40
*/
QgsGeometry rotatedExtent() const;

//! Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,-z,y))
QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords ) const;
//! Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,-z,y))
Expand Down Expand Up @@ -911,6 +937,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
//! Connects the various changed signals of this widget to the settingsChanged signal
void connectChangedSignalsToSettingsChanged();

//! Updates the terrain generator extent when the extent of the scene has changed
void updateTerrainGeneratorExtent();

//! Recomputes the extent of the scene when mExtent or mZRotation has changed
void updateRotatedExtent();

private:
//! Offset in map CRS coordinates at which our 3D world has origin (0,0,0)
QgsVector3D mOrigin;
Expand Down Expand Up @@ -973,7 +1005,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec

bool mIsDebugOverlayEnabled = false;

QgsRectangle mExtent; //!< 2d extent used to limit the 3d view
QgsRectangle mExtent; //!< 2d extent used to limit the 3d view. It does not take into account mZRotation

double mZRotation = 0.0; // extent Z rotation in degrees clockwise from North

QgsGeometry mRotatedExtent; //!< 2d extent used to limit the 3d view. It takes into account mZRotation
mutable QgsRectangle mRotatedExtentBBox; //!< The bounding box of the rotated extent

bool mShowExtentIn2DView = false;

Expand Down
Loading
Loading