From b0bd6293366a31f2bd7fa347aa104c326bc2d088 Mon Sep 17 00:00:00 2001 From: Peter Petrik Date: Tue, 23 Oct 2018 11:11:25 +0200 Subject: [PATCH] fix #19939: render mesh arrows also on the edge of the canvas --- src/core/mesh/qgsmeshvectorrenderer.cpp | 26 ++++++++++++------ src/core/mesh/qgsmeshvectorrenderer.h | 8 ++++++ ...triangle_face_vector_user_grid_dataset.png | Bin 80307 -> 80307 bytes ...iangle_vertex_vector_user_grid_dataset.png | Bin 80307 -> 80307 bytes 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/core/mesh/qgsmeshvectorrenderer.cpp b/src/core/mesh/qgsmeshvectorrenderer.cpp index 31d83813987c..5bbe0bd61a0a 100644 --- a/src/core/mesh/qgsmeshvectorrenderer.cpp +++ b/src/core/mesh/qgsmeshvectorrenderer.cpp @@ -64,11 +64,21 @@ QgsMeshVectorRenderer::QgsMeshVectorRenderer( const QgsTriangularMesh &m, , mCfg( settings ) , mDataOnVertices( dataIsOnVertices ) , mOutputSize( size ) + , mBufferedExtent( context.extent() ) { // should be checked in caller Q_ASSERT( !mDatasetValuesMag.empty() ); Q_ASSERT( !std::isnan( mMinMag ) ); Q_ASSERT( !std::isnan( mMaxMag ) ); + + // we need to expand out the extent so that it includes + // arrows which start or end up outside of the + // actual visible extent + double extension = context.convertToMapUnits( mMaxMag, QgsUnitTypes::RenderPixels ); + mBufferedExtent.setXMinimum( mBufferedExtent.xMinimum() - extension ); + mBufferedExtent.setXMaximum( mBufferedExtent.xMaximum() + extension ); + mBufferedExtent.setYMinimum( mBufferedExtent.yMinimum() - extension ); + mBufferedExtent.setYMaximum( mBufferedExtent.yMaximum() + extension ); } QgsMeshVectorRenderer::~QgsMeshVectorRenderer() = default; @@ -91,7 +101,7 @@ void QgsMeshVectorRenderer::draw() pen.setColor( mCfg.color() ); painter->setPen( pen ); - const QList trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mContext.extent() ); + const QList trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mBufferedExtent ); if ( mCfg.isOnUserDefinedGrid() ) drawVectorDataOnGrid( trianglesInExtent ); @@ -180,11 +190,11 @@ bool QgsMeshVectorRenderer::calcVectorLineEnd( vectorLength = sqrt( xDist * xDist + yDist * yDist ); - // Check to see if any of the coords are outside the QImage area, if so, skip the whole vector - if ( lineStart.x() < 0 || lineStart.x() > mOutputSize.width() || - lineStart.y() < 0 || lineStart.y() > mOutputSize.height() || - lineEnd.x() < 0 || lineEnd.x() > mOutputSize.width() || - lineEnd.y() < 0 || lineEnd.y() > mOutputSize.height() ) + // Check to see if both of the coords are outside the QImage area, if so, skip the whole vector + if ( ( lineStart.x() < 0 || lineStart.x() > mOutputSize.width() || + lineStart.y() < 0 || lineStart.y() > mOutputSize.height() ) && + ( lineEnd.x() < 0 || lineEnd.x() > mOutputSize.width() || + lineEnd.y() < 0 || lineEnd.y() > mOutputSize.height() ) ) return true; return false; //success @@ -213,7 +223,7 @@ void QgsMeshVectorRenderer::drawVectorDataOnVertices( const QList &triangle drawnVertices.insert( i ); const QgsMeshVertex &vertex = vertices.at( i ); - if ( !mContext.extent().contains( vertex ) ) + if ( !mBufferedExtent.contains( vertex ) ) continue; double xVal = mDatasetValuesX[i]; @@ -240,7 +250,7 @@ void QgsMeshVectorRenderer::drawVectorDataOnFaces( const QList &trianglesIn break; QgsPointXY center = centroids.at( i ); - if ( !mContext.extent().contains( center ) ) + if ( !mBufferedExtent.contains( center ) ) continue; double xVal = mDatasetValuesX[i]; diff --git a/src/core/mesh/qgsmeshvectorrenderer.h b/src/core/mesh/qgsmeshvectorrenderer.h index 6ee40f6919e6..d89bd5f0eaaa 100644 --- a/src/core/mesh/qgsmeshvectorrenderer.h +++ b/src/core/mesh/qgsmeshvectorrenderer.h @@ -94,6 +94,14 @@ class QgsMeshVectorRenderer const QgsMeshRendererVectorSettings &mCfg; bool mDataOnVertices = true; QSize mOutputSize; + + /** + * Canvas extent buffered by vector maximum magnitude + * Needed to draw arrows which have + * start or end point outside the + * visible canvas extent + */ + QgsRectangle mBufferedExtent; }; ///@endcond diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset/expected_quad_and_triangle_face_vector_user_grid_dataset.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_face_vector_user_grid_dataset/expected_quad_and_triangle_face_vector_user_grid_dataset.png index b25f74247c2f2711fc9d7b0c7ce5bf8ac97e7875..0c184aa71c5a2bb9abc1239c8768a85c68ec1a2d 100644 GIT binary patch delta 1391 zcmb7EeMnSU6uDmJ-77h=tso9W(kT#d6uAFO`Yu)70tQnK$M5$3g>l-o5Ai&c{9P z_j@!X(2!7{Cob7o8ot|ljvTn?BdPNoihHMcp=uxLMAQEB9VE@Z@PABkfhWb$&m*M$ z#2=)+sg{h7jY0C#3`5DWCdJ)P#c?wa_p4<^YNqvfe&_KC<%i8Jeja>xnU$T|>!)%F z{FHE*yblE-r*6L@HG102XG?fbAcj%>qa0{OGx>GfJW#7hG6K9MADJ!1u(9R@WHc}< zh~o+LdP4;ky2w(i{$KSB(klN>fW$Mz4egGCrSoe8E(<*XGfPp`e$&MA@rg}WARetyQmKuCbK!F&j`+OdIVMY2)f^$k4ysTN`e`b7PgLw_z*-ueyCYTFP8_is9= z=IrMaIgTUGdLNSBzwdzeQx@%CT*eFC$1jVp##IGrKCI&Zp83O#x<z(ofX1waX1#R3oj<>Ss5}$1WXE8hOgNH>quA187bQyb{fH!R=8V zoE<52cqEyJE?;i6!%WD}B&8jYrbR`m)S)7E5H=mOYWu>~B@+K_YnF0z)xs2@rU=Y0}=3%A!ys zU!(fE{vxY(A0k{+->0zG9U(i5HbHk&rXr>52__sZFufxwIgF|a4ZS8aEI-C#Q4|xX z8yG5_eAJ3qYCr~+ZjH0a(y=k1VZ!naKG;l;<1OGjbCC7}mXhvNj z@jg5AdHhCNe%^}HwCmwD80LsmiffO?+yfyalwHYbZW(US>d?`2#mFr&k+NEYnoCFFbz!kiIVU+a;zsPQx(dlSgk n8eVu*Y<(R4gygqpbKJH?mV(M-jlI9l&x>$i#hTpKWm5GQwWM@= delta 815 zcmY*XZAepL6!u=;@``tC(Vzuo`ypX4)Nnt>u(-sk31iJHs1R*b^f|ge7OW5%CV>*M zy8|gXA}S2Y4EC-@1#+AVI5z+M17dC%j5AIc+JlAY*Ahd9UNB^o_nLJqBFjZ}XAXNQ zG`BAxlGk@UUEo#1nresCJR?t1<1d2kH?Wsyu=6`o3gS7?OT{IT4^`Ve(uY7#F#0I3W_W4B6g#Yc4}mFij<&y& z@$Ep5*%nWr!D&2ai5YuSBwNqBo7oNH2_?G);f%w)^IlrrzX@odgM2< C7IEDG diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_user_grid_dataset/expected_quad_and_triangle_vertex_vector_user_grid_dataset.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_vector_user_grid_dataset/expected_quad_and_triangle_vertex_vector_user_grid_dataset.png index 856e316703b694db2417da48b3ac5a2918f17b55..2ebb9a7932f5c970623f9fb59cc2900f38cc376d 100644 GIT binary patch delta 1521 zcmbtUdr(wm6hHTJVX*}kWEX+eSZ4>JkXWqbF~sgNj<%Oy{5P%y-Xs&iVb$ z?_AEva7LzjJtf|!@PyI+KAt6t`06Fq6c#mtPim3ea*8GL}c{qRK zLr`nWSyitf@{J6zVytm!C@gnh#j4&H+_};MCw4@`B!7AD^sBX)oLG zDtz#L7lf<#0EJj#5VLD&?GAK6A8R%8doQ}KH@N4kBjM_|H9-1))F=woG(E}p4pxGu zLI-@oa#mGtH#0c_7fbVDf0#F*ni~mdq;Vyymhf%u?18t855{}LD5lwyClI;9=B#{_ zwJjA%46dlM!xoKP{@MM?g(_TW&Qjq5O zhKd5ve^CgN7Kn&ZnsAOgVpk?jaoABqzyE`pKwd&gZ9U znn&ig^-uvi*qAJxnR)=<qQ2oxPqP{Y68G704V{IwWbE!AP_|bMUCj-Dm&2YT zMm;w8Cs9QVlJzrOTi2Jglql;|MhZL_8?i)_4U%u&39)-~pd>8`DeE`l^fJ!rw@fA6_!t8uUhV~J-qYtfjA;Rc5S z2^AhoQjz;P_$nfZ;<{_?QN(~ZS2|iod;BZ#BgIHH?8_Y+H~d%7{@m9S2HK-=cbxeb zVW9>){{Z_uXP7e3VzNa9EHN@OzJTW!$D5wGkN0{Sw;G`fp(wS7tv2J`835NAr0ogOmGP(>G|FpCAl?uE%M;#O V;W(sk(>sxVBVLROuMA5%^cVgDEDrzx delta 884 zcmYjPdq|T}6hGf~bv~xk+;BR^QhuYD(3x2Ynw;Z{oErk%xyx}S$r*68xE%Zf zgRy=mDn9$Ih7`9S6c3rY$d~qBv8nkv)+^jOP6Q4I=@<;I=tGj+>UxlPNwNL~Yg&Q% z6f)HrLikd(mxt5`WC|sS5NYh%C==khs%Os6sc?p(mKtJkSE#egC-9RAK(!7|Anw?zCK128X>>^hbMhL!Kai^I_+Btpmw>}=UzHQ2*ddxjjMF(2uY zPoz(cB z7C=hQ6+rG1tj}c=L8NFlB4DudEs*SVXZrpNg^-?KjP)Hdq3idLtDvdO01NYTSRW=4 zqG=be5kqY$=C`<7@uPWtuUThum#d`r2A(iC#JL)Bq8gLZw!!<1Q9BtAq8Ufj^u3NT z5yBOgp`rdmMa++8eu6W;IC6(WHT@+w*|KR#&**Q=YglkARgDQ+aSU&!n(83&@~$v8%*FxrQtPDIk$=|{{@qqi-+%pRuob1vI!bJ^*|e#U1~ znf-