Skip to content

Commit

Permalink
Node experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 17, 2023
1 parent a64083a commit 67b2695
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,61 @@




class QgsTiledMeshNode
{
%Docstring(signature="appended")
*************************************************************************

This program is free software; you can redistribute it and/or modify *
it under the terms of the GNU General Public License as published by *
the Free Software Foundation; either version 2 of the License, or *
(at your option) any later version. *

**************************************************************************
%End

%TypeHeaderCode
#include "qgstiledmeshdataprovider.h"
%End
public:

QgsTiledMeshNode();
%Docstring
Constructor for an empty node.
%End

QgsTiledMeshNode( const QgsTiledMeshNode &other );

QgsTiledMeshNode( QgsTiledMeshNode *parent );
%Docstring
Constructor for a valid node.
%End

bool operator==( QgsTiledMeshNode other ) const;

void addChild( QgsTiledMeshNode *child /Transfer/ );

void setBoundingVolume( QgsAbstractTiledMeshNodeBoundingVolume *volume /Transfer/ );

QgsTiledMeshNode *parentNode() const;
%Docstring
Returns the parent of the node.
%End

QList< QgsTiledMeshNode * > children() const;
%Docstring
Returns the child nodes.
%End

const QgsAbstractTiledMeshNodeBoundingVolume *boundingVolume() const;
%Docstring
Returns the bounding volume for the node.
%End

};


class QgsTiledMeshDataProvider: QgsDataProvider
{
%Docstring(signature="appended")
Expand Down Expand Up @@ -79,6 +134,8 @@ This corresponds to the root node bounding volume.
Coordinates in the returned volume are in the :py:func:`~QgsTiledMeshDataProvider.meshCrs` reference system, not the :py:func:`QgsDataProvider.crs()` system.
%End

virtual const QgsTiledMeshNode *rootNode() const = 0;

};

/************************************************************************
Expand Down
59 changes: 59 additions & 0 deletions src/core/tiledmesh/qgscesiumtilesdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,58 @@ void QgsCesiumTilesDataProviderSharedData::setTilesetContent( const QString &til
QgsDebugError( QStringLiteral( "unsupported boundingVolume format" ) );
}
}

std::function< QgsTiledMeshNode *( const json &json, QgsTiledMeshNode *parent ) > addNodeFromJson;
addNodeFromJson = [&addNodeFromJson]( const json & json, QgsTiledMeshNode * parent ) -> QgsTiledMeshNode *
{
QgsTiledMeshNode *node = new QgsTiledMeshNode( parent );

const auto &boundingVolume = json[ "boundingVolume" ];
if ( boundingVolume.contains( "region" ) )
{
const QgsBox3d rootRegion = QgsCesiumUtils::parseRegion( boundingVolume[ "region" ] );
if ( !rootRegion.isNull() )
{
node->setBoundingVolume( new QgsTiledMeshNodeBoundingVolumeRegion( rootRegion ) );
}
}
else if ( boundingVolume.contains( "box" ) )
{
const QgsOrientedBox3D bbox = QgsCesiumUtils::parseBox( boundingVolume["box"] );
if ( !bbox.isNull() )
{
node->setBoundingVolume( new QgsTiledMeshNodeBoundingVolumeBox( bbox ) );
}
}
else if ( boundingVolume.contains( "sphere" ) )
{
const QgsSphere sphere = QgsCesiumUtils::parseSphere( boundingVolume["sphere"] );
if ( !sphere.isNull() )
{
node->setBoundingVolume( new QgsTiledMeshNodeBoundingVolumeSphere( sphere ) );
}
}
else
{
QgsDebugError( QStringLiteral( "unsupported boundingVolume format" ) );
}

if ( json.contains( "children" ) )
{
for ( const auto &childJson : json["children"] )
{
addNodeFromJson( childJson, node );
}
}

if ( parent )
parent->addChild( node );

return node;
};

mRootNode.reset( addNodeFromJson( mTileset[ "root" ], nullptr ) );

}
}

Expand Down Expand Up @@ -341,6 +393,13 @@ const QgsAbstractTiledMeshNodeBoundingVolume *QgsCesiumTilesDataProvider::boundi
return mShared ? mShared->mBoundingVolume.get() : nullptr;
}

const QgsTiledMeshNode *QgsCesiumTilesDataProvider::rootNode() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS

return mShared ? mShared->mRootNode.get() : nullptr;
}


//
// QgsCesiumTilesProviderMetadata
Expand Down
5 changes: 4 additions & 1 deletion src/core/tiledmesh/qgscesiumtilesdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class QgsCesiumTilesDataProviderSharedData
QgsCoordinateReferenceSystem mMeshCrs;
std::unique_ptr< QgsAbstractTiledMeshNodeBoundingVolume > mBoundingVolume;

std::unique_ptr< QgsTiledMeshNode > mRootNode;

QgsRectangle mExtent;
nlohmann::json mTileset;
QgsDoubleRange mZRange;
Expand Down Expand Up @@ -75,7 +77,8 @@ class CORE_EXPORT QgsCesiumTilesDataProvider final: public QgsTiledMeshDataProvi
QString description() const final;
QString htmlMetadata() const final;
const QgsCoordinateReferenceSystem meshCrs() const final;
const QgsAbstractTiledMeshNodeBoundingVolume *boundingVolume() const override;
const QgsAbstractTiledMeshNodeBoundingVolume *boundingVolume() const final;
virtual const QgsTiledMeshNode *rootNode() const final;

private:

Expand Down
1 change: 1 addition & 0 deletions src/core/tiledmesh/qgstiledmeshboundingvolume.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "qgscircle.h"
#include "qgscoordinatetransform.h"
#include "qgsvector3d.h"
#include "qgslogger.h"

QgsAbstractTiledMeshNodeBoundingVolume::~QgsAbstractTiledMeshNodeBoundingVolume() = default;

Expand Down
46 changes: 46 additions & 0 deletions src/core/tiledmesh/qgstiledmeshdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "qgstiledmeshdataprovider.h"
#include "qgsthreadingutils.h"
#include "qgstiledmeshboundingvolume.h"

QgsTiledMeshDataProvider::QgsTiledMeshDataProvider(
const QString &uri,
Expand Down Expand Up @@ -47,3 +48,48 @@ QString QgsTiledMeshDataProvider::htmlMetadata() const

return QString();
}

QgsTiledMeshNode::QgsTiledMeshNode()
{

}

QgsTiledMeshNode::QgsTiledMeshNode( const QgsTiledMeshNode &other )
: mParent( other.mParent )
{
for ( const QgsTiledMeshNode *node : other.mChildren )
{
QgsTiledMeshNode *newNode = new QgsTiledMeshNode( *node );
newNode->mParent = this;
mChildren.append( newNode );
}
mBoundingVolume.reset( other.mBoundingVolume ? other.mBoundingVolume->clone() : nullptr );
}

QgsTiledMeshNode &QgsTiledMeshNode::operator=( const QgsTiledMeshNode &other )
{
mParent = other.mParent;
for ( const QgsTiledMeshNode *node : other.mChildren )
{
QgsTiledMeshNode *newNode = new QgsTiledMeshNode( *node );
newNode->mParent = this;
mChildren.append( newNode );
}
mBoundingVolume.reset( other.mBoundingVolume ? other.mBoundingVolume->clone() : nullptr );
}

QgsTiledMeshNode::QgsTiledMeshNode( QgsTiledMeshNode *parent )
: mParent( parent )
{

}

void QgsTiledMeshNode::setBoundingVolume( QgsAbstractTiledMeshNodeBoundingVolume *volume )
{
mBoundingVolume.reset( volume );
}

const QgsAbstractTiledMeshNodeBoundingVolume *QgsTiledMeshNode::boundingVolume() const
{
return mBoundingVolume.get();
}
56 changes: 56 additions & 0 deletions src/core/tiledmesh/qgstiledmeshdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,60 @@

class QgsAbstractTiledMeshNodeBoundingVolume;


class CORE_EXPORT QgsTiledMeshNode
{
public:

/**
* Constructor for an empty node.
*/
QgsTiledMeshNode();

QgsTiledMeshNode( const QgsTiledMeshNode &other );
QgsTiledMeshNode &operator=( const QgsTiledMeshNode &other );

/**
* Constructor for a valid node.
*/
QgsTiledMeshNode( QgsTiledMeshNode *parent );

bool operator==( QgsTiledMeshNode other ) const
{
return false;
}

void addChild( QgsTiledMeshNode *child SIP_TRANSFER )
{
child->mParent = this;
mChildren.append( child );
}

void setBoundingVolume( QgsAbstractTiledMeshNodeBoundingVolume *volume SIP_TRANSFER );

/**
* Returns the parent of the node.
*/
QgsTiledMeshNode *parentNode() const { return mParent; }

/**
* Returns the child nodes.
*/
QList< QgsTiledMeshNode * > children() const { return mChildren; }

/**
* Returns the bounding volume for the node.
*/
const QgsAbstractTiledMeshNodeBoundingVolume *boundingVolume() const;

private:
QgsTiledMeshNode *mParent = nullptr;
QList< QgsTiledMeshNode * > mChildren;
std::unique_ptr< QgsAbstractTiledMeshNodeBoundingVolume > mBoundingVolume;

};


/**
* \ingroup core
* \brief Base class for data providers for QgsTiledMeshLayer
Expand Down Expand Up @@ -90,6 +144,8 @@ class CORE_EXPORT QgsTiledMeshDataProvider: public QgsDataProvider
*/
virtual const QgsAbstractTiledMeshNodeBoundingVolume *boundingVolume() const = 0;

virtual const QgsTiledMeshNode *rootNode() const = 0;

};

#endif // QGSTILEDMESHDATAPROVIDER_H
65 changes: 40 additions & 25 deletions src/core/tiledmesh/qgstiledmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ QgsTiledMeshLayerRenderer::QgsTiledMeshLayerRenderer( QgsTiledMeshLayer *layer,
if ( const QgsAbstractTiledMeshNodeBoundingVolume *layerBoundingVolume = layer->dataProvider()->boundingVolume() )
mLayerBoundingVolume.reset( layerBoundingVolume->clone() );

mRootNode.reset( new QgsTiledMeshNode( *layer->dataProvider()->rootNode() ) );

mReadyToCompose = false;
}

Expand Down Expand Up @@ -70,39 +72,52 @@ bool QgsTiledMeshLayerRenderer::render()
mElapsedTimer.start();
}

if ( mLayerBoundingVolume )
if ( mRootNode )
{
const QgsCoordinateTransform transform = QgsCoordinateTransform( mMeshCrs, renderContext()->coordinateTransform().destinationCrs(), renderContext()->transformContext() );
try

std::function< void ( const QgsTiledMeshNode * )> renderNode;
renderNode = [&renderNode, transform, this]( const QgsTiledMeshNode * node )
{
std::unique_ptr< QgsAbstractGeometry > rootBoundsGeometry( mLayerBoundingVolume->as2DGeometry( transform ) );
if ( QgsCurvePolygon *polygon = qgsgeometry_cast< QgsCurvePolygon * >( rootBoundsGeometry.get() ) )
const QgsAbstractTiledMeshNodeBoundingVolume *volume = node->boundingVolume();
try
{
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 )
std::unique_ptr< QgsAbstractGeometry > volumeGeometry( volume->as2DGeometry( transform ) );
if ( QgsCurvePolygon *polygon = qgsgeometry_cast< QgsCurvePolygon * >( volumeGeometry.get() ) )
{
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() );
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() );
}

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

QgsLineSymbol symbol;
symbol.startRender( *renderContext() );
symbol.renderPolyline( rootBoundsPoly, nullptr, *renderContext() );
symbol.stopRender( *renderContext() );
for ( QgsTiledMeshNode *child : node->children() )
{
renderNode( child );
}
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "Error transforming root bounding volume" ) );
}
};

renderNode( mRootNode.get() );
}

mReadyToCompose = true;
Expand Down
Loading

0 comments on commit 67b2695

Please sign in to comment.