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 000000000000..9432606ad7ee Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_lines_edge_scalar_dataset_rotated_45/expected_lines_edge_scalar_dataset_rotated_45.png differ 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 000000000000..32c778876762 Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_lines_edge_vector_dataset_rotated_45/expected_lines_edge_vector_dataset_rotated_45.png differ diff --git a/tests/testdata/control_images/mesh/expected_lines_vertex_scalar_dataset_rotated_45/expected_lines_vertex_scalar_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_lines_vertex_scalar_dataset_rotated_45/expected_lines_vertex_scalar_dataset_rotated_45.png new file mode 100644 index 000000000000..2b44231794fa Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_lines_vertex_scalar_dataset_rotated_45/expected_lines_vertex_scalar_dataset_rotated_45.png differ 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 000000000000..72c86cb3285b Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_lines_vertex_vector_dataset_rotated_45/expected_lines_vertex_vector_dataset_rotated_45.png differ 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 000000000000..b5658e8c6558 Binary files /dev/null and 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 differ diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_dataset_rotated_45/expected_quad_and_triangle_face_vector_dataset_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_dataset_rotated_45/expected_quad_and_triangle_face_vector_dataset_rotated_45.png new file mode 100644 index 000000000000..3ad82a22b869 Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_dataset_rotated_45/expected_quad_and_triangle_face_vector_dataset_rotated_45.png differ 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 000000000000..6d04df99d430 Binary files /dev/null and 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 differ 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 000000000000..8642305bbe2d Binary files /dev/null and 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 differ diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_native_mesh_rotated_45/expected_quad_and_triangle_native_mesh_rotated_45.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_native_mesh_rotated_45/expected_quad_and_triangle_native_mesh_rotated_45.png new file mode 100644 index 000000000000..1ff9fd29d2b7 Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_quad_and_triangle_native_mesh_rotated_45/expected_quad_and_triangle_native_mesh_rotated_45.png differ 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 000000000000..da679b5c1516 Binary files /dev/null and b/tests/testdata/control_images/mesh/expected_quad_and_triangle_triangular_mesh_rotated_45/expected_quad_and_triangle_triangular_mesh_rotated_45.png differ 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 000000000000..68ab60f31cdf Binary files /dev/null and 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 differ 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 000000000000..72c86cb3285b Binary files /dev/null and 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 differ 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 000000000000..853c41b256f0 Binary files /dev/null and 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 differ 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 000000000000..e0d62a00bc3d Binary files /dev/null and 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 differ diff --git a/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 b/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 new file mode 100644 index 000000000000..41c4de36b22e Binary files /dev/null and b/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 differ