@@ -157,22 +157,91 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
157
157
polyline.reserve ( exterior->numPoints () );
158
158
159
159
QgsVertexId::VertexType vt;
160
- QgsPoint pt, ptPrev;
160
+ QgsPoint pt, ptFirst;
161
+
162
+ QVector3D pNormal (0 , 0 , 0 );
163
+ int pCount = exterior->numPoints ();
164
+ for (int i = 0 ; i < pCount - 1 ; i++)
165
+ {
166
+ QgsPoint pt1, pt2;
167
+ exterior->pointAt (i, pt1, vt);
168
+ exterior->pointAt ((i + 1 ) % pCount, pt2, vt);
169
+ ptFirst = pt1;
170
+
171
+ pNormal.setX (pNormal.x () + (pt1.y () - pt2.y ()) * (pt1.z () + pt2.z ()));
172
+ pNormal.setY (pNormal.y () + (pt1.z () - pt2.z ()) * (pt1.x () + pt2.x ()));
173
+ pNormal.setZ (pNormal.z () + (pt1.x () - pt2.x ()) * (pt1.y () + pt2.y ()));
174
+ }
175
+
176
+ pNormal.normalize ();
177
+
178
+ if (pNormal.length () < 0.999 || pNormal.length () > 1.001 )
179
+ {
180
+ return ;
181
+ }
182
+
183
+ if (pCount == 4 )
184
+ {
185
+ QgsPoint pt;
186
+ for (int i = 0 ; i < 3 ; i++)
187
+ {
188
+ exterior->pointAt (i, pt, vt);
189
+ mData << pt.x () - mOriginX << pt.z () << - pt.y () + mOriginY ;
190
+ if ( mAddNormals )
191
+ mData << pNormal.x () << pNormal.z () << - pNormal.y ();
192
+ }
193
+
194
+ return ;
195
+ }
196
+
197
+ QVector3D pOrigin (ptFirst.x (), ptFirst.y (), ptFirst.z ()), pXVector;
198
+ if (pNormal.z () > 0.001 || pNormal.z () < -0.001 )
199
+ {
200
+ pXVector = QVector3D (1 , 0 , -pNormal.x ()/pNormal.z ());
201
+ }
202
+ else if (pNormal.y () > 0.001 || pNormal.y () < -0.001 )
203
+ {
204
+ pXVector = QVector3D (1 , -pNormal.x ()/pNormal.y (), 0 );
205
+ }
206
+ else
207
+ {
208
+ pXVector = QVector3D (-pNormal.y () / pNormal.x (), 1 , 0 );
209
+ }
210
+ QVector3D pYVector = QVector3D::normal (pNormal, pXVector);
211
+ pXVector.normalize ();
161
212
162
213
for ( int i = 0 ; i < exterior->numPoints () - 1 ; ++i )
163
214
{
164
215
exterior->pointAt ( i, pt, vt );
165
- if ( i == 0 || pt != ptPrev )
216
+ QVector3D tempPt ( pt.x (), pt.y (), (qIsNaN ( pt.z () ) ? 0 : pt.z ()) );
217
+ float x = QVector3D::dotProduct (tempPt - pOrigin, pXVector);
218
+ float y = QVector3D::dotProduct (tempPt - pOrigin, pYVector);
219
+
220
+ p2t::Point *pt2 = new p2t::Point ( x, y );
221
+ bool found = false ;
222
+ for (std::vector<p2t::Point *>::iterator it = polyline.begin (); it != polyline.end (); it++)
166
223
{
167
- p2t::Point *pt2 = new p2t::Point ( pt. x () - mOriginX , pt. y () - mOriginY );
168
- polyline. push_back ( pt2 );
169
- float zPt = qIsNaN ( pt. z () ) ? 0 : pt. z () ;
170
- z[pt2] = zPt;
224
+ if ( *pt2 == **it)
225
+ {
226
+ found = true ;
227
+ }
171
228
}
172
- ptPrev = pt;
229
+
230
+ if (found)
231
+ {
232
+ continue ;
233
+ }
234
+
235
+ polyline.push_back (pt2);
236
+
237
+ float zPt = qIsNaN ( pt.z () ) ? 0 : pt.z ();
238
+ z[pt2] = zPt;
173
239
}
174
240
polylinesToDelete << polyline;
175
241
242
+ if (polyline.size () < 3 )
243
+ return ;
244
+
176
245
p2t::CDT *cdt = new p2t::CDT ( polyline );
177
246
178
247
// polygon holes
@@ -184,22 +253,63 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
184
253
for ( int j = 0 ; j < hole->numPoints () - 1 ; ++j )
185
254
{
186
255
hole->pointAt ( j, pt, vt );
187
- if ( j == 0 || pt != ptPrev )
256
+ QVector3D tempPt ( pt.x (), pt.y (), (qIsNaN ( pt.z () ) ? 0 : pt.z ()) );
257
+
258
+ float x = QVector3D::dotProduct (tempPt - pOrigin, pXVector);
259
+ float y = QVector3D::dotProduct (tempPt - pOrigin, pYVector);
260
+
261
+ p2t::Point *pt2 = new p2t::Point ( x, y );
262
+ bool found = false ;
263
+ for (std::vector<p2t::Point *>::iterator it = polyline.begin (); it != polyline.end (); it++)
264
+ {
265
+ if (*pt2 == **it)
266
+ {
267
+ found = true ;
268
+ }
269
+ }
270
+
271
+ if (found)
188
272
{
189
- p2t::Point *pt2 = new p2t::Point ( pt.x () - mOriginX , pt.y () - mOriginY );
190
- holePolyline.push_back ( pt2 );
191
- float zPt = qIsNaN ( pt.z () ) ? 0 : pt.z ();
192
- z[pt2] = zPt;
273
+ continue ;
193
274
}
194
- ptPrev = pt;
275
+
276
+ holePolyline.push_back (pt2);
277
+
278
+ float zPt = qIsNaN ( pt.z () ) ? 0 : pt.z ();
279
+ z[pt2] = zPt;
195
280
}
196
281
cdt->AddHole ( holePolyline );
197
282
polylinesToDelete << holePolyline;
198
283
}
199
284
200
285
// TODO: robustness (no nearly duplicate points, invalid geometries ...)
201
286
202
- cdt->Triangulate ();
287
+ if (polyline.size () == 3 )
288
+ {
289
+ for (std::vector<p2t::Point*>::iterator it = polyline.begin (); it != polyline.end (); it++)
290
+ {
291
+ p2t::Point *p = *it;
292
+ double zPt = z[p];
293
+ QVector3D nPoint = pOrigin + pXVector * p->x + pYVector * p->y ;
294
+ double fx = nPoint.x () - mOriginX ;
295
+ double fy = nPoint.y () - mOriginY ;
296
+ double fz = extrusionHeight + (qIsNaN (zPt) ? 0 : zPt);
297
+ mData << fx << fz << -fy;
298
+ if ( mAddNormals )
299
+ mData << pNormal.x () << pNormal.z () << - pNormal.y ();
300
+ }
301
+
302
+ return ;
303
+ }
304
+
305
+ try {
306
+ cdt->Triangulate ();
307
+ }
308
+ catch (...)
309
+ {
310
+ qDebug () << " Triangulation failed. Skipping polygon..." ;
311
+ return ;
312
+ }
203
313
204
314
std::vector<p2t::Triangle *> triangles = cdt->GetTriangles ();
205
315
@@ -210,9 +320,13 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
210
320
{
211
321
p2t::Point *p = t->GetPoint ( j );
212
322
float zPt = z[p];
213
- mData << p->x << extrusionHeight + zPt << -p->y ;
323
+ QVector3D nPoint = pOrigin + pXVector * p->x + pYVector * p->y ;
324
+ float fx = nPoint.x () - mOriginX ;
325
+ float fy = nPoint.y () - mOriginY ;
326
+ float fz = extrusionHeight + (qIsNaN (zPt) ? 0 : zPt);
327
+ mData << fx << fz << -fy;
214
328
if ( mAddNormals )
215
- mData << 0 . f << 1 . f << 0 . f ;
329
+ mData << pNormal. x () << pNormal. z () << - pNormal. y () ;
216
330
}
217
331
}
218
332
0 commit comments