Skip to content
Permalink
Browse files

Move conversion of tesselation to multipolygon to QgsTessellator

Also
- add unit test
- fix bad tesselation due to missing origins
  • Loading branch information
nyalldawson committed Nov 26, 2017
1 parent c0e732b commit 006da6e365a83891585e374b17041b2cdb713a0b
@@ -74,33 +74,6 @@ QgsTesselateAlgorithm *QgsTesselateAlgorithm::createInstance() const
return new QgsTesselateAlgorithm();
}

QgsPoint getPointFromData( QVector< float >::const_iterator &it )
{
// tesselator geometry is x, z, -y
double x = *it;
++it;
double z = *it;
++it;
double y = -( *it );
++it;
return QgsPoint( x, y, z );
}

void tesselatePolygon( const QgsPolygon *polygon, QgsMultiPolygon *destination )
{
QgsTessellator t( 0, 0, false );
t.addPolygon( *polygon, 0 );

QVector<float> data = t.data();
for ( auto it = data.constBegin(); it != data.constEnd(); )
{
QgsPoint p1 = getPointFromData( it );
QgsPoint p2 = getPointFromData( it );
QgsPoint p3 = getPointFromData( it );
destination->addGeometry( new QgsTriangle( p1, p2, p3 ) );
}
}

QgsFeature QgsTesselateAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback * )
{
QgsFeature f = feature;
@@ -110,22 +83,26 @@ QgsFeature QgsTesselateAlgorithm::processFeature( const QgsFeature &feature, Qgs
f.clearGeometry();
else
{
std::unique_ptr< QgsMultiPolygon > mp = qgis::make_unique< QgsMultiPolygon >();
QgsRectangle bounds = f.geometry().boundingBox();
QgsTessellator t( bounds.xMinimum(), bounds.yMinimum(), false );

if ( f.geometry().isMultipart() )
{
const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( f.geometry().constGet() );
for ( int i = 0; i < ms->numGeometries(); ++i )
{
std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i )->segmentize() ) );
tesselatePolygon( p.get(), mp.get() );
t.addPolygon( *p, 0 );
}
}
else
{
std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( f.geometry().constGet()->segmentize() ) );
tesselatePolygon( p.get(), mp.get() );
t.addPolygon( *p, 0 );
}
f.setGeometry( QgsGeometry( std::move( mp ) ) );
QgsGeometry g( t.asMultiPolygon() );
g.translate( bounds.xMinimum(), bounds.yMinimum() );
f.setGeometry( g );
}
}
return f;
@@ -17,8 +17,10 @@

#include "qgscurve.h"
#include "qgsgeometry.h"
#include "qgsmultipolygon.h"
#include "qgspoint.h"
#include "qgspolygon.h"
#include "qgstriangle.h"
#include "qgis_sip.h"

#include "poly2tri/poly2tri.h"
@@ -397,3 +399,29 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
_makeWalls( *polygon.interiorRing( i ), true, extrusionHeight, mData, mAddNormals, mOriginX, mOriginY );
}
}

QgsPoint getPointFromData( QVector< float >::const_iterator &it )
{
// tesselator geometry is x, z, -y
double x = *it;
++it;
double z = *it;
++it;
double y = -( *it );
++it;
return QgsPoint( x, y, z );
}

std::unique_ptr<QgsMultiPolygon> QgsTessellator::asMultiPolygon() const
{
std::unique_ptr< QgsMultiPolygon > mp = qgis::make_unique< QgsMultiPolygon >();
const QVector<float> data = mData;
for ( auto it = data.constBegin(); it != data.constEnd(); )
{
QgsPoint p1 = getPointFromData( it );
QgsPoint p2 = getPointFromData( it );
QgsPoint p3 = getPointFromData( it );
mp->addGeometry( new QgsTriangle( p1, p2, p3 ) );
}
return mp;
}
@@ -19,9 +19,10 @@
#include "qgis_3d.h"

class QgsPolygon;
class QgsMultiPolygon;

#include <QVector>

#include <memory>

/**
* \ingroup 3d
@@ -48,6 +49,11 @@ class _3D_EXPORT QgsTessellator
//! Returns size of one vertex entry in bytes
int stride() const { return mStride; }

/**
* Returns the triangulation as a multipolygon geometry.
*/
std::unique_ptr< QgsMultiPolygon > asMultiPolygon() const;

private:
double mOriginX, mOriginY;
bool mAddNormals;
@@ -20,6 +20,7 @@
#include "qgspoint.h"
#include "qgspolygon.h"
#include "qgstessellator.h"
#include "qgsmultipolygon.h"

/**
* Simple structure to record an expected triangle from tessellator.
@@ -115,6 +116,7 @@ class TestQgsTessellator : public QObject

void testBasic();
void testWalls();
void asMultiPolygon();

private:
};
@@ -191,6 +193,24 @@ void TestQgsTessellator::testWalls()
QVERIFY( checkTriangleOutput( tZ.data(), false, tc ) );
}

void TestQgsTessellator::asMultiPolygon()
{
QgsPolygon polygon;
polygon.fromWkt( "POLYGON((1 1, 2 1, 3 2, 1 2, 1 1))" );

QgsPolygon polygonZ;
polygonZ.fromWkt( "POLYGONZ((1 1 1, 2 1 2, 3 2 3, 1 2 4, 1 1 1))" );

QgsTessellator t( 0, 0, false );
t.addPolygon( polygon, 0 );
QCOMPARE( t.asMultiPolygon()->asWkt(), QStringLiteral( "MultiPolygonZ (((1 2 0, 2 1 0, 3 2 0, 1 2 0)),((1 2 0, 1 1 0, 2 1 0, 1 2 0)))" ) );

QgsTessellator t2( 0, 0, false );
t2.addPolygon( polygonZ, 0 );
QCOMPARE( t2.asMultiPolygon()->asWkt(), QStringLiteral( "MultiPolygonZ (((1 2 4, 2 1 2, 3 2 3, 1 2 4)),((1 2 4, 1 1 1, 2 1 2, 1 2 4)))" ) );

}


QGSTEST_MAIN( TestQgsTessellator )
#include "testqgstessellator.moc"

0 comments on commit 006da6e

Please sign in to comment.
You can’t perform that action at this time.