2424#include " poly2tri/poly2tri.h"
2525
2626#include < QtDebug>
27+ #include < QMatrix4x4>
2728#include < QVector3D>
2829#include < algorithm>
2930
@@ -193,7 +194,7 @@ static void _normalVectorToXYVectors( const QVector3D &pNormal, QVector3D &pXVec
193194}
194195
195196
196- static void _ringToPoly2tri ( const QgsCurve *ring, const QgsPoint &ptFirst, const QVector3D &pXVector, const QVector3D &pYVector , std::vector<p2t::Point *> &polyline, QHash<p2t::Point *, float > &zHash )
197+ static void _ringToPoly2tri ( const QgsCurve *ring, const QgsPoint &ptFirst, const QMatrix4x4 &toNewBase , std::vector<p2t::Point *> &polyline, QHash<p2t::Point *, float > &zHash )
197198{
198199 QgsVertexId::VertexType vt;
199200 QgsPoint pt;
@@ -206,10 +207,11 @@ static void _ringToPoly2tri( const QgsCurve *ring, const QgsPoint &ptFirst, cons
206207 for ( int i = 0 ; i < pCount - 1 ; ++i )
207208 {
208209 ring->pointAt ( i, pt, vt );
209- const float z = std::isnan ( pt.z () ) ? 0 : pt.z ();
210- QVector3D tempPt ( pt.x () - x0, pt.y () - y0, z - z0 );
211- const float x = QVector3D::dotProduct ( tempPt, pXVector );
212- const float y = QVector3D::dotProduct ( tempPt, pYVector );
210+ QVector4D tempPt ( pt.x () - x0, pt.y () - y0, std::isnan ( pt.z () ) ? 0 : pt.z () - z0, 0 );
211+ QVector4D newBasePt = toNewBase * tempPt;
212+ const float x = newBasePt.x ();
213+ const float y = newBasePt.y ();
214+ const float z = newBasePt.z ();
213215
214216 const bool found = std::find_if ( polyline.begin (), polyline.end (), [x, y]( p2t::Point *&p ) { return *p == p2t::Point ( x, y ); } ) != polyline.end ();
215217
@@ -301,23 +303,35 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
301303 QVector3D pXVector, pYVector;
302304 _normalVectorToXYVectors ( pNormal, pXVector, pYVector );
303305
306+ // so now we have three orthogonal unit vectors defining new base
307+ // let's build transform matrix. We actually need just a 3x3 matrix,
308+ // but Qt does not have good support for it, so using 4x4 matrix instead.
309+ QMatrix4x4 toNewBase (
310+ pXVector.x (), pXVector.y (), pXVector.z (), 0 ,
311+ pYVector.x (), pYVector.y (), pYVector.z (), 0 ,
312+ pNormal.x (), pNormal.y (), pNormal.z (), 0 ,
313+ 0 , 0 , 0 , 0 );
314+
315+ // our 3x3 matrix is orthogonal, so for inverse we only need to transpose it
316+ QMatrix4x4 toOldBase = toNewBase.transposed ();
317+
304318 const QgsPoint ptFirst ( exterior->startPoint () );
305- _ringToPoly2tri ( exterior, ptFirst, pXVector, pYVector , polyline, z );
319+ _ringToPoly2tri ( exterior, ptFirst, toNewBase , polyline, z );
306320 polylinesToDelete << polyline;
307321
308322 // TODO: robustness (no nearly duplicate points, invalid geometries ...)
309323
310- double x0 = ptFirst.x (), y0 = ptFirst.y ();
324+ double x0 = ptFirst.x (), y0 = ptFirst.y (), z0 = ( std::isnan ( ptFirst. z () ) ? 0 : ptFirst. z () ) ;
311325 if ( polyline.size () == 3 && polygon.numInteriorRings () == 0 )
312326 {
313327 for ( std::vector<p2t::Point *>::iterator it = polyline.begin (); it != polyline.end (); it++ )
314328 {
315329 p2t::Point *p = *it;
316- const double zPt = z[p];
317- QVector3D nPoint = pXVector * p-> x + pYVector * p-> y ;
330+ QVector4D ptInNewBase ( p-> x , p-> y , z[p], 0 ) ;
331+ QVector4D nPoint = toOldBase * ptInNewBase ;
318332 const double fx = nPoint.x () - mOriginX + x0;
319333 const double fy = nPoint.y () - mOriginY + y0;
320- const double fz = extrusionHeight + ( std::isnan ( zPt ) ? 0 : zPt ) ;
334+ const double fz = nPoint. z () + extrusionHeight + z0 ;
321335 mData << fx << fz << -fy;
322336 if ( mAddNormals )
323337 mData << pNormal.x () << pNormal.z () << - pNormal.y ();
@@ -333,7 +347,7 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
333347 std::vector<p2t::Point *> holePolyline;
334348 const QgsCurve *hole = polygon.interiorRing ( i );
335349
336- _ringToPoly2tri ( hole, ptFirst, pXVector, pYVector , holePolyline, z );
350+ _ringToPoly2tri ( hole, ptFirst, toNewBase , holePolyline, z );
337351
338352 cdt->AddHole ( holePolyline );
339353 polylinesToDelete << holePolyline;
@@ -351,11 +365,11 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
351365 for ( int j = 0 ; j < 3 ; ++j )
352366 {
353367 p2t::Point *p = t->GetPoint ( j );
354- const double zPt = z[p];
355- QVector3D nPoint = pXVector * p-> x + pYVector * p-> y ;
368+ QVector4D ptInNewBase ( p-> x , p-> y , z[p], 0 ) ;
369+ QVector4D nPoint = toOldBase * ptInNewBase ;
356370 const double fx = nPoint.x () - mOriginX + x0;
357371 const double fy = nPoint.y () - mOriginY + y0;
358- const double fz = extrusionHeight + ( std::isnan ( zPt ) ? 0 : zPt ) ;
372+ const double fz = nPoint. z () + extrusionHeight + z0 ;
359373 mData << fx << fz << -fy;
360374 if ( mAddNormals )
361375 mData << pNormal.x () << pNormal.z () << - pNormal.y ();
0 commit comments