Refactor QgsTessellator so that errors are stored

Instead of writing errors to QgsMessageLog and discarding, instead
make the QgsTessellator class store errors and make the callers
responsible for pushing to QgsMessageLog when appropriate.

Gives us more flexibility to show user facing tesselation errors,
eg in the processing log.
This commit is contained in:
Nyall Dawson 2024-02-05 13:51:24 +10:00
parent d4def83b3a
commit 6db11e287d
7 changed files with 46 additions and 4 deletions

View File

@ -80,6 +80,13 @@ Returns minimal Z value of the data (in world coordinates)
Returns maximal Z value of the data (in world coordinates)
.. versionadded:: 3.12
%End
QString error() const;
%Docstring
Returns a descriptive error string if the tessellation failed.
.. versionadded:: 3.34
%End
};

View File

@ -80,6 +80,13 @@ Returns minimal Z value of the data (in world coordinates)
Returns maximal Z value of the data (in world coordinates)
.. versionadded:: 3.12
%End
QString error() const;
%Docstring
Returns a descriptive error string if the tessellation failed.
.. versionadded:: 3.34
%End
};

View File

@ -15,6 +15,8 @@
#include "qgstessellatedpolygongeometry.h"
#include "qgsraycastingutils_p.h"
#include "qgsmessagelog.h"
#include <QMatrix4x4>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@ -98,6 +100,10 @@ void QgsTessellatedPolygonGeometry::setPolygons( const QList<QgsPolygon *> &poly
const float extr = extrusionHeightPerPolygon.isEmpty() ? extrusionHeight : extrusionHeightPerPolygon.at( i );
tessellator.addPolygon( *polygon, extr );
}
if ( !tessellator.error().isEmpty() )
{
QgsMessageLog::logMessage( tessellator.error(), QObject::tr( "3D" ) );
}
qDeleteAll( polygons );

View File

@ -31,6 +31,7 @@
#include "qgssimplelinematerialsettings.h"
#include "qgspolygon.h"
#include "qgsphongtexturedmaterialsettings.h"
#include "qgsmessagelog.h"
#include <Qt3DExtras/QPhongMaterial>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@ -174,6 +175,11 @@ void QgsBufferedLine3DSymbolHandler::processPolygon( QgsPolygon *polyBuffered, Q
out.triangleIndexStartingIndices.append( startingTriangleIndex );
out.triangleIndexFids.append( fid );
out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
if ( !out.tessellator->error().isEmpty() )
{
QgsMessageLog::logMessage( out.tessellator->error(), QObject::tr( "3D" ) );
}
delete polyBuffered;
}

View File

@ -39,6 +39,7 @@
#include "qgslinestring.h"
#include "qgsmultipolygon.h"
#include "qgspolygon.h"
#include "qgsmessagelog.h"
#include "qgslinevertexdata_p.h"
#include "qgslinematerial_p.h"
@ -144,6 +145,10 @@ void QgsPolygon3DSymbolHandler::processPolygon( const QgsPolygon *poly, QgsFeatu
out.triangleIndexStartingIndices.append( startingTriangleIndex );
out.triangleIndexFids.append( fid );
out.tessellator->addPolygon( *polyClone, extrusionHeight );
if ( !out.tessellator->error().isEmpty() )
{
QgsMessageLog::logMessage( out.tessellator->error(), QObject::tr( "3D" ) );
}
if ( mSymbol->materialSettings()->dataDefinedProperties().hasActiveProperties() )
processMaterialDatadefined( out.tessellator->dataVerticesCount() - oldVerticesCount, context.expressionContext(), out );

View File

@ -18,7 +18,6 @@
#include "qgscurve.h"
#include "qgsgeometryutils_base.h"
#include "qgsgeometry.h"
#include "qgsmessagelog.h"
#include "qgsmultipolygon.h"
#include "qgspoint.h"
#include "qgspolygon.h"
@ -615,7 +614,7 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
const QgsGeometry polygonSimplified = QgsGeometry( polygonNew->clone() ).simplify( 0.001 );
if ( polygonSimplified.isNull() )
{
QgsMessageLog::logMessage( QObject::tr( "geometry simplification failed - skipping" ), QObject::tr( "3D" ) );
mError = QObject::tr( "geometry simplification failed - skipping" );
return;
}
const QgsPolygon *polygonSimplifiedData = qgsgeometry_cast<const QgsPolygon *>( polygonSimplified.constGet() );
@ -623,7 +622,7 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
{
// Failed to fix that. It could be a really tiny geometry... or maybe they gave us
// geometry in unprojected lat/lon coordinates
QgsMessageLog::logMessage( QObject::tr( "geometry's coordinates are too close to each other and simplification failed - skipping" ), QObject::tr( "3D" ) );
mError = QObject::tr( "geometry's coordinates are too close to each other and simplification failed - skipping" );
return;
}
else
@ -716,9 +715,13 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
}
}
}
catch ( std::runtime_error &err )
{
mError = err.what();
}
catch ( ... )
{
QgsMessageLog::logMessage( QObject::tr( "Triangulation failed. Skipping polygon…" ), QObject::tr( "3D" ) );
mError = QObject::tr( "An unknown error occurred" );
}
for ( int i = 0; i < polylinesToDelete.count(); ++i )

View File

@ -89,6 +89,13 @@ class CORE_EXPORT QgsTessellator
*/
float zMaximum() const { return mZMax; }
/**
* Returns a descriptive error string if the tessellation failed.
*
* \since QGIS 3.34
*/
QString error() const { return mError; }
private:
void init();
@ -103,6 +110,7 @@ class CORE_EXPORT QgsTessellator
bool mNoZ = false;
int mTessellatedFacade = 3;
float mTextureRotation = 0.0f;
QString mError;
float mZMin = std::numeric_limits<float>::max();
float mZMax = -std::numeric_limits<float>::max();