Skip to content

Commit 042bf97

Browse files
committedOct 4, 2017
Change triangulation algorithm for 3D planes
1 parent cb241e8 commit 042bf97

File tree

1 file changed

+130
-16
lines changed

1 file changed

+130
-16
lines changed
 

‎src/3d/qgstessellator.cpp

Lines changed: 130 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -157,22 +157,91 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
157157
polyline.reserve( exterior->numPoints() );
158158

159159
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();
161212

162213
for ( int i = 0; i < exterior->numPoints() - 1; ++i )
163214
{
164215
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++)
166223
{
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+
}
171228
}
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;
173239
}
174240
polylinesToDelete << polyline;
175241

242+
if (polyline.size() < 3)
243+
return;
244+
176245
p2t::CDT *cdt = new p2t::CDT( polyline );
177246

178247
// polygon holes
@@ -184,22 +253,63 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
184253
for ( int j = 0; j < hole->numPoints() - 1; ++j )
185254
{
186255
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)
188272
{
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;
193274
}
194-
ptPrev = pt;
275+
276+
holePolyline.push_back(pt2);
277+
278+
float zPt = qIsNaN( pt.z() ) ? 0 : pt.z();
279+
z[pt2] = zPt;
195280
}
196281
cdt->AddHole( holePolyline );
197282
polylinesToDelete << holePolyline;
198283
}
199284

200285
// TODO: robustness (no nearly duplicate points, invalid geometries ...)
201286

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+
}
203313

204314
std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
205315

@@ -210,9 +320,13 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
210320
{
211321
p2t::Point *p = t->GetPoint( j );
212322
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;
214328
if ( mAddNormals )
215-
mData << 0.f << 1.f << 0.f;
329+
mData << pNormal.x() << pNormal.z() << - pNormal.y();
216330
}
217331
}
218332

0 commit comments

Comments
 (0)
Please sign in to comment.