Skip to content

Commit

Permalink
Experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 16, 2023
1 parent 9c14539 commit 5bafc0c
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ Returns the axis aligned bounding box of the volume.
virtual QgsAbstractTiledMeshNodeBoundingVolume *clone() const = 0 /Factory/;
%Docstring
Returns a clone of the volume.
%End

virtual void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) throw( QgsCsException ) = 0;
%Docstring
Transforms the volume using the specified coordinate ``transform``.
%End

virtual QgsAbstractGeometry *as2DGeometry() const = 0 /Factory/;
%Docstring
Return a new geometry representing the 2-dimensional X/Y projection of the volume.

Caller takes ownership of the returned geometry.
%End

};
Expand Down Expand Up @@ -83,6 +95,10 @@ Constructor for QgsTiledMeshNodeBoundingVolumeRegion, with the specified ``regio

virtual QgsTiledMeshNodeBoundingVolumeRegion *clone() const ${SIP_FINAL} /Factory/;

virtual QgsAbstractGeometry *as2DGeometry() const ${SIP_FINAL} /Factory/;

virtual void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) ${SIP_FINAL} throw( QgsCsException );


QgsBox3d region() const;
%Docstring
Expand All @@ -104,7 +120,7 @@ A oriented box bounding volume for tiled mesh nodes.
%End
public:

QgsTiledMeshNodeBoundingVolumeBox( const QgsOrientedBoundingBox &box );
QgsTiledMeshNodeBoundingVolumeBox( const QgsOrientedBox3D &box );
%Docstring
Constructor for QgsTiledMeshNodeBoundingVolumeBox, with the specified oriented ``box``.
%End
Expand All @@ -115,8 +131,12 @@ Constructor for QgsTiledMeshNodeBoundingVolumeBox, with the specified oriented `

virtual QgsTiledMeshNodeBoundingVolumeBox *clone() const ${SIP_FINAL} /Factory/;

virtual QgsAbstractGeometry *as2DGeometry() const ${SIP_FINAL} /Factory/;

virtual void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) ${SIP_FINAL} throw( QgsCsException );

QgsOrientedBoundingBox box() const;

QgsOrientedBox3D box() const;
%Docstring
Returns the volume's oriented box.
%End
Expand Down Expand Up @@ -147,6 +167,10 @@ Constructor for :py:class:`QgsTiledMeshNodeBoundingVolumeBox`, with the specifie

virtual QgsTiledMeshNodeBoundingVolumeSphere *clone() const ${SIP_FINAL} /Factory/;

virtual QgsAbstractGeometry *as2DGeometry() const ${SIP_FINAL} /Factory/;

virtual void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) ${SIP_FINAL} throw( QgsCsException );


QgsSphere sphere() const;
%Docstring
Expand Down
26 changes: 9 additions & 17 deletions src/core/tiledmesh/qgscesiumtilesdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,8 @@ void QgsCesiumTilesDataProviderSharedData::setTilesetContent( const QString &til
{
mBoundingVolume = std::make_unique< QgsTiledMeshNodeBoundingVolumeRegion >( rootRegion );
mZRange = QgsDoubleRange( rootRegion.zMinimum(), rootRegion.zMaximum() );
// The latitude and longitude values are given in radians!
// TODO -- is this ALWAYS the case? What if there's a region root bounding volume, but a transform object present? What if there's crs metadata specifying a different crs?
mCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4979" ) );
const double xMin = rootRegion.xMinimum() * 180 / M_PI;
const double xMax = rootRegion.xMaximum() * 180 / M_PI;
const double yMin = rootRegion.yMinimum() * 180 / M_PI;
const double yMax = rootRegion.yMaximum() * 180 / M_PI;
mExtent = QgsRectangle( xMin, yMin, xMax, yMax );
mExtent = rootRegion.toRectangle();
}
}
else if ( rootBoundingVolume.contains( "box" ) )
Expand All @@ -81,11 +75,8 @@ void QgsCesiumTilesDataProviderSharedData::setTilesetContent( const QString &til
mBoundingVolume = std::make_unique< QgsTiledMeshNodeBoundingVolumeBox >( bbox );
const QgsBox3d rootRegion = bbox.extent();
mZRange = QgsDoubleRange( rootRegion.zMinimum(), rootRegion.zMaximum() );
const double xMin = rootRegion.xMinimum();
const double xMax = rootRegion.xMaximum();
const double yMin = rootRegion.yMinimum();
const double yMax = rootRegion.yMaximum();
mExtent = QgsRectangle( xMin, yMin, xMax, yMax );
mExtent = rootRegion.toRectangle();
mCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4978" ) );
}
}
else if ( rootBoundingVolume.contains( "sphere" ) )
Expand All @@ -96,11 +87,12 @@ void QgsCesiumTilesDataProviderSharedData::setTilesetContent( const QString &til
mBoundingVolume = std::make_unique< QgsTiledMeshNodeBoundingVolumeSphere >( sphere );
const QgsBox3d rootRegion = sphere.boundingBox();
mZRange = QgsDoubleRange( rootRegion.zMinimum(), rootRegion.zMaximum() );
const double xMin = rootRegion.xMinimum();
const double xMax = rootRegion.xMaximum();
const double yMin = rootRegion.yMinimum();
const double yMax = rootRegion.yMaximum();
mExtent = QgsRectangle( xMin, yMin, xMax, yMax );

// HMMM -- how to handle 4978 here? we need to use z coordinate for its transform to work correctly.
// Maybe we could say the layer is always in 4326??
mExtent = rootRegion.toRectangle();

mCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4978" ) );
}
}
else
Expand Down
12 changes: 8 additions & 4 deletions src/core/tiledmesh/qgscesiumutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ QgsBox3d QgsCesiumUtils::parseRegion( const json &region )
{
try
{
const double west = region[0].get<double>();
const double south = region[1].get<double>();
const double east = region[2].get<double>();
const double north = region[3].get<double>();
// The latitude and longitude values are given in radians!
// TODO -- is this ALWAYS the case? What if there's a region root bounding volume, but a transform object present? What if there's crs metadata specifying a different crs?

const double west = region[0].get<double>() * 180 / M_PI;
const double south = region[1].get<double>() * 180 / M_PI;
const double east = region[2].get<double>() * 180 / M_PI;
const double north = region[3].get<double>() * 180 / M_PI;
double minHeight = region[4].get<double>();
double maxHeight = region[5].get<double>();

return QgsBox3d( west, south, minHeight, east, north, maxHeight );
}
catch ( nlohmann::json::exception & )
Expand Down
75 changes: 74 additions & 1 deletion src/core/tiledmesh/qgstiledmeshboundingvolume.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
***************************************************************************/

#include "qgstiledmeshboundingvolume.h"
#include "qgscircle.h"
#include "qgscoordinatetransform.h"

QgsAbstractTiledMeshNodeBoundingVolume::~QgsAbstractTiledMeshNodeBoundingVolume() = default;

Expand Down Expand Up @@ -44,12 +46,36 @@ QgsTiledMeshNodeBoundingVolumeRegion *QgsTiledMeshNodeBoundingVolumeRegion::clon
return new QgsTiledMeshNodeBoundingVolumeRegion( *this );
}

QgsAbstractGeometry *QgsTiledMeshNodeBoundingVolumeRegion::as2DGeometry() const
{
std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString >(
QVector< double >() << mRegion.xMinimum()
<< mRegion.xMaximum()
<< mRegion.xMaximum()
<< mRegion.xMinimum()
<< mRegion.xMinimum(),
QVector< double >() << mRegion.yMinimum()
<< mRegion.yMinimum()
<< mRegion.yMaximum()
<< mRegion.yMaximum()
<< mRegion.yMinimum() );
std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
polygon->setExteriorRing( ext.release() );
return polygon.release();
}

void QgsTiledMeshNodeBoundingVolumeRegion::transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction )
{

}



//
// QgsTiledMeshNodeBoundingVolumeBox
//

QgsTiledMeshNodeBoundingVolumeBox::QgsTiledMeshNodeBoundingVolumeBox( const QgsOrientedBoundingBox &box )
QgsTiledMeshNodeBoundingVolumeBox::QgsTiledMeshNodeBoundingVolumeBox( const QgsOrientedBox3D &box )
: mBox( box )
{
}
Expand All @@ -69,6 +95,33 @@ QgsTiledMeshNodeBoundingVolumeBox *QgsTiledMeshNodeBoundingVolumeBox::clone() co
return new QgsTiledMeshNodeBoundingVolumeBox( *this );
}

QgsAbstractGeometry *QgsTiledMeshNodeBoundingVolumeBox::as2DGeometry() const
{
std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString >();
#if 0
QVector< double >() << mRegion.xMinimum()
<< mRegion.xMaximum()
<< mRegion.xMaximum()
<< mRegion.xMinimum()
<< mRegion.xMinimum(),
QVector< double >() << mRegion.yMinimum()
<< mRegion.yMinimum()
<< mRegion.yMaximum()
<< mRegion.yMaximum()
<< mRegion.yMinimum() );
#endif
std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
polygon->setExteriorRing( ext.release() );
return polygon.release();
}

void QgsTiledMeshNodeBoundingVolumeBox::transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction )
{

}



//
// QgsTiledMeshNodeBoundingVolumeSphere
//
Expand All @@ -93,3 +146,23 @@ QgsTiledMeshNodeBoundingVolumeSphere *QgsTiledMeshNodeBoundingVolumeSphere::clon
{
return new QgsTiledMeshNodeBoundingVolumeSphere( *this );
}

QgsAbstractGeometry *QgsTiledMeshNodeBoundingVolumeSphere::as2DGeometry() const
{
std::unique_ptr< QgsCircularString > exterior( mSphere.toCircle().toCircularString() );
std::unique_ptr< QgsCurvePolygon > polygon = std::make_unique< QgsCurvePolygon >();
polygon->setExteriorRing( exterior.release() );
polygon->addZValue( mSphere.centerZ() );
return polygon.release();
}

void QgsTiledMeshNodeBoundingVolumeSphere::transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction )
{
// hmmm maybe the transform argument should be used by as2DGeometry...!
// other types won't be as easy to handle as spheres...
double x = mSphere.centerX();
double y = mSphere.centerY();
double z = mSphere.centerZ();
transform.transformInPlace( x, y, z, direction );
mSphere = QgsSphere( x, y, z, mSphere.radius() );
}
26 changes: 22 additions & 4 deletions src/core/tiledmesh/qgstiledmeshboundingvolume.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "qgis.h"
#include "qgsbox3d.h"
#include "qgssphere.h"
#include "qgscesiumutils.h"
#include "qgsorientedbox3d.h"

/**
* \ingroup core
Expand Down Expand Up @@ -73,6 +73,18 @@ class CORE_EXPORT QgsAbstractTiledMeshNodeBoundingVolume
*/
virtual QgsAbstractTiledMeshNodeBoundingVolume *clone() const = 0 SIP_FACTORY;

/**
* Transforms the volume using the specified coordinate \a transform.
*/
virtual void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) SIP_THROW( QgsCsException ) = 0;

/**
* Return a new geometry representing the 2-dimensional X/Y projection of the volume.
*
* Caller takes ownership of the returned geometry.
*/
virtual QgsAbstractGeometry *as2DGeometry() const = 0 SIP_FACTORY;

};

/**
Expand All @@ -93,6 +105,8 @@ class CORE_EXPORT QgsTiledMeshNodeBoundingVolumeRegion : public QgsAbstractTiled
Qgis::TiledMeshBoundingVolumeType type() const FINAL;
QgsBox3d bounds() const FINAL;
QgsTiledMeshNodeBoundingVolumeRegion *clone() const FINAL SIP_FACTORY;
QgsAbstractGeometry *as2DGeometry() const FINAL SIP_FACTORY;
void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) FINAL SIP_THROW( QgsCsException );

/**
* Returns the volume's region.
Expand All @@ -116,20 +130,22 @@ class CORE_EXPORT QgsTiledMeshNodeBoundingVolumeBox : public QgsAbstractTiledMes
/**
* Constructor for QgsTiledMeshNodeBoundingVolumeBox, with the specified oriented \a box.
*/
QgsTiledMeshNodeBoundingVolumeBox( const QgsOrientedBoundingBox &box );
QgsTiledMeshNodeBoundingVolumeBox( const QgsOrientedBox3D &box );

Qgis::TiledMeshBoundingVolumeType type() const FINAL;
QgsBox3d bounds() const FINAL;
QgsTiledMeshNodeBoundingVolumeBox *clone() const FINAL SIP_FACTORY;
QgsAbstractGeometry *as2DGeometry() const FINAL SIP_FACTORY;
void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) FINAL SIP_THROW( QgsCsException );

/**
* Returns the volume's oriented box.
*/
QgsOrientedBoundingBox box() const { return mBox; }
QgsOrientedBox3D box() const { return mBox; }

private:

QgsOrientedBoundingBox mBox;
QgsOrientedBox3D mBox;

};

Expand All @@ -151,6 +167,8 @@ class CORE_EXPORT QgsTiledMeshNodeBoundingVolumeSphere: public QgsAbstractTiledM
Qgis::TiledMeshBoundingVolumeType type() const FINAL;
QgsBox3d bounds() const FINAL;
QgsTiledMeshNodeBoundingVolumeSphere *clone() const FINAL SIP_FACTORY;
QgsAbstractGeometry *as2DGeometry() const FINAL SIP_FACTORY;
void transform( const QgsCoordinateTransform &transform, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward ) FINAL SIP_THROW( QgsCsException );

/**
* Returns the volume's sphere.
Expand Down
43 changes: 43 additions & 0 deletions src/core/tiledmesh/qgstiledmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@


#include "qgstiledmeshlayerrenderer.h"
#include "qgscurve.h"
#include "qgstiledmeshboundingvolume.h"
#include "qgstiledmeshlayer.h"
#include "qgsfeedback.h"
#include "qgsmapclippingutils.h"
#include "qgsrendercontext.h"
#include "qgscurvepolygon.h"
#include "qgsfillsymbol.h"

QgsTiledMeshLayerRenderer::QgsTiledMeshLayerRenderer( QgsTiledMeshLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )
Expand All @@ -32,6 +36,8 @@ QgsTiledMeshLayerRenderer::QgsTiledMeshLayerRenderer( QgsTiledMeshLayer *layer,
return;

mClippingRegions = QgsMapClippingUtils::collectClippingRegionsForLayer( *renderContext(), layer );
if ( const QgsAbstractTiledMeshNodeBoundingVolume *layerBoundingVolume = layer->dataProvider()->boundingVolume() )
mLayerBoundingVolume.reset( layerBoundingVolume->clone() );

mReadyToCompose = false;
}
Expand Down Expand Up @@ -62,6 +68,43 @@ bool QgsTiledMeshLayerRenderer::render()
mElapsedTimer.start();
}

if ( mLayerBoundingVolume )
{
const QgsCoordinateTransform transform = renderContext()->coordinateTransform();
try
{
mLayerBoundingVolume->transform( transform );
std::unique_ptr< QgsAbstractGeometry > rootBoundsGeometry( mLayerBoundingVolume->as2DGeometry() );
QgsDebugError( rootBoundsGeometry->asWkt( ) );
if ( QgsCurvePolygon *polygon = qgsgeometry_cast< QgsCurvePolygon * >( rootBoundsGeometry.get() ) )
{
QPolygonF rootBoundsPoly = polygon->exteriorRing()->asQPolygonF();

// remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
rootBoundsPoly.erase( std::remove_if( rootBoundsPoly.begin(), rootBoundsPoly.end(),
[]( const QPointF point )
{
return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
} ), rootBoundsPoly.end() );

QPointF *ptr = rootBoundsPoly.data();
for ( int i = 0; i < rootBoundsPoly.size(); ++i, ++ptr )
{
renderContext()->mapToPixel().transformInPlace( ptr->rx(), ptr->ry() );
}

QgsFillSymbol fillSymbol;
fillSymbol.startRender( *renderContext() );
fillSymbol.renderPolygon( rootBoundsPoly, nullptr, nullptr, *renderContext() );
fillSymbol.stopRender( *renderContext() );
}
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "Error transforming root bounding volume" ) );
}
}

mReadyToCompose = true;
return false;
}
Expand Down
Loading

0 comments on commit 5bafc0c

Please sign in to comment.