24
24
#include " poly2tri/poly2tri.h"
25
25
26
26
#include < QtDebug>
27
+ #include < QMatrix4x4>
27
28
#include < QVector3D>
28
29
#include < algorithm>
29
30
@@ -193,7 +194,7 @@ static void _normalVectorToXYVectors( const QVector3D &pNormal, QVector3D &pXVec
193
194
}
194
195
195
196
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 )
197
198
{
198
199
QgsVertexId::VertexType vt;
199
200
QgsPoint pt;
@@ -206,10 +207,11 @@ static void _ringToPoly2tri( const QgsCurve *ring, const QgsPoint &ptFirst, cons
206
207
for ( int i = 0 ; i < pCount - 1 ; ++i )
207
208
{
208
209
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 ();
213
215
214
216
const bool found = std::find_if ( polyline.begin (), polyline.end (), [x, y]( p2t::Point *&p ) { return *p == p2t::Point ( x, y ); } ) != polyline.end ();
215
217
@@ -301,23 +303,35 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
301
303
QVector3D pXVector, pYVector;
302
304
_normalVectorToXYVectors ( pNormal, pXVector, pYVector );
303
305
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
+
304
318
const QgsPoint ptFirst ( exterior->startPoint () );
305
- _ringToPoly2tri ( exterior, ptFirst, pXVector, pYVector , polyline, z );
319
+ _ringToPoly2tri ( exterior, ptFirst, toNewBase , polyline, z );
306
320
polylinesToDelete << polyline;
307
321
308
322
// TODO: robustness (no nearly duplicate points, invalid geometries ...)
309
323
310
- double x0 = ptFirst.x (), y0 = ptFirst.y ();
324
+ double x0 = ptFirst.x (), y0 = ptFirst.y (), z0 = ( std::isnan ( ptFirst. z () ) ? 0 : ptFirst. z () ) ;
311
325
if ( polyline.size () == 3 && polygon.numInteriorRings () == 0 )
312
326
{
313
327
for ( std::vector<p2t::Point *>::iterator it = polyline.begin (); it != polyline.end (); it++ )
314
328
{
315
329
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 ;
318
332
const double fx = nPoint.x () - mOriginX + x0;
319
333
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 ;
321
335
mData << fx << fz << -fy;
322
336
if ( mAddNormals )
323
337
mData << pNormal.x () << pNormal.z () << - pNormal.y ();
@@ -333,7 +347,7 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
333
347
std::vector<p2t::Point *> holePolyline;
334
348
const QgsCurve *hole = polygon.interiorRing ( i );
335
349
336
- _ringToPoly2tri ( hole, ptFirst, pXVector, pYVector , holePolyline, z );
350
+ _ringToPoly2tri ( hole, ptFirst, toNewBase , holePolyline, z );
337
351
338
352
cdt->AddHole ( holePolyline );
339
353
polylinesToDelete << holePolyline;
@@ -351,11 +365,11 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
351
365
for ( int j = 0 ; j < 3 ; ++j )
352
366
{
353
367
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 ;
356
370
const double fx = nPoint.x () - mOriginX + x0;
357
371
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 ;
359
373
mData << fx << fz << -fy;
360
374
if ( mAddNormals )
361
375
mData << pNormal.x () << pNormal.z () << - pNormal.y ();
0 commit comments