From fce4b276441747b977e3adcc6fd97fa2d204ba77 Mon Sep 17 00:00:00 2001 From: Peter Petrik Date: Thu, 17 Sep 2020 10:44:58 +0200 Subject: [PATCH] fix #35147 QgsMeshLayer map canvas rotation rendering (#38795) fix #35147 QgsMeshLayer map canvas rotation rendering --- .../core/auto_generated/qgsmaptopixel.sip.in | 2 +- src/core/mesh/qgsmeshlayerrenderer.cpp | 11 ++--- src/core/mesh/qgsmeshlayerutils.cpp | 46 +++++++++++++----- src/core/mesh/qgsmeshlayerutils.h | 23 +++++++-- src/core/mesh/qgsmeshtracerenderer.cpp | 32 ++++++------ src/core/mesh/qgsmeshtracerenderer.h | 5 +- src/core/mesh/qgsmeshvectorrenderer.cpp | 10 +++- src/core/qgsmaptopixel.h | 2 +- tests/src/core/testqgsmeshlayerrenderer.cpp | 23 +++++++-- ...d_lines_edge_scalar_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...d_lines_edge_vector_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...lines_vertex_scalar_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...lines_vertex_vector_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...riangle_face_scalar_dataset_rotated_45.png | Bin 0 -> 471523 bytes ...riangle_face_vector_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...ce_vector_user_grid_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...er_grid_dataset_streamlines_rotated_45.png | Bin 0 -> 471523 bytes ...ad_and_triangle_native_mesh_rotated_45.png | Bin 0 -> 80307 bytes ...nd_triangle_triangular_mesh_rotated_45.png | Bin 0 -> 80307 bytes ...angle_vertex_scalar_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...angle_vertex_vector_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...iangle_vertex_vector_traces_rotated_45.png | Bin 0 -> 80307 bytes ...ex_vector_user_grid_dataset_rotated_45.png | Bin 0 -> 80307 bytes ...er_grid_dataset_streamlines_rotated_45.png | Bin 0 -> 80307 bytes 24 files changed, 106 insertions(+), 48 deletions(-) create mode 100644 tests/testdata/control_images/mesh/expected_lines_edge_scalar_dataset_rotated_45/expected_lines_edge_scalar_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_lines_edge_vector_dataset_rotated_45/expected_lines_edge_vector_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_lines_vertex_scalar_dataset_rotated_45/expected_lines_vertex_scalar_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_lines_vertex_vector_dataset_rotated_45/expected_lines_vertex_vector_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_face_scalar_dataset_rotated_45/expected_quad_and_triangle_face_scalar_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_dataset_rotated_45/expected_quad_and_triangle_face_vector_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset_rotated_45/expected_quad_and_triangle_face_vector_user_grid_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45/expected_quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_native_mesh_rotated_45/expected_quad_and_triangle_native_mesh_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_triangular_mesh_rotated_45/expected_quad_and_triangle_triangular_mesh_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_scalar_dataset_rotated_45/expected_quad_and_triangle_vertex_scalar_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_dataset_rotated_45/expected_quad_and_triangle_vertex_vector_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_traces_rotated_45/expected_quad_and_triangle_vertex_vector_traces_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45/expected_quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45.png create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_user_grid_dataset_streamlines_rotated_45/expected_quad_and_triangle_vertex_vector_user_grid_dataset_streamlines_rotated_45.png diff --git a/python/core/auto_generated/qgsmaptopixel.sip.in b/python/core/auto_generated/qgsmaptopixel.sip.in index 06dab2fd41a8..5143785e742f 100644 --- a/python/core/auto_generated/qgsmaptopixel.sip.in +++ b/python/core/auto_generated/qgsmaptopixel.sip.in @@ -161,7 +161,7 @@ Set map rotation in degrees (clockwise) double mapRotation() const; %Docstring -Returns current map rotation in degrees +Returns current map rotation in degrees (clockwise) .. versionadded:: 2.8 %End diff --git a/src/core/mesh/qgsmeshlayerrenderer.cpp b/src/core/mesh/qgsmeshlayerrenderer.cpp index 38ed7150e8d0..5063b15fe3d9 100644 --- a/src/core/mesh/qgsmeshlayerrenderer.cpp +++ b/src/core/mesh/qgsmeshlayerrenderer.cpp @@ -99,12 +99,11 @@ void QgsMeshLayerRenderer::calculateOutputSize() { // figure out image size QgsRenderContext &context = *renderContext(); - QgsRectangle extent = context.mapExtent(); - QgsMapToPixel mapToPixel = context.mapToPixel(); - QgsPointXY topleft = mapToPixel.transform( extent.xMinimum(), extent.yMaximum() ); - QgsPointXY bottomright = mapToPixel.transform( extent.xMaximum(), extent.yMinimum() ); - int width = int( bottomright.x() - topleft.x() ); - int height = int( bottomright.y() - topleft.y() ); + const QgsRectangle extent = context.mapExtent(); + const QgsMapToPixel mapToPixel = context.mapToPixel(); + const QgsRectangle screenBBox = QgsMeshLayerUtils::boundingBoxToScreenRectangle( mapToPixel, extent ); + int width = int( screenBBox.width() ); + int height = int( screenBBox.height() ); mOutputSize = QSize( width, height ); } diff --git a/src/core/mesh/qgsmeshlayerutils.cpp b/src/core/mesh/qgsmeshlayerutils.cpp index 16aa0af2659f..f9a759bdfa99 100644 --- a/src/core/mesh/qgsmeshlayerutils.cpp +++ b/src/core/mesh/qgsmeshlayerutils.cpp @@ -197,20 +197,40 @@ QVector QgsMeshLayerUtils::calculateMagnitudes( const QgsMeshDataBlock & return ret; } -void QgsMeshLayerUtils::boundingBoxToScreenRectangle( const QgsMapToPixel &mtp, - const QSize &outputSize, - const QgsRectangle &bbox, - int &leftLim, - int &rightLim, - int &topLim, - int &bottomLim ) +QgsRectangle QgsMeshLayerUtils::boundingBoxToScreenRectangle( + const QgsMapToPixel &mtp, + const QgsRectangle &bbox +) { - QgsPointXY ll = mtp.transform( bbox.xMinimum(), bbox.yMinimum() ); - QgsPointXY ur = mtp.transform( bbox.xMaximum(), bbox.yMaximum() ); - topLim = std::max( int( ur.y() ), 0 ); - bottomLim = std::min( int( ll.y() ), outputSize.height() - 1 ); - leftLim = std::max( int( ll.x() ), 0 ); - rightLim = std::min( int( ur.x() ), outputSize.width() - 1 ); + const QgsPointXY topLeft = mtp.transform( bbox.xMinimum(), bbox.yMaximum() ); + const QgsPointXY topRight = mtp.transform( bbox.xMaximum(), bbox.yMaximum() ); + const QgsPointXY bottomLeft = mtp.transform( bbox.xMinimum(), bbox.yMinimum() ); + const QgsPointXY bottomRight = mtp.transform( bbox.xMaximum(), bbox.yMinimum() ); + + double xMin = std::min( {topLeft.x(), topRight.x(), bottomLeft.x(), bottomRight.x()} ); + double xMax = std::max( {topLeft.x(), topRight.x(), bottomLeft.x(), bottomRight.x()} ); + double yMin = std::min( {topLeft.y(), topRight.y(), bottomLeft.y(), bottomRight.y()} ); + double yMax = std::max( {topLeft.y(), topRight.y(), bottomLeft.y(), bottomRight.y()} ); + + QgsRectangle ret( xMin, yMin, xMax, yMax ); + return ret; +} + +void QgsMeshLayerUtils::boundingBoxToScreenRectangle( + const QgsMapToPixel &mtp, + const QSize &outputSize, + const QgsRectangle &bbox, + int &leftLim, + int &rightLim, + int &bottomLim, + int &topLim ) +{ + const QgsRectangle screenBBox = boundingBoxToScreenRectangle( mtp, bbox ); + + bottomLim = std::max( int( screenBBox.yMinimum() ), 0 ); + topLim = std::min( int( screenBBox.yMaximum() ), outputSize.height() - 1 ); + leftLim = std::max( int( screenBBox.xMinimum() ), 0 ); + rightLim = std::min( int( screenBBox.xMaximum() ), outputSize.width() - 1 ); } static void lamTol( double &lam ) diff --git a/src/core/mesh/qgsmeshlayerutils.h b/src/core/mesh/qgsmeshlayerutils.h index ffbe3e53c0c2..39e28f75bf26 100644 --- a/src/core/mesh/qgsmeshlayerutils.h +++ b/src/core/mesh/qgsmeshlayerutils.h @@ -115,16 +115,29 @@ class CORE_EXPORT QgsMeshLayerUtils * \param mtp actual renderer map to pixel * \param outputSize actual renderer output size * \param bbox bounding box in map coordinates - * \param leftLim minimum x coordinate in pixel - * \param rightLim maximum x coordinate in pixel - * \param topLim minimum y coordinate in pixel - * \param bottomLim maximum y coordinate in pixel + * \param leftLim minimum x coordinate in pixel, clipped by 0 + * \param rightLim maximum x coordinate in pixel, clipped by outputSize width + * \param bottomLim minimum y coordinate in pixel, clipped by 0 + * \param topLim maximum y coordinate in pixel, clipped by outputSize height */ static void boundingBoxToScreenRectangle( const QgsMapToPixel &mtp, const QSize &outputSize, const QgsRectangle &bbox, - int &leftLim, int &rightLim, int &topLim, int &bottomLim ); + int &leftLim, + int &rightLim, + int &bottomLim, + int &topLim ); + + /** + * Transformes the bounding box to rectangle in screen coordinates (in pixels) + * \param mtp actual renderer map to pixel + * \param bbox bounding box in map coordinates + */ + static QgsRectangle boundingBoxToScreenRectangle( + const QgsMapToPixel &mtp, + const QgsRectangle &bbox + ); /** * Interpolates value based on known values on the vertices of a edge diff --git a/src/core/mesh/qgsmeshtracerenderer.cpp b/src/core/mesh/qgsmeshtracerenderer.cpp index 2e91427c57c3..dfb4a8f22ba6 100644 --- a/src/core/mesh/qgsmeshtracerenderer.cpp +++ b/src/core/mesh/qgsmeshtracerenderer.cpp @@ -19,6 +19,11 @@ #include "qgsmeshlayerrenderer.h" ///@cond PRIVATE +#ifndef M_DEG2RAD +#define M_DEG2RAD 0.0174532925 +#endif + + QgsVector QgsMeshVectorValueInterpolator::vectorValue( const QgsPointXY &point ) const { if ( mCacheFaceIndex != -1 && mCacheFaceIndex < mTriangularMesh.triangles().count() ) @@ -268,7 +273,7 @@ void QgsMeshStreamField::updateSize( const QgsRenderContext &renderContext ) } catch ( QgsCsException &cse ) { - Q_UNUSED( cse ); + Q_UNUSED( cse ) //if the transform fails, consider the whole map layerExtent = mMapExtent; } @@ -288,17 +293,11 @@ void QgsMeshStreamField::updateSize( const QgsRenderContext &renderContext ) return; } - QgsPointXY interestZoneTopLeft; - QgsPointXY interestZoneBottomRight; - - interestZoneTopLeft = deviceMapToPixel.transform( QgsPointXY( interestZoneExtent.xMinimum(), interestZoneExtent.yMaximum() ) ); - interestZoneBottomRight = deviceMapToPixel.transform( QgsPointXY( interestZoneExtent.xMaximum(), interestZoneExtent.yMinimum() ) ); - - mFieldTopLeftInDeviceCoordinates = interestZoneTopLeft.toQPointF().toPoint(); - QPoint mFieldBottomRightInDeviceCoordinates = interestZoneBottomRight.toQPointF().toPoint(); - int fieldWidthInDeviceCoordinate = mFieldBottomRightInDeviceCoordinates.x() - mFieldTopLeftInDeviceCoordinates.x(); - int fieldHeightInDeviceCoordinate = mFieldBottomRightInDeviceCoordinates.y() - mFieldTopLeftInDeviceCoordinates.y(); + QgsRectangle fieldInterestZoneInDeviceCoordinates = QgsMeshLayerUtils::boundingBoxToScreenRectangle( deviceMapToPixel, interestZoneExtent ); + mFieldTopLeftInDeviceCoordinates = QPoint( int( fieldInterestZoneInDeviceCoordinates.xMinimum() ), int( fieldInterestZoneInDeviceCoordinates.yMinimum() ) ); + int fieldWidthInDeviceCoordinate = int( fieldInterestZoneInDeviceCoordinates.width() ); + int fieldHeightInDeviceCoordinate = int ( fieldInterestZoneInDeviceCoordinates.height() ); int fieldWidth = int( fieldWidthInDeviceCoordinate / mFieldResolution ); int fieldHeight = int( fieldHeightInDeviceCoordinate / mFieldResolution ); @@ -319,10 +318,9 @@ void QgsMeshStreamField::updateSize( const QgsRenderContext &renderContext ) mFieldSize.setHeight( fieldHeight ); } - double mapUnitPerFieldPixel; if ( interestZoneExtent.width() > 0 ) - mapUnitPerFieldPixel = interestZoneExtent.width() / fieldWidthInDeviceCoordinate * mFieldResolution; + mapUnitPerFieldPixel = deviceMapToPixel.mapUnitsPerPixel() * mFieldResolution * mFieldSize.width() / ( fieldWidthInDeviceCoordinate / mFieldResolution ) ; else mapUnitPerFieldPixel = 1e-8; @@ -341,7 +339,9 @@ void QgsMeshStreamField::updateSize( const QgsRenderContext &renderContext ) xc, yc, fieldWidth, - fieldHeight, 0 ); + fieldHeight, + deviceMapToPixel.mapRotation() + ); initField(); mValid = true; @@ -363,8 +363,6 @@ bool QgsMeshStreamField::isValid() const void QgsMeshStreamField::addTrace( QgsPointXY startPoint ) { - QPoint sp; - sp = mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint(); addTrace( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint() ); } @@ -462,8 +460,10 @@ void QgsMeshStreamField::addTrace( QPoint startPixel ) /* nondimensional value : Vu=2 when the particle need dt=1 to go through a pixel with the mMagMax magnitude * The nondimensional size of the side of a pixel is 2 */ + vector = vector.rotateBy( -mMapToFieldPixel.mapRotation() * M_DEG2RAD ); QgsVector vu = vector / mMaximumMagnitude * 2; data.magnitude = vector.length(); + double Vx = vu.x(); double Vy = vu.y(); double Vu = data.magnitude / mMaximumMagnitude * 2; //nondimensional vector magnitude diff --git a/src/core/mesh/qgsmeshtracerenderer.h b/src/core/mesh/qgsmeshtracerenderer.h index ba75a8041af7..20022b6b65af 100644 --- a/src/core/mesh/qgsmeshtracerenderer.h +++ b/src/core/mesh/qgsmeshtracerenderer.h @@ -62,7 +62,10 @@ class QgsMeshVectorValueInterpolator //! Destructor virtual ~QgsMeshVectorValueInterpolator() = default; - //! Returns the interpolated vector + /** + * Returns the interpolated vector + * \param point point in map coordinates + */ virtual QgsVector vectorValue( const QgsPointXY &point ) const; //! Assignment operator diff --git a/src/core/mesh/qgsmeshvectorrenderer.cpp b/src/core/mesh/qgsmeshvectorrenderer.cpp index 55cf4f80b1db..f927b9d95cb0 100644 --- a/src/core/mesh/qgsmeshvectorrenderer.cpp +++ b/src/core/mesh/qgsmeshvectorrenderer.cpp @@ -32,6 +32,10 @@ ///@cond PRIVATE +#ifndef M_DEG2RAD +#define M_DEG2RAD 0.0174532925 +#endif + inline double mag( double input ) { if ( input < 0.0 ) @@ -146,7 +150,8 @@ bool QgsMeshVectorArrowRenderer::calcVectorLineEnd( // Determine the angle of the vector, counter-clockwise, from east // (and associated trigs) - double vectorAngle = -1.0 * atan( ( -1.0 * yVal ) / xVal ); + double vectorAngle = -1.0 * atan( ( -1.0 * yVal ) / xVal ) - mContext.mapToPixel().mapRotation() * M_DEG2RAD; + cosAlpha = cos( vectorAngle ) * mag( xVal ); sinAlpha = sin( vectorAngle ) * mag( xVal ); @@ -487,7 +492,8 @@ QgsMeshVectorRenderer *QgsMeshVectorRenderer::makeVectorRenderer( datasetMagMinimumValue, dataType, settings, - context, size ); + context, + size ); break; case QgsMeshRendererVectorSettings::Streamlines: renderer = new QgsMeshVectorStreamlineRenderer( diff --git a/src/core/qgsmaptopixel.h b/src/core/qgsmaptopixel.h index 32c2f70b8f91..97234bfbe56c 100644 --- a/src/core/qgsmaptopixel.h +++ b/src/core/qgsmaptopixel.h @@ -169,7 +169,7 @@ class CORE_EXPORT QgsMapToPixel void setMapRotation( double degrees, double cx, double cy ); /** - * Returns current map rotation in degrees + * Returns current map rotation in degrees (clockwise) * \since QGIS 2.8 */ double mapRotation() const; diff --git a/tests/src/core/testqgsmeshlayerrenderer.cpp b/tests/src/core/testqgsmeshlayerrenderer.cpp index fd3892f61c80..5cd7751951cf 100644 --- a/tests/src/core/testqgsmeshlayerrenderer.cpp +++ b/tests/src/core/testqgsmeshlayerrenderer.cpp @@ -65,7 +65,7 @@ class TestQgsMeshRenderer : public QObject void cleanupTestCase();// will be called after the last testfunction was executed. void init(); // will be called before each testfunction is executed. void cleanup() {} // will be called after every testfunction. - bool imageCheck( const QString &testType, QgsMeshLayer *layer ); + bool imageCheck( const QString &testType, QgsMeshLayer *layer, double rotation = 0.0 ); QString readFile( const QString &fname ) const; @@ -228,12 +228,14 @@ QString TestQgsMeshRenderer::readFile( const QString &fname ) const return uri; } -bool TestQgsMeshRenderer::imageCheck( const QString &testType, QgsMeshLayer *layer ) +bool TestQgsMeshRenderer::imageCheck( const QString &testType, QgsMeshLayer *layer, double rotation ) { mReport += "

" + testType + "

\n"; - mMapSettings->setExtent( layer->extent() ); mMapSettings->setDestinationCrs( layer->crs() ); + mMapSettings->setExtent( layer->extent() ); + mMapSettings->setRotation( rotation ); mMapSettings->setOutputDpi( 96 ); + QgsRenderChecker myChecker; myChecker.setControlPathPrefix( QStringLiteral( "mesh" ) ); myChecker.setControlName( "expected_" + testType ); @@ -253,6 +255,7 @@ void TestQgsMeshRenderer::test_native_mesh_rendering() rendererSettings.setNativeMeshSettings( settings ); mMemoryLayer->setRendererSettings( rendererSettings ); QVERIFY( imageCheck( "quad_and_triangle_native_mesh", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_native_mesh_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_native_mesh_renderingWithClipping() @@ -287,6 +290,7 @@ void TestQgsMeshRenderer::test_triangular_mesh_rendering() rendererSettings.setTriangularMeshSettings( settings ); mMemoryLayer->setRendererSettings( rendererSettings ); QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_edge_mesh_rendering() @@ -319,6 +323,7 @@ void TestQgsMeshRenderer::test_1d_vertex_scalar_dataset_rendering() mMemory1DLayer->setStaticScalarDatasetIndex( ds ); QVERIFY( imageCheck( "lines_vertex_scalar_dataset", mMemory1DLayer ) ); + QVERIFY( imageCheck( "lines_vertex_scalar_dataset_rotated_45", mMemory1DLayer, 45 ) ); } void TestQgsMeshRenderer::test_1d_vertex_vector_dataset_rendering() @@ -337,6 +342,7 @@ void TestQgsMeshRenderer::test_1d_vertex_vector_dataset_rendering() mMemory1DLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "lines_vertex_vector_dataset", mMemory1DLayer ) ); + QVERIFY( imageCheck( "lines_vertex_vector_dataset_rotated_45", mMemory1DLayer, 45 ) ); } void TestQgsMeshRenderer::test_1d_edge_scalar_dataset_rendering() @@ -357,6 +363,7 @@ void TestQgsMeshRenderer::test_1d_edge_scalar_dataset_rendering() mMemory1DLayer->setStaticScalarDatasetIndex( ds ); QVERIFY( imageCheck( "lines_edge_scalar_dataset", mMemory1DLayer ) ); + QVERIFY( imageCheck( "lines_edge_scalar_dataset_rotated_45", mMemory1DLayer, 45 ) ); } void TestQgsMeshRenderer::test_1d_edge_vector_dataset_rendering() @@ -370,6 +377,7 @@ void TestQgsMeshRenderer::test_1d_edge_vector_dataset_rendering() mMemory1DLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "lines_edge_vector_dataset", mMemory1DLayer ) ); + QVERIFY( imageCheck( "lines_edge_vector_dataset_rotated_45", mMemory1DLayer, 45 ) ); } void TestQgsMeshRenderer::test_vertex_scalar_dataset_rendering() @@ -383,6 +391,7 @@ void TestQgsMeshRenderer::test_vertex_scalar_dataset_rendering() mMemoryLayer->setStaticScalarDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering() @@ -401,6 +410,7 @@ void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_vector_dataset_colorRamp_rendering() @@ -433,6 +443,7 @@ void TestQgsMeshRenderer::test_face_scalar_dataset_rendering() mMemoryLayer->setStaticScalarDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_face_scalar_dataset_interpolated_neighbour_average_rendering() @@ -463,6 +474,7 @@ void TestQgsMeshRenderer::test_face_vector_dataset_rendering() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_scalar_dataset_with_inactive_face_rendering() @@ -496,6 +508,7 @@ void TestQgsMeshRenderer::test_face_vector_on_user_grid() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_face_vector_on_user_grid_streamlines() @@ -516,6 +529,7 @@ void TestQgsMeshRenderer::test_face_vector_on_user_grid_streamlines() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset_streamlines", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_vector_on_user_grid() @@ -537,6 +551,7 @@ void TestQgsMeshRenderer::test_vertex_vector_on_user_grid() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_vector_on_user_grid_streamlines() @@ -558,6 +573,7 @@ void TestQgsMeshRenderer::test_vertex_vector_on_user_grid_streamlines() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_streamlines", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_streamlines_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_vector_on_user_grid_streamlines_colorRamp() @@ -606,6 +622,7 @@ void TestQgsMeshRenderer::test_vertex_vector_traces() mMemoryLayer->setStaticVectorDatasetIndex( ds ); QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_traces", mMemoryLayer ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_traces_rotated_45", mMemoryLayer, 45.0 ) ); } void TestQgsMeshRenderer::test_vertex_vector_traces_colorRamp() diff --git a/tests/testdata/control_images/mesh/expected_lines_edge_scalar_dataset_rotated_45/expected_lines_edge_scalar_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_lines_edge_scalar_dataset_rotated_45/expected_lines_edge_scalar_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..9432606ad7eeabbbcfb0b6033da3f7f61489d387 GIT binary patch literal 80307 zcmeI4O=uit7=Yi|Y@4QAicQRPhJ0KmY;(1abk#I0OL*ED=BuS^)wP1P~+w4yPc1 zAoKtPA_yQz1RPF5072*h2t*J-kO(-Of&hZh0}zNHfFKcYI0b>cTL`Yqef&o4Spc^p zcQx99YqRp;g)_3|#;jaf_kjGiY0TABI*yyiPC7=ItqTmz{2@72>^7-Q;o|mm;V`Rg}tr(EB47p?Gl8l`?BCAVRt8$pU^YbNt|C&7W$%GaR4S6C+ z0}kCgk9>c^zjIsb9BNU4LKn-(fyR`7i(DRK+vxvAEsm z-${o5{JG65xbkNfymNtLij6Rk;QPARyqGJqHW<0qOIbQ`I@^&_)-yl z?V>N^@cMHG0xbj(qy-5FAaIKSg4|-k76e)d7H#Oi+>j&*(-Ck zGzsJe2KxnJ(nQW&E)mETCbkNaxKuJ?O_M-wg}_ZgOu$IuO4*1rEdmXKm`RZ&E%eOe0)ZAmOwdT;Lg|Px4FZ9Jn2C`j z4gAbuJAqI^OyEdjd-=K=-!H@Gcov|ZaHK3|Ai~t+Vp|)5Wd$)nkVIQskZ+AZEJ4iR zswCq)qEZ9LS_gsHf*2el2mD7=kVHpkkY$xXTY{K(APJqLi9p+eAc>~-AlDTMf+RGK z76L041WB~Ci0(W)5(G(fH;;zwI~D{-M*1WA@J0we4tkcuEkVs8TwSu}yv1VNJMLU7hj0$ms6{N8_F3wsuT zUpBF`DTpeVK-XmnniffdsBp|i0zDDLfIt!(+ku#x3G_@569|$tmxF!V2=r7C0|QBH zYYF11C(v_2OfX1NUlO)$B4C9e1_+Ya)E2~2BVdgnCLkoKm4&q}1gsLoKtU2)T7x(Y z0qX=YK_Q8uz+wXdD+MuNdMioakH4P{dltZkvJpcs2v{qNfzexGdQlGMw2gq(f*4px zVq44TipP3EkVIEQ+Lo;of*^@)ZKEe1X9PhKJxys-rcMchBsR5rY%`I zDM(F{9pg{Pz+k@|+I-9wp2U$c0?rCz>hR=&ErKK&>qyJeaas^0Y3!!6CwKJmEI=cZ zB=?+`1!0nG2d>pjAQOThNpo4*Pl`Zh1VNIdT7v7;6UdYxNK#)~wv!-`IYE#liMHSx zH3FFw1W9V;W!))(%nE`eowf$=Hv}>*h)IzDSTqz^R!SiAf*3GJveNe8eJTV&5}O-+ z^zogi+;|qi+qd=eZ`BwRW{vm5UpBWBvGtfhzQ^;YKE3(;WtOjxpOcwwAIbW=Zx{J@ zPRh@2lJdl(smH^Fb`wx_2dS09Nb>TAVOgK^AN;#~U8FQG-j^4}`|46{2x|yb38)lA z=F4(tuJPvS&EAl{sq;vJ7!3q;3X;!BdGvk}uYrZg)e@34A<@38QxL!E761E2Wy`%% zS>=Dss$Y<#o`(8uwSt(+FTAx~&XB?K7D8ECz0V&u`sq@D;EFz3Bu?ten{p4vV@FOau`XJ6gp;_2oeAa zNdllKJ%k`3g-4PQFv<=iNJPPrBm$0-QwXw5p^;=6Kp8)cATbJzBrzambO?gPEG&}5 c1eLL2xewo5xBI>E_f1;GoqGyjY(IG9e`8*^;s5{u literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_lines_edge_vector_dataset_rotated_45/expected_lines_edge_vector_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_lines_edge_vector_dataset_rotated_45/expected_lines_edge_vector_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..32c778876762becc26043ac6278b3591384dd53d GIT binary patch literal 80307 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 Ijhnal|D8(Wd;kCd literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_lines_vertex_vector_dataset_rotated_45/expected_lines_vertex_vector_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_lines_vertex_vector_dataset_rotated_45/expected_lines_vertex_vector_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..72c86cb3285b5a29d88cba2176e7f27b094fd7e4 GIT binary patch literal 80307 zcmeI23rrM87{|X;R0IKeRX7AiDhMcwwpC-Q#h`*!>jPVB+NN#VrfH(sm(Uo6YO2tt zZCcxgHpUp678?XxpEOmgV$_;=2B{BxP(gh06p=T0omuYS_JD;0c46=SB+KsH%+AjI zzWLqE?rrkoMf02-v<^h%6de`0l6!wbmGATP0F=8Ju8Sm5CDO82n=ZFGkgRBAYdQ>K`<0RK!N}Sk${6N5P%>U z10Wzl0D?%sK^6!=5R3s3kRSj-B;X(m1Rw~;00>ABP*f28a)ZSolxMkDza%=Z(7V+ZHqU1*A~zHx!^U4SkWM-f#LcyRv?4IiQHcWqZxmcq-~ z6!Xa!6gYJz6<)a@Y&k~{2zz@+Cli61MRNBU)$f3zLA_7l!jb)y`e`gR*4GJRz&CiJ z;fpkkw1J_$e?bdsRP?>9^rSd)(~hEu*WPQ>#PYj^&C*pCoQDH-65vbjz-ML(o3RIayuYMLzP5@Q z>gwomV*|Oc^=ndAo{=l|y+DA^_&LWid!Z)jDyk~VSPYxU$=y@Bph<31Lj%>1DhJ;Q;utv*(CzwE-t}odEwvx8z&B>oto@4s&&Zro=qe?vI-@bwp0Btxpt?m;TciWvmfdBe>Z7osFTuLS~s96a@f zm4Xa|hS*h^<8&{k4by1hEJg3fme12x4my zM}I9M06{Fmg~GN*0D{L2qMCP1PF);KoBtxq(DGK0D_2cAOQkm z0uV&Z11S&?5r7~f97uqGm;eM3^FRs&LsC&4f^)eHHATk3+_39>I^MX`Yl&d>}XuYfiY+jI?Ip-*0?s)qB z%k@-n@w}|CQMvjEXi~1#>DAZl-feN|?R?T@?jhZwbgF(>PT}*G(B!D4$CNCaAt^v7nZuT5=aiC#*R*^@E8%t}p+rMR>cLZ=><6tS5lj*1KN zXjyy`1x%it!R4~>dl!BWQc{Y&=YeUzRYPZJ{M3rjD} z0GogDp_e0IS#_Xq8Lu9d=C8Fldw9{}4>nTV?krlheIE^Va-m;0tfItuVf4q>3FM~r zrHy}GBu~EpS{>#}hqr&zqif>io)N$d(ldS*ot?J%W3qR2qJ^;=+MHK%>p#-{xkp%r z)l^ncIQz|oKN&lBAPqP2ZD=X?0R&NwHD&#_jSl^gOjQrc*bFg7*gX9F4aWiG;oE#{ zltssW(XV~R| MSrnNu`}K|g1B9lt)c^nh literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_scalar_dataset_rotated_45/expected_quad_and_triangle_face_scalar_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_scalar_dataset_rotated_45/expected_quad_and_triangle_face_scalar_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..b5658e8c6558cf7cbbd07e503132f14c51822ad1 GIT binary patch literal 471523 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 literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset_rotated_45/expected_quad_and_triangle_face_vector_user_grid_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset_rotated_45/expected_quad_and_triangle_face_vector_user_grid_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..6d04df99d43087b16b22ea09e13a291e0d00cc59 GIT binary patch literal 80307 zcmeI5TWB0r9LCRXW476JlMP8W=_ZWNs~>N*)V%%&i{Wd-?G*?dfd?jtJ3l zCU|B}jCBkMF)S)G(|e!Ih{~~3vzZUiU8~9s$sdPDa*>){{R3if(}cKHJ|_W#TpjAWeZ82!^t+U=irq(F5<_EmOJj_S_F}izE4mmIm(g7in|4O|@N2&AEF_3=vHc{YQPj}(F+pg;fyQGkYB z{2>5?_)}|)RDl2tq5uuM_(K2&@u$`psR98QL;)Ih@rQtA208of&bJoV0{BxTjMNMQ zmYKy2Xy}DM1Yi((1yQY5#UszWEN&a!9EOUMr~ z=F>Q90bCqA<*}n%s|DF@n(Vf3oOK_#RPARz`0c+cM?4joaheiyai$raew8eTIf7w9 zSATIiIn#_zze>aN5&hCo00Hv}z#!(=2t8yZ0D~~XhqUyfI%4HL)v@- zFo^jzLJt`Uz#xq9&6fUVa`KHhYXQt2MVh^XS<@97uZ{W$#Yvya6;m*B%&9a@8_!i*i8t?Weo=e>biRWCs za?bUnoO8)D{POxS%((1KQ-a!ypZ**wc^?LnDMR?s;8lpqKOStf0Gl&cDd>zA<9s5PT*cHAr3r7&TgS1_YWU0E09M44eB!00!}^-WY9@1hDL+Nnj>z z&J`Tz(&bxx9Z0y~_MXsRyku7EM z@72rUjk-79H!V7Q`{l=iltk<5ymI-HhM02sb}@3#{o%)x6uL{IrRA1beMzc|z!~v1T)H|aB5OZsTo*6&@%T5d^f@&AIGUHsjs+^MS2ZJP` z$Gk6BW}Hix1Gjeu(Xj-bqj2?_T$yn$-TLwC`q{gMi(FZC6K`@}3s3dQ@D#G@Q6}@w zAjqmm9R_@_)n`kPRp+b4ipt2UuZTzUFOgN(3^;!C@v`di+l#xUiT594-f z`S;>l0K@OAzUSVPbKcFlTsmv#3XXH>#{JhR&F#Fqti=^rPqS!IZPici5m=9+)ckAS z8Kikc=I+529Ou&IsDyV@EDp%fw3h%DXW3gj^qhbI3_<`I67~{+LF}y^dQLz91|fh9 z33~~^AokV{JtrUlgAhQ5guMhJ46^Uaocy@{{%e()>Am(23_S;dv>f*RkyD-Q~bPWF;S8$w5m!ljo2nTfynq0wgE?o@> zBb&s+#YimazlgwkjVW%fUSompZV+e`l=mG_eWt~Qs4f*UXm> HJbL_p3Gd+= literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45/expected_quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45/expected_quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..8642305bbe2d3f4a049635e6219d748745d14d57 GIT binary patch literal 471523 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 literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_triangular_mesh_rotated_45/expected_quad_and_triangle_triangular_mesh_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_triangular_mesh_rotated_45/expected_quad_and_triangle_triangular_mesh_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..da679b5c151619fa9a626cc35ae6509ff540172f GIT binary patch literal 80307 zcmeI*PiS0490%~lwP?Yf6!a!-MWvV2ozz|OcIUmFd2il(znR}RkS05C zX5P&AHy_e8ujHL)_w3%dVeQ!pR;#1-ZRA9QhOSz<;p}S6Gc(6L7>O<5&ByPma^iFHF(ySN8d}a3-tO0s#&t)p4{8AW0u&4-nu; zA13FKK$5OH5g@>kE<|5O0f~L3IzWKKK0F^s0Eu1IR)GMAU1+}d1`_iMR)NDjtdM#F ziCHzP_&JAJP$BjLlKxdq{6S&=;ph=U0{CHKd=)$2q{nyRbY*D&!OiVw0XVHIoVDPq zN_;In!xFy{T*;OIkm&OR5PdEpTY;pv>;Tf6iRcy}iI%_e=YtQ$KG_@XidT{nSoil| zbZzT4`s#R7(zbi{IS;uS>;x*eR%l;+JKeQj{l5y?Zv!{BJRmy(>^_n}Wo3n? z#)fF&>x=aC!TphI5?|nZ5Q$Zf*>fAmvCG$EddO=A5P3D%?ie_OeMvylKd8`p0Ebyc zSHB+t60@*E=>;6-mF#@O4kYHG`P>sY?5fuRqJ{y9U3k9r1`hj*MS!T`Kw=-F4+0u+~SUo2`V08?B+T-+%;6c?)qV-6!AYO6rvN5O%^ZJmsP0Eye+ z^Oy}d+^1><1W4Q$z}1Yv;VQ}KJk~(eaQt;E8e-Y6fFr*OqynOr10?ws#b##Uuu03l zZ)zawRzPAOxXTg1;WADAT$zBVDS<>EY~HQFk$1wk=g$m8O#>vw6svs~;Akh2|3@c4 z)G~o2|6-{-07r7ppa1qmEw^U@>NBUNorzKVfSTlLX1xk6SrfD$?-Yo-J&@QJ!DIw* zn55*sk8>bui9q7EP{83fPn+3t0iqTFBsOJ;?+YC9*%WalHy~>9K$5M5z>zIK7o&3p zq811w>B2h;DDt91i!9ZeHHsG+!E6?7A08twN607AtM0}ljF#*4?7?sA^{G52j6r>EP;fC1UO8OBF}zofs~8no+=$qdKSRG zn1EuR8MhIvv6KrYTd9B}TYg+dvj^fM65!x+ytA*v3m`rr0gmj4lG6;{0Pz6{aBw=> zZr0)z5Y9+|!_9%@Hj8&aI3fWKZpYf)db|X}2?=nxJB%D>@)igOB*4M(NV{E=*Fefd z0vv7+BG=ix2T}$St~h2N{qdsPX92h#+j719szFt-ha9_p=3@~0>?n_g@$YkQV$7yNd zOz!u>4g5?%>{pO>xfYks(~kGwqT$ocb`w4#fldPAfv6;;|4OXRX}~8v2>{6dkpM~0 z*+4@p0RUNZ3|5hxXwdMPZ`QQpQ^^ScNLTfn^CxNK)1yGrm5bDu0HUcpkZ3{?+N1&U zQsbXLh&J7<*LLm|no8HU0j4Vup)WO9geIZcwn8%c$vh38{Z?}oO%f6SkUmvjKDtPw zAI||vpPWLy3?K%T1rmdh0__4IhJ^(Z!=M7|1|Sv%T}5*I2;Fz?JBv~1>T?1BVp+ZA u#u7d9(JYWy=H_d607+3fAW0FLr$Y`6zBn^EI60@5Uw>*(ZE@FuH~#}1+L3zz literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_scalar_dataset_rotated_45/expected_quad_and_triangle_vertex_scalar_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_scalar_dataset_rotated_45/expected_quad_and_triangle_vertex_scalar_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..68ab60f31cdfc6aa8c571bb17328ab4135e28621 GIT binary patch literal 80307 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 Z+i&{Au{S?-A7HZWUFU7R`yIPK_kSf>r;7jp literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_dataset_rotated_45/expected_quad_and_triangle_vertex_vector_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_dataset_rotated_45/expected_quad_and_triangle_vertex_vector_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..72c86cb3285b5a29d88cba2176e7f27b094fd7e4 GIT binary patch literal 80307 zcmeI23rrM87{|X;R0IKeRX7AiDhMcwwpC-Q#h`*!>jPVB+NN#VrfH(sm(Uo6YO2tt zZCcxgHpUp678?XxpEOmgV$_;=2B{BxP(gh06p=T0omuYS_JD;0c46=SB+KsH%+AjI zzWLqE?rrkoMf02-v<^h%6de`0l6!wbmGATP0F=8Ju8Sm5CDO82n=ZFGkgRBAYdQ>K`<0RK!N}Sk${6N5P%>U z10Wzl0D?%sK^6!=5R3s3kRSj-B;X(m1Rw~;00>ABP*f28a)ZSolxMkDza%=Z(7V+ZHqU1*A~zHx!^U4SkWM-f#LcyRv?4IiQHcWqZxmcq-~ z6!Xa!6gYJz6<)a@Y&k~{2zz@+Cli61MRNBU)$f3zLA_7l!jb)y`e`gR*4GJRz&CiJ z;fpkkw1J_$e?bdsRP?>9^rSd)(~hEu*WPQ>#PYj^&C*pCoQDH-65vbjz-ML(o3RIayuYMLzP5@Q z>gwomV*|Oc^=ndAo{=l|y+DA^_&LWid!Z)jDyk~VSPYxU$=y@Bph<31Lj%>1DhJ;Q;utv*(CzwE-t}odEwvx8z&B>oto@4s&&Zro=qe?vI-@bwp0Btxpt?m;TciWvmfdBe>Z7osFTuLS~s96a@f zm4Xa|hS*h^<8&{k4by1hEJg3fme12x4my zM}I9M06{Fmg~GN*0D{L2qMCP1PF);KoBtxq(DGK0D_2cAOQkm z0uV&Z11S&?5r7~f97uqGm;eM3^FRs&LsC&4f^)eHHATk3+_39>I^MX`Yl&d>}XuYfiY+jI?Ip-*0?s)qB z%k@-n@w}|CQMvjEXi~1#>DAZl-feN|?R?T@?jhZwbgF(>PT}*G(B!D4$CNCaAt^v7nZuT5=aiC#*R*^@E8%t}p+rMR>cLZ=><6tS5lj*1KN zXjyy`1x%it!R4~>dl!BWQc{Y&=YeUzRYPZJ{M3rjD} z0GogDp_e0IS#_Xq8Lu9d=C8Fldw9{}4>nTV?krlheIE^Va-m;0tfItuVf4q>3FM~r zrHy}GBu~EpS{>#}hqr&zqif>io)N$d(ldS*ot?J%W3qR2qJ^;=+MHK%>p#-{xkp%r z)l^ncIQz|oKN&lBAPqP2ZD=X?0R&NwHD&#_jSl^gOjQrc*bFg7*gX9F4aWiG;oE#{ zltssW(XV~R| MSrnNu`}K|g1B9lt)c^nh literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_traces_rotated_45/expected_quad_and_triangle_vertex_vector_traces_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_traces_rotated_45/expected_quad_and_triangle_vertex_vector_traces_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..853c41b256f0302895c355e0b601baff8030fb91 GIT binary patch literal 80307 zcmeI2O=uNY6oAi*)}L78LJ^6-MWkp{{96bvtTm!i zb3fid?hjw=+&;6qwpv7H=6BTZ3O-wc_rYmXg1^6?YMc>#OmEon*SG`$2)reLAS?w4I0zt!0}ewFKoHgd z1RMkq!~usP2p|Y+00IsI2;zXl5Cjl}H2?tz0R(ZtVF&`o1i9I??%2D%05lH*<4eGp zEaMA@Z-W4Wum&LDAb=naI1E7mL0AJ2a1cNc2ONeVfFP^^2sj8JhyxBo5I_*t00bNa z5X1q8AqXJIIIMw{kG`p8FTgl}R{jcPQ3gzS+XN8AcK^s;nE-+)117v}0tjNee`K#r z06~-i6W%rf1hL&evR5X6Aj*IVZ<_#u*zOvlk!? z7+JzJIEFxk0D?q-a0-Di0R#!t;1~iC0tgZT!YKs81P~-lgJTFp2p~uV2&WJT6F`tK z4UQoYA%GweAe=%VOaMW`G&qJpgaCp>fN*M?z-J2{Usl@-kU!Dfh%vSo2-zzWKoDiX zgttuqL2UPr?3D>1h%#Wp+a`b@w);o+$^;NZ88G2(6F?B#{Udv20tliEnDDjVHqEARWau1axaSla$=m4Uv3 z^mca0>q3w8b$3dCp<5QNSR>#5^qb^zIVs;aGCU-OmoKEJqg}e%pUJDXr*VH;t(oDDO!nti~djT{PpJ1_DuKiN^Whn%b^p|CM6?_&76#A?Bzi90FWLg}dS$S`Z}h&Zs!1~UlV!5+^aWW|w>B<> zx7XBV@s{iu6<&VqnmvEmY zD}Cz_Bt0|k@Q48a6Y;3ol$xFZf~0509Uc)t5RaNosp$zINP1@6;Sm7@@u=C9nw|iH z#4=lYe*Yf!0>q;6_#(1++5uopnDUC5%xmdF_( zfFK!YA|>b%KoC8)M9u&K1j#@XDM60_g6Od&as~(>NCuin33>z&M2{_zGe7`AGSEay z&?A5#dTfcD0Rjk;fhO86VP$RY&o=e~1h%#Wp+a`b@w);o+$^;NZ88G2(6F?B#{Udv20tliEnDDj< z#0c`R{p;^V<_+ZQx9qlE9N9x)ED6NOGM3?q1p(Ux5X5%>$X=NMf+zzfylnyqV!MB2 xuS@_zlmQdoHUR{&-9NHdCV(KyfC+D#z=2sU_r9BQWN*2O{I;F-S3lo(@(mEQ{g?m% literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45/expected_quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45/expected_quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45.png new file mode 100644 index 0000000000000000000000000000000000000000..e0d62a00bc3d47369a9da959105f4d59469a0700 GIT binary patch literal 80307 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 N=Pl^n*Ynbw{{f(CVmtr< literal 0 HcmV?d00001