Skip to content

Commit e25e8a9

Browse files
author
mhugent
committedSep 5, 2009
Updated interpolation classes with the changes in trunk
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@11553 c8812cc2-4d05-0410-92ff-de0c093fc19c

15 files changed

+409
-99
lines changed
 

‎src/analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ QT4_WRAP_CPP(QGIS_ANALYSIS_MOC_SRCS ${QGIS_ANALYSIS_MOC_HDRS})
3030
INCLUDE_DIRECTORIES(
3131
${CMAKE_CURRENT_SOURCE_DIR}
3232
${CMAKE_CURRENT_SOURCE_DIR}/../core/
33+
${CMAKE_CURRENT_SOURCE_DIR}/../core/renderer
3334
interpolation
3435
${PROJ_INCLUDE_DIR}
3536
${GEOS_INCLUDE_DIR}

‎src/analysis/interpolation/DualEdgeTriangulation.cc

Lines changed: 119 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
#include "DualEdgeTriangulation.h"
1919
#include <map>
20+
#include "qgsgeometry.h"
2021
#include "qgslogger.h"
22+
#include "qgsvectorfilewriter.h"
2123

2224
double leftOfTresh = 0.00000001;
2325

@@ -85,20 +87,22 @@ void DualEdgeTriangulation::addLine( Line3D* line, bool breakline )
8587

8688
if ( actpoint == -100 )//no point of the line could be inserted
8789
{
90+
delete line;
8891
return;
8992
}
9093

9194
for ( ;i < line->getSize();i++ )
9295
{
9396
line->goToNext();
9497
currentpoint = mDecorator->addPoint( line->getPoint() );
95-
//if(currentpoint!=-100&&actpoint!=-100&&currentpoint!=actpoint)//-100 is the return value if the point could not be not inserted
96-
//{
97-
// insertForcedSegment(actpoint,currentpoint,breakline);
98-
//}
98+
if ( currentpoint != -100 && actpoint != -100 && currentpoint != actpoint )//-100 is the return value if the point could not be not inserted
99+
{
100+
insertForcedSegment( actpoint, currentpoint, breakline );
101+
}
99102
actpoint = currentpoint;
100103
}
101104
}
105+
delete line;
102106
}
103107

104108
int DualEdgeTriangulation::addPoint( Point3D* p )
@@ -1121,6 +1125,10 @@ bool DualEdgeTriangulation::getTriangle( double x, double y, Point3D* p1, Point3
11211125
int ptnr1 = mHalfEdge[edge1]->getPoint();
11221126
int ptnr2 = mHalfEdge[edge2]->getPoint();
11231127
int ptnr3 = mHalfEdge[edge3]->getPoint();
1128+
if ( ptnr1 == -1 || ptnr2 == -1 || ptnr3 == -1 )
1129+
{
1130+
return false;
1131+
}
11241132
p1->setX( mPointVector[ptnr1]->getX() );
11251133
p1->setY( mPointVector[ptnr1]->getY() );
11261134
p1->setZ( mPointVector[ptnr1]->getZ() );
@@ -1174,7 +1182,6 @@ unsigned int DualEdgeTriangulation::insertEdge( int dual, int next, int point, b
11741182

11751183
}
11761184

1177-
#if 0
11781185
int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
11791186
{
11801187
if ( p1 == p2 )
@@ -1432,8 +1439,8 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
14321439
}
14331440

14341441
//set the flags 'forced' and 'break' to false for every edge and dualedge of 'crossEdges'
1435-
QListIterator<int> iter;
1436-
for ( iter = crossedEdges.begin();iter != crossedEdges.end();++iter )
1442+
QList<int>::const_iterator iter;
1443+
for ( iter = crossedEdges.constBegin();iter != crossedEdges.constEnd();++iter )
14371444
{
14381445
mHalfEdge[( *( iter ) )]->setForced( false );
14391446
mHalfEdge[( *( iter ) )]->setBreak( false );
@@ -1463,8 +1470,9 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
14631470

14641471
//finish the polygon on the left side
14651472
int actpointl = p2;
1466-
QListIterator<int> leftiter;
1467-
leftiter = crossedEdges.fromLast();
1473+
QList<int>::const_iterator leftiter; //todo: is there a better way to set an iterator to the last list element?
1474+
leftiter = crossedEdges.constEnd();
1475+
--leftiter;
14681476
while ( true )
14691477
{
14701478
int newpoint = mHalfEdge[mHalfEdge[mHalfEdge[mHalfEdge[( *leftiter )]->getDual()]->getNext()]->getNext()]->getPoint();
@@ -1475,7 +1483,7 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
14751483
int theedge = mHalfEdge[mHalfEdge[mHalfEdge[( *leftiter )]->getDual()]->getNext()]->getNext();
14761484
leftPolygon.append( theedge );
14771485
}
1478-
if ( leftiter == crossedEdges.begin() )
1486+
if ( leftiter == crossedEdges.constBegin() )
14791487
{break;}
14801488
--leftiter;
14811489
}
@@ -1484,9 +1492,9 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
14841492
leftPolygon.append( mHalfEdge[crossedEdges.first()]->getNext() );
14851493

14861494
//finish the polygon on the right side
1487-
QValueListIterator<int> rightiter;
1495+
QList<int>::const_iterator rightiter;
14881496
int actpointr = p1;
1489-
for ( rightiter = crossedEdges.begin();rightiter != crossedEdges.end();++rightiter )
1497+
for ( rightiter = crossedEdges.constBegin();rightiter != crossedEdges.constEnd();++rightiter )
14901498
{
14911499
int newpoint = mHalfEdge[mHalfEdge[mHalfEdge[( *rightiter )]->getNext()]->getNext()]->getPoint();
14921500
if ( newpoint != actpointr )
@@ -1505,15 +1513,17 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
15051513

15061514
//set the necessary nexts of leftPolygon(exept the first)
15071515
int actedgel = leftPolygon[1];
1508-
for ( leftiter = leftPolygon.at( 2 );leftiter != leftPolygon.end();++leftiter )
1516+
leftiter = leftPolygon.constBegin(); leftiter += 2;
1517+
for ( ;leftiter != leftPolygon.constEnd();++leftiter )
15091518
{
15101519
mHalfEdge[actedgel]->setNext(( *leftiter ) );
15111520
actedgel = ( *leftiter );
15121521
}
15131522

15141523
//set all the necessary nexts of rightPolygon
15151524
int actedger = rightPolygon[1];
1516-
for ( rightiter = rightPolygon.at( 2 );rightiter != rightPolygon.end();++rightiter )
1525+
rightiter = rightPolygon.constBegin(); rightiter += 2;
1526+
for ( ;rightiter != rightPolygon.constEnd();++rightiter )
15171527
{
15181528
mHalfEdge[actedger]->setNext(( *rightiter ) );
15191529
actedger = ( *( rightiter ) );
@@ -1528,8 +1538,6 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
15281538
mHalfEdge[rightPolygon.first()]->setPoint( p1 );
15291539
mHalfEdge[rightPolygon.last()]->setNext( dualfirstedge );
15301540

1531-
1532-
15331541
triangulatePolygon( &leftPolygon, &freelist, firstedge );
15341542
triangulatePolygon( &rightPolygon, &freelist, dualfirstedge );
15351543

@@ -1541,7 +1549,6 @@ int DualEdgeTriangulation::insertForcedSegment( int p1, int p2, bool breakline )
15411549

15421550
return leftPolygon.first();
15431551
}
1544-
#endif //0
15451552

15461553
void DualEdgeTriangulation::setForcedCrossBehaviour( Triangulation::forcedCrossBehaviour b )
15471554
{
@@ -2438,7 +2445,6 @@ bool DualEdgeTriangulation::swapPossible( unsigned int edge )
24382445
return true;
24392446
}
24402447

2441-
#if 0
24422448
void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* free, int mainedge )
24432449
{
24442450
if ( poly && free )
@@ -2449,13 +2455,13 @@ void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* fr
24492455
}
24502456

24512457
//search for the edge pointing on the closest point(distedge) and for the next(nextdistedge)
2452-
QValueListIterator<int> iterator = ++( poly->begin() );//go to the second edge
2458+
QList<int>::const_iterator iterator = ++( poly->constBegin() );//go to the second edge
24532459
double distance = MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] );
24542460
int distedge = ( *iterator );
24552461
int nextdistedge = mHalfEdge[( *iterator )]->getNext();
24562462
++iterator;
24572463

2458-
while ( iterator != --( poly->end() ) )
2464+
while ( iterator != --( poly->constEnd() ) )
24592465
{
24602466
if ( MathUtils::distPointFromLine( mPointVector[mHalfEdge[( *iterator )]->getPoint()], mPointVector[mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint()], mPointVector[mHalfEdge[mainedge]->getPoint()] ) < distance )
24612467
{
@@ -2472,15 +2478,15 @@ void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* fr
24722478
int insertb = mHalfEdge[inserta]->getDual();
24732479
free->pop_front();
24742480

2475-
mHalfEdge[inserta]->setNext(( *( poly->at( 1 ) ) ) );
2481+
mHalfEdge[inserta]->setNext(( poly->at( 1 ) ) );
24762482
mHalfEdge[inserta]->setPoint( mHalfEdge[mainedge]->getPoint() );
24772483
mHalfEdge[insertb]->setNext( nextdistedge );
24782484
mHalfEdge[insertb]->setPoint( mHalfEdge[distedge]->getPoint() );
24792485
mHalfEdge[distedge]->setNext( inserta );
24802486
mHalfEdge[mainedge]->setNext( insertb );
24812487

2482-
QValueList<int> polya;
2483-
for ( iterator = ( ++( poly->begin() ) );( *iterator ) != nextdistedge;++iterator )
2488+
QList<int> polya;
2489+
for ( iterator = ( ++( poly->constBegin() ) );( *iterator ) != nextdistedge;++iterator )
24842490
{
24852491
polya.append(( *iterator ) );
24862492
}
@@ -2503,16 +2509,16 @@ void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* fr
25032509
int insertb = mHalfEdge[inserta]->getDual();
25042510
free->pop_front();
25052511

2506-
mHalfEdge[inserta]->setNext(( *( poly->at( 2 ) ) ) );
2512+
mHalfEdge[inserta]->setNext(( poly->at( 2 ) ) );
25072513
mHalfEdge[inserta]->setPoint( mHalfEdge[distedge]->getPoint() );
25082514
mHalfEdge[insertb]->setNext( mainedge );
25092515
mHalfEdge[insertb]->setPoint( mHalfEdge[mHalfEdge[mainedge]->getDual()]->getPoint() );
25102516
mHalfEdge[distedge]->setNext( insertb );
25112517
mHalfEdge[( *( --poly->end() ) )]->setNext( inserta );
25122518

2513-
QValueList<int> polya;
2514-
iterator = poly->at( 2 );
2515-
while ( iterator != poly->end() )
2519+
QList<int> polya;
2520+
iterator = poly->constBegin(); iterator += 2;
2521+
while ( iterator != poly->constEnd() )
25162522
{
25172523
polya.append(( *iterator ) );
25182524
++iterator;
@@ -2532,7 +2538,7 @@ void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* fr
25322538
int insertd = mHalfEdge[insertc]->getDual();
25332539
free->pop_front();
25342540

2535-
mHalfEdge[inserta]->setNext(( *( poly->at( 1 ) ) ) );
2541+
mHalfEdge[inserta]->setNext(( poly->at( 1 ) ) );
25362542
mHalfEdge[inserta]->setPoint( mHalfEdge[mainedge]->getPoint() );
25372543
mHalfEdge[insertb]->setNext( insertd );
25382544
mHalfEdge[insertb]->setPoint( mHalfEdge[distedge]->getPoint() );
@@ -2546,17 +2552,17 @@ void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* fr
25462552
mHalfEdge[( *( --poly->end() ) )]->setNext( insertc );
25472553

25482554
//build two new polygons for recursive triangulation
2549-
QValueList<int> polya;
2550-
QValueList<int> polyb;
2555+
QList<int> polya;
2556+
QList<int> polyb;
25512557

2552-
for ( iterator = ++( poly->begin() );( *iterator ) != nextdistedge;++iterator )
2558+
for ( iterator = ++( poly->constBegin() );( *iterator ) != nextdistedge;++iterator )
25532559
{
25542560
polya.append(( *iterator ) );
25552561
}
25562562
polya.prepend( inserta );
25572563

25582564

2559-
while ( iterator != poly->end() )
2565+
while ( iterator != poly->constEnd() )
25602566
{
25612567
polyb.append(( *iterator ) );
25622568
++iterator;
@@ -2574,7 +2580,6 @@ void DualEdgeTriangulation::triangulatePolygon( QList<int>* poly, QList<int>* fr
25742580
}
25752581

25762582
}
2577-
#endif //0
25782583

25792584
bool DualEdgeTriangulation::pointInside( double x, double y )
25802585
{
@@ -3066,6 +3071,87 @@ QList<int>* DualEdgeTriangulation::getPointsAroundEdge( double x, double y )
30663071
}
30673072
}
30683073

3074+
bool DualEdgeTriangulation::saveAsShapefile( const QString& fileName ) const
3075+
{
3076+
QString shapeFileName = fileName;
3077+
3078+
QgsFieldMap fields;
3079+
fields.insert( 0, QgsField( "type", QVariant::String, "String" ) );
3080+
3081+
// add the extension if not present
3082+
if ( shapeFileName.indexOf( ".shp" ) == -1 )
3083+
{
3084+
shapeFileName += ".shp";
3085+
}
3086+
3087+
//delete already existing files
3088+
if ( QFile::exists( shapeFileName ) )
3089+
{
3090+
if ( !QgsVectorFileWriter::deleteShapeFile( shapeFileName ) )
3091+
{
3092+
return false;
3093+
}
3094+
}
3095+
3096+
QgsVectorFileWriter writer( shapeFileName, "Utf-8", fields, QGis::WKBLineString, 0 );
3097+
if ( writer.hasError() != QgsVectorFileWriter::NoError )
3098+
{
3099+
return false;
3100+
}
3101+
3102+
bool *alreadyVisitedEdges = new bool[mHalfEdge.size()];
3103+
if ( !alreadyVisitedEdges )
3104+
{
3105+
QgsDebugMsg( "out of memory" );
3106+
return false;
3107+
}
3108+
3109+
for ( int i = 0; i < mHalfEdge.size(); ++i )
3110+
{
3111+
alreadyVisitedEdges[i] = false;
3112+
}
3113+
3114+
for ( int i = 0; i < mHalfEdge.size(); ++i )
3115+
{
3116+
HalfEdge* currentEdge = mHalfEdge[i];
3117+
if ( currentEdge->getPoint() != -1 && mHalfEdge[currentEdge->getDual()]->getPoint() != -1 && !alreadyVisitedEdges[currentEdge->getDual()] )
3118+
{
3119+
QgsFeature edgeLineFeature;
3120+
3121+
//geometry
3122+
Point3D* p1 = mPointVector[currentEdge->getPoint()];
3123+
Point3D* p2 = mPointVector[mHalfEdge[currentEdge->getDual()]->getPoint()];
3124+
QgsPolyline lineGeom;
3125+
lineGeom.push_back( QgsPoint( p1->getX(), p1->getY() ) );
3126+
lineGeom.push_back( QgsPoint( p2->getX(), p2->getY() ) );
3127+
QgsGeometry* geom = QgsGeometry::fromPolyline( lineGeom );
3128+
edgeLineFeature.setGeometry( geom );
3129+
3130+
//attributes
3131+
QString attributeString;
3132+
if ( currentEdge->getForced() )
3133+
{
3134+
if ( currentEdge->getBreak() )
3135+
{
3136+
attributeString = "break line";
3137+
}
3138+
else
3139+
{
3140+
attributeString = "structure line";
3141+
}
3142+
}
3143+
edgeLineFeature.addAttribute( 0, attributeString );
3144+
3145+
writer.addFeature( edgeLineFeature );
3146+
}
3147+
alreadyVisitedEdges[i] = true;
3148+
}
3149+
3150+
delete [] alreadyVisitedEdges;
3151+
3152+
return true;
3153+
}
3154+
30693155
double DualEdgeTriangulation::swapMinAngle( int edge ) const
30703156
{
30713157
Point3D* p1 = getPoint( mHalfEdge[edge]->getPoint() );

‎src/analysis/interpolation/DualEdgeTriangulation.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class ANALYSIS_EXPORT DualEdgeTriangulation: public Triangulation
4343
DualEdgeTriangulation();
4444
DualEdgeTriangulation( int nop, Triangulation* decorator );
4545
virtual ~DualEdgeTriangulation();
46-
/**Adds a line (e.g. a break-, structure- or an isoline) to the triangulation*/
46+
void setDecorator( Triangulation* d ) {mDecorator = d;}
47+
/**Adds a line (e.g. a break-, structure- or an isoline) to the triangulation. The class takes ownership of the line object and its points*/
4748
void addLine( Line3D* line, bool breakline );
4849
/**Adds a point to the triangulation and returns the number of this point in case of success or -100 in case of failure*/
4950
int addPoint( Point3D* p );
@@ -104,6 +105,9 @@ class ANALYSIS_EXPORT DualEdgeTriangulation: public Triangulation
104105
virtual bool swapEdge( double x, double y );
105106
/**Returns a value list with the numbers of the four points, which would be affected by an edge swap. This function is e.g. needed by NormVecDecorator to know the points, for which the normals have to be recalculated. The returned ValueList has to be deleted by the code which calls the method*/
106107
virtual QList<int>* getPointsAroundEdge( double x, double y );
108+
/**Saves the triangulation as a (line) shapefile
109+
@return true in case of success*/
110+
virtual bool saveAsShapefile( const QString& fileName ) const;
107111

108112
protected:
109113
/**X-coordinate of the upper right corner of the bounding box*/
@@ -137,7 +141,7 @@ class ANALYSIS_EXPORT DualEdgeTriangulation: public Triangulation
137141
/**inserts an edge and makes sure, everything is ok with the storage of the edge. The number of the HalfEdge is returned*/
138142
unsigned int insertEdge( int dual, int next, int point, bool mbreak, bool forced );
139143
/**inserts a forced segment between the points with the numbers p1 and p2 into the triangulation and returns the number of a HalfEdge belonging to this forced edge or -100 in case of failure*/
140-
//int insertForcedSegment(int p1, int p2, bool breakline);
144+
int insertForcedSegment( int p1, int p2, bool breakline );
141145
/**Treshold for the leftOfTest to handle numerical instabilities*/
142146
//const static double leftOfTresh=0.00001;
143147
/**Security to prevent endless loops in 'baseEdgeOfTriangle'. It there are more iteration then this number, the point will not be inserted*/
@@ -165,7 +169,7 @@ class ANALYSIS_EXPORT DualEdgeTriangulation: public Triangulation
165169
/**Returns true, if it is possible to swap an edge, otherwise false(concave quad or edge on (or outside) the convex hull)*/
166170
bool swapPossible( unsigned int edge );
167171
/**divides a polygon in a triangle and two polygons and calls itself recursively for these two polygons. 'poly' is a pointer to a list with the numbers of the edges of the polygon, 'free' is a pointer to a list of free halfedges, and 'mainedge' is the number of the edge, towards which the new triangle is inserted. Mainedge has to be the same as poly->begin(), otherwise the recursion does not work*/
168-
//void triangulatePolygon(QList<int>* poly, QList<int>* free, int mainedge);
172+
void triangulatePolygon( QList<int>* poly, QList<int>* free, int mainedge );
169173
/**Tests, if the bounding box of the halfedge with index i intersects the specified bounding box. The main purpose for this method is the drawing of the triangulation*/
170174
bool halfEdgeBBoxTest( int edge, double xlowleft, double ylowleft, double xupright, double yupright ) const;
171175
/**Calculates the minimum angle, which would be present, if the specified halfedge would be swapped*/
@@ -188,6 +192,10 @@ inline DualEdgeTriangulation::DualEdgeTriangulation( int nop, Triangulation* dec
188192
{
189193
mPointVector.reserve( nop );
190194
mHalfEdge.reserve( nop );
195+
if ( !mDecorator )
196+
{
197+
mDecorator = this;
198+
}
191199
}
192200

193201
inline double DualEdgeTriangulation::getXMax() const

‎src/analysis/interpolation/MathUtils.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
#ifndef MATHUTILS_H
1818
#define MATHUTILS_H
1919

20+
#ifndef Q_OS_MACX
2021
#include <cmath>
22+
#else
23+
#include <math.h>
24+
#endif
2125
#include "Vector3D.h"
2226
#include "Point3D.h"
2327

2428

25-
namespace MathUtils
29+
namespace ANALYSIS_EXPORT MathUtils
2630
{
2731
/**Calculates the barycentric coordinates of a point (x,y) with respect to p1, p2, p3 and stores the three barycentric coordinates in 'result'. Thus the u-coordinate is stored in result::x, the v-coordinate in result::y and the w-coordinate in result::z. Attention: p1, p2 and p3 have to be ordered counterclockwise*/
2832
bool calcBarycentricCoordinates( double x, double y, Point3D* p1, Point3D* p2, Point3D* p3, Point3D* result );

‎src/analysis/interpolation/Point3D.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
#ifndef POINT3D_H
1818
#define POINT3D_H
1919

20+
#ifndef Q_OS_MACX
2021
#include <cmath>
22+
#else
23+
#include <math.h>
24+
#endif
2125
#include <iostream>
2226

2327
/**Point3D is a class to represent a three dimensional point*/

‎src/analysis/interpolation/Triangulation.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ANALYSIS_EXPORT Triangulation
3131
/**Enumeration describing the behaviour, if two forced lines cross. SnappingType_VERTICE means, that the second inserted forced line is snapped to the closest vertice of the first inserted forced line. DELETE_FIRST means, that the status of the first inserted forced line is reset to that of a normal edge (so that the second inserted forced line remain and the first not*/
3232
enum forcedCrossBehaviour {SnappingType_VERTICE, DELETE_FIRST, INSERT_VERTICE};
3333
virtual ~Triangulation();
34-
/**Adds a line (e.g. a break-, structure- or an isoline) to the triangulation*/
34+
/**Adds a line (e.g. a break-, structure- or an isoline) to the triangulation. The class takes ownership of the line object and its points*/
3535
virtual void addLine( Line3D* line, bool breakline ) = 0;
3636
/**Adds a point to the triangulation*/
3737
virtual int addPoint( Point3D* p ) = 0;
@@ -88,6 +88,9 @@ class ANALYSIS_EXPORT Triangulation
8888
//virtual bool saveToTAFF(QString fileName) const=0;
8989
/**Swaps the edge which is closest to the point with x and y coordinates (if this is possible)*/
9090
virtual bool swapEdge( double x, double y ) = 0;
91+
/**Saves the triangulation as a (line) shapefile
92+
@return true in case of success*/
93+
virtual bool saveAsShapefile( const QString& fileName ) const = 0;
9194
};
9295

9396
inline Triangulation::~Triangulation()

‎src/analysis/interpolation/Vector3D.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
#ifndef VECTOR3D_H
1818
#define VECTOR3D_H
1919

20+
#ifndef Q_OS_MACX
2021
#include <cmath>
22+
#else
23+
#include <math.h>
24+
#endif
2125

2226
class ANALYSIS_EXPORT Vector3D
2327
/**
24-
Class Vector3D represents a 3D-Vector, capable to store x-,y- and z-coordinates in double values. In fact, the class is the same as Point3D. The name 'vector' makes it easier to understand the programms.
25-
*/
28+
Class Vector3D represents a 3D-Vector, capable to store x-,y- and z-coordinates in double values. In fact, the class is the same as Point3D. The name 'vector' makes it easier to understand the programms.
29+
*/
2630

2731
{
2832
protected:

‎src/analysis/interpolation/qgsgridfilewriter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
#include <QFile>
2121
#include <QProgressDialog>
2222

23-
QgsGridFileWriter::QgsGridFileWriter( QgsInterpolator* i, QString outputPath, QgsRectangle extent, int nCols, int nRows ): mInterpolator( i ), mOutputFilePath( outputPath ), mInterpolationExtent( extent ), mNumColumns( nCols ), mNumRows( nRows )
23+
QgsGridFileWriter::QgsGridFileWriter( QgsInterpolator* i, QString outputPath, QgsRectangle extent, int nCols, int nRows , double cellSizeX, double cellSizeY ): \
24+
mInterpolator( i ), mOutputFilePath( outputPath ), mInterpolationExtent( extent ), mNumColumns( nCols ), mNumRows( nRows ), mCellSizeX( cellSizeX ), mCellSizeY( cellSizeY )
2425
{
25-
mCellSizeX = ( mInterpolationExtent.xMaximum() - mInterpolationExtent.xMinimum() ) / mNumColumns;
26-
mCellSizeY = ( mInterpolationExtent.yMaximum() - mInterpolationExtent.yMinimum() ) / mNumRows;
26+
2727
}
2828

2929
QgsGridFileWriter::QgsGridFileWriter(): mInterpolator( 0 )
@@ -65,6 +65,7 @@ int QgsGridFileWriter::writeFile( bool showProgressDialog )
6565
progressDialog = new QProgressDialog( QObject::tr( "Interpolating..." ), QObject::tr( "Abort" ), 0, mNumRows, 0 );
6666
progressDialog->setWindowModality( Qt::WindowModal );
6767
}
68+
6869
for ( int i = 0; i < mNumRows; ++i )
6970
{
7071
currentXValue = mInterpolationExtent.xMinimum();

‎src/analysis/interpolation/qgsgridfilewriter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class QgsInterpolator;
2929
class ANALYSIS_EXPORT QgsGridFileWriter
3030
{
3131
public:
32-
QgsGridFileWriter( QgsInterpolator* i, QString outputPath, QgsRectangle extent, int nCols, int nRows );
32+
QgsGridFileWriter( QgsInterpolator* i, QString outputPath, QgsRectangle extent, int nCols, int nRows, double cellSizeX, double cellSizeY );
3333
~QgsGridFileWriter();
3434

3535
/**Writes the grid file.

‎src/analysis/interpolation/qgsidwinterpolator.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
#include <cmath>
2020
#include <limits>
2121

22-
QgsIDWInterpolator::QgsIDWInterpolator( const QList<QgsVectorLayer*>& vlayers ): QgsInterpolator( vlayers ), mDistanceCoefficient( 2.0 )
22+
QgsIDWInterpolator::QgsIDWInterpolator( const QList<LayerData>& layerData ): QgsInterpolator( layerData ), mDistanceCoefficient( 2.0 )
2323
{
2424

2525
}
2626

27-
QgsIDWInterpolator::QgsIDWInterpolator(): QgsInterpolator( QList<QgsVectorLayer*>() ), mDistanceCoefficient( 2.0 )
27+
QgsIDWInterpolator::QgsIDWInterpolator(): QgsInterpolator( QList<LayerData>() ), mDistanceCoefficient( 2.0 )
2828
{
2929

3030
}
@@ -62,6 +62,11 @@ int QgsIDWInterpolator::interpolatePoint( double x, double y, double& result )
6262
sumDenominator += currentWeight;
6363
}
6464

65+
if ( sumDenominator == 0.0 )
66+
{
67+
return 1;
68+
}
69+
6570
result = sumCounter / sumDenominator;
6671
return 0;
6772
}

‎src/analysis/interpolation/qgsidwinterpolator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
class ANALYSIS_EXPORT QgsIDWInterpolator: public QgsInterpolator
2424
{
2525
public:
26-
QgsIDWInterpolator( const QList<QgsVectorLayer*>& vlayers );
26+
QgsIDWInterpolator( const QList<LayerData>& layerData );
2727
~QgsIDWInterpolator();
2828

2929
/**Calculates interpolation value for map coordinates x, y

‎src/analysis/interpolation/qgsinterpolator.cpp

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
#else
2424
#include <math.h>
2525
#endif
26-
#ifdef _MSC_VER
26+
#ifdef WIN32
2727
#include <float.h>
2828
#define isnan(f) _isnan(f)
2929
#endif
3030

31-
QgsInterpolator::QgsInterpolator( const QList<QgsVectorLayer*>& vlayers ): mDataIsCached( false ), mVectorLayers( vlayers ), zCoordInterpolation( false ), mValueAttribute( -1 )
31+
QgsInterpolator::QgsInterpolator( const QList<LayerData>& layerData ): mDataIsCached( false ), mLayerData( layerData )
3232
{
3333

3434
}
@@ -43,15 +43,9 @@ QgsInterpolator::~QgsInterpolator()
4343

4444
}
4545

46-
void QgsInterpolator::enableAttributeValueInterpolation( int attribute )
47-
{
48-
mValueAttribute = attribute;
49-
zCoordInterpolation = false;
50-
}
51-
5246
int QgsInterpolator::cacheBaseData()
5347
{
54-
if ( mVectorLayers.size() < 1 )
48+
if ( mLayerData.size() < 1 )
5549
{
5650
return 0;
5751
}
@@ -60,25 +54,25 @@ int QgsInterpolator::cacheBaseData()
6054
mCachedBaseData.clear();
6155
mCachedBaseData.reserve( 100000 );
6256

63-
QList<QgsVectorLayer*>::iterator v_it = mVectorLayers.begin();
57+
QList<LayerData>::iterator v_it = mLayerData.begin();
6458

65-
for ( ; v_it != mVectorLayers.end(); ++v_it )
59+
for ( ; v_it != mLayerData.end(); ++v_it )
6660
{
67-
if (( *v_it ) == 0 )
61+
if ( v_it->vectorLayer == 0 )
6862
{
6963
continue;
7064
}
7165

72-
QgsVectorDataProvider* provider = ( *v_it )->dataProvider();
66+
QgsVectorDataProvider* provider = v_it->vectorLayer->dataProvider();
7367
if ( !provider )
7468
{
7569
return 2;
7670
}
7771

7872
QgsAttributeList attList;
79-
if ( !zCoordInterpolation )
73+
if ( !v_it->zCoordInterpolation )
8074
{
81-
attList.push_back( mValueAttribute );
75+
attList.push_back( v_it->interpolationAttribute );
8276
}
8377

8478
provider->select( attList );
@@ -89,22 +83,22 @@ int QgsInterpolator::cacheBaseData()
8983

9084
while ( provider->nextFeature( theFeature ) )
9185
{
92-
if ( !zCoordInterpolation )
86+
if ( !v_it->zCoordInterpolation )
9387
{
9488
QgsAttributeMap attMap = theFeature.attributeMap();
95-
QgsAttributeMap::const_iterator att_it = attMap.find( mValueAttribute );
96-
if ( att_it == attMap.end() ) //attribute not found, something must be wrong
89+
QgsAttributeMap::const_iterator att_it = attMap.find( v_it->interpolationAttribute );
90+
if ( att_it == attMap.end() ) //attribute not found, something must be wrong (e.g. NULL value)
9791
{
98-
return 3;
92+
continue;
9993
}
100-
attributeValue = att_it.value().toDouble(&attributeConversionOk);
101-
if(!attributeConversionOk || isnan(attributeValue)) //don't consider vertices with attributes like 'nan' for the interpolation
94+
attributeValue = att_it.value().toDouble( &attributeConversionOk );
95+
if ( !attributeConversionOk || isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
10296
{
10397
continue;
10498
}
10599
}
106100

107-
if ( addVerticesToCache( theFeature.geometry(), attributeValue ) != 0 )
101+
if ( addVerticesToCache( theFeature.geometry(), v_it->zCoordInterpolation, attributeValue ) != 0 )
108102
{
109103
return 3;
110104
}
@@ -114,7 +108,7 @@ int QgsInterpolator::cacheBaseData()
114108
return 0;
115109
}
116110

117-
int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, double attributeValue )
111+
int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, bool zCoord, double attributeValue )
118112
{
119113
if ( !geom )
120114
{
@@ -136,7 +130,7 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, double attributeValu
136130
theVertex.x = *(( double * )( currentWkbPtr ) );
137131
currentWkbPtr += sizeof( double );
138132
theVertex.y = *(( double * )( currentWkbPtr ) );
139-
if ( zCoordInterpolation && hasZValue )
133+
if ( zCoord && hasZValue )
140134
{
141135
currentWkbPtr += sizeof( double );
142136
theVertex.z = *(( double * )( currentWkbPtr ) );
@@ -161,7 +155,7 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, double attributeValu
161155
currentWkbPtr += sizeof( double );
162156
theVertex.y = *(( double * )( currentWkbPtr ) );
163157
currentWkbPtr += sizeof( double );
164-
if ( zCoordInterpolation && hasZValue ) //skip z-coordinate for 25D geometries
158+
if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
165159
{
166160
theVertex.z = *(( double * )( currentWkbPtr ) );
167161
currentWkbPtr += sizeof( double );
@@ -365,5 +359,6 @@ int QgsInterpolator::addVerticesToCache( QgsGeometry* geom, double attributeValu
365359
default:
366360
break;
367361
}
362+
mDataIsCached = true;
368363
return 0;
369364
}

‎src/analysis/interpolation/qgsinterpolator.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,16 @@ class ANALYSIS_EXPORT QgsInterpolator
4444
BREAK_LINES
4545
};
4646

47-
QgsInterpolator( const QList<QgsVectorLayer*>& vlayers );
47+
/**A layer together with the information about interpolation attribute / z-coordinate interpolation and the type (point, structure line, breakline)*/
48+
struct LayerData
49+
{
50+
QgsVectorLayer* vectorLayer;
51+
bool zCoordInterpolation;
52+
int interpolationAttribute;
53+
InputType mInputType;
54+
};
55+
56+
QgsInterpolator( const QList<LayerData>& layerData );
4857

4958
virtual ~QgsInterpolator();
5059

@@ -55,17 +64,9 @@ class ANALYSIS_EXPORT QgsInterpolator
5564
@return 0 in case of success*/
5665
virtual int interpolatePoint( double x, double y, double& result ) = 0;
5766

58-
/**Use the z-coord of 25D for interpolation*/
59-
void enableZCoordInterpolation() {zCoordInterpolation = true;}
60-
6167
/**Use a vector attribute as interpolation value*/
6268
void enableAttributeValueInterpolation( int attribute );
6369

64-
/**Creates a vector layer that can be added to the main map, e.g. TIN edges for triangle interpolation.
65-
Mouse clicks in the main map can be tracked and used for configuration (e.g. edge swaping). Default implementation does
66-
nothing.*/
67-
virtual QgsVectorLayer* createVectorLayer() const {return 0;}
68-
6970
protected:
7071
/**Caches the vertex and value data from the provider. All the vertex data
7172
will be held in virtual memory
@@ -77,18 +78,19 @@ class ANALYSIS_EXPORT QgsInterpolator
7778
/**Flag that tells if the cache already has been filled*/
7879
bool mDataIsCached;
7980

81+
//Information about the input vector layers and the attributes (or z-values) that are used for interpolation
82+
QList<LayerData> mLayerData;
83+
8084
private:
8185
QgsInterpolator(); //forbidden
8286
/**Helper method that adds the vertices of a geometry to the mCachedBaseData
8387
@param geom the geometry
88+
@param zCoord true if the z-coordinate of the geometry is to be interpolated
8489
@param attributeValue the attribute value for interpolation (if not interpolated from z-coordinate)
8590
@return 0 in case of success*/
86-
int addVerticesToCache( QgsGeometry* geom, double attributeValue );
91+
int addVerticesToCache( QgsGeometry* geom, bool zCoord, double attributeValue );
8792

88-
QList<QgsVectorLayer*> mVectorLayers;
8993

90-
bool zCoordInterpolation;
91-
int mValueAttribute;
9294
};
9395

9496
#endif

‎src/analysis/interpolation/qgstininterpolator.cpp

Lines changed: 192 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,24 @@
1919
#include "DualEdgeTriangulation.h"
2020
#include "LinTriangleInterpolator.h"
2121
#include "Point3D.h"
22-
//#include "qgssinglesymbolrenderer.h"
22+
#include "qgsfeature.h"
23+
#include "qgsgeometry.h"
24+
#include "qgssinglesymbolrenderer.h"
2325
#include "qgsvectorlayer.h"
26+
#include <QProgressDialog>
2427

25-
QgsTINInterpolator::QgsTINInterpolator( const QList<QgsVectorLayer*>& inputData ): QgsInterpolator( inputData ), mTriangulation( 0 ), mTriangleInterpolator( 0 ), mIsInitialized( false )
28+
#ifndef Q_OS_MACX
29+
#include <cmath>
30+
#else
31+
#include <math.h>
32+
#endif
33+
#ifdef WIN32
34+
#include <float.h>
35+
#define isnan(f) _isnan(f)
36+
#endif
37+
38+
QgsTINInterpolator::QgsTINInterpolator( const QList<LayerData>& inputData, bool showProgressDialog ): QgsInterpolator( inputData ), mTriangulation( 0 ), \
39+
mTriangleInterpolator( 0 ), mIsInitialized( false ), mShowProgressDialog( showProgressDialog ), mExportTriangulationToFile( false )
2640
{
2741
}
2842

@@ -55,25 +69,190 @@ int QgsTINInterpolator::interpolatePoint( double x, double y, double& result )
5569

5670
void QgsTINInterpolator::initialize()
5771
{
58-
if ( !mDataIsCached )
72+
DualEdgeTriangulation* theDualEdgeTriangulation = new DualEdgeTriangulation( 100000, 0 );
73+
mTriangulation = theDualEdgeTriangulation;
74+
75+
//get number of features if we use a progress bar
76+
int nFeatures = 0;
77+
int nProcessedFeatures = 0;
78+
if ( mShowProgressDialog )
5979
{
60-
cacheBaseData();
80+
QList<LayerData>::iterator layerDataIt = mLayerData.begin();
81+
for ( ; layerDataIt != mLayerData.end(); ++layerDataIt )
82+
{
83+
if ( layerDataIt->vectorLayer )
84+
{
85+
nFeatures += layerDataIt->vectorLayer->featureCount();
86+
}
87+
}
6188
}
6289

63-
//create DualEdgeTriangulation
90+
QProgressDialog* theProgressDialog = 0;
91+
if ( mShowProgressDialog )
92+
{
93+
theProgressDialog = new QProgressDialog( QObject::tr( "Building triangulation..." ), QObject::tr( "Abort" ), 0, nFeatures, 0 );
94+
theProgressDialog->setWindowModality( Qt::WindowModal );
95+
}
6496

65-
DualEdgeTriangulation* theDualEdgeTriangulation = new DualEdgeTriangulation( mCachedBaseData.size(), 0 );
66-
mTriangulation = theDualEdgeTriangulation;
6797

68-
//add all the vertices to the triangulation
69-
QVector<vertexData>::const_iterator vertex_it = mCachedBaseData.constBegin();
70-
for ( ; vertex_it != mCachedBaseData.constEnd(); ++vertex_it )
98+
QgsFeature f;
99+
QList<LayerData>::iterator layerDataIt = mLayerData.begin();
100+
for ( ; layerDataIt != mLayerData.end(); ++layerDataIt )
71101
{
72-
Point3D* thePoint = new Point3D( vertex_it->x, vertex_it->y, vertex_it->z );
73-
mTriangulation->addPoint( thePoint );
102+
if ( layerDataIt->vectorLayer )
103+
{
104+
QgsAttributeList attList;
105+
if ( !layerDataIt->zCoordInterpolation )
106+
{
107+
attList.push_back( layerDataIt->interpolationAttribute );
108+
}
109+
layerDataIt->vectorLayer->select( attList );
110+
while ( layerDataIt->vectorLayer->nextFeature( f ) )
111+
{
112+
if ( mShowProgressDialog )
113+
{
114+
if ( theProgressDialog->wasCanceled() )
115+
{
116+
break;
117+
}
118+
theProgressDialog->setValue( nProcessedFeatures );
119+
}
120+
insertData( &f, layerDataIt->zCoordInterpolation, layerDataIt->interpolationAttribute, layerDataIt->mInputType );
121+
++nProcessedFeatures;
122+
}
123+
}
74124
}
75125

126+
delete theProgressDialog;
76127
mTriangleInterpolator = new LinTriangleInterpolator( theDualEdgeTriangulation );
77-
78128
mIsInitialized = true;
129+
130+
//debug
131+
if ( mExportTriangulationToFile )
132+
{
133+
theDualEdgeTriangulation->saveAsShapefile( mTriangulationFilePath );
134+
}
79135
}
136+
137+
int QgsTINInterpolator::insertData( QgsFeature* f, bool zCoord, int attr, InputType type )
138+
{
139+
if ( !f )
140+
{
141+
return 1;
142+
}
143+
144+
QgsGeometry* g = f->geometry();
145+
{
146+
if ( !g )
147+
{
148+
return 2;
149+
}
150+
}
151+
152+
//check attribute value
153+
double attributeValue = 0;
154+
bool attributeConversionOk = false;
155+
if ( !zCoord )
156+
{
157+
QgsAttributeMap attMap = f->attributeMap();
158+
QgsAttributeMap::const_iterator att_it = attMap.find( attr );
159+
if ( att_it == attMap.end() ) //attribute not found, something must be wrong (e.g. NULL value)
160+
{
161+
return 3;
162+
}
163+
attributeValue = att_it.value().toDouble( &attributeConversionOk );
164+
if ( !attributeConversionOk || isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
165+
{
166+
return 4;
167+
}
168+
}
169+
170+
//parse WKB. We cannot use the methods with QgsPoint because they don't contain z-values for 25D types
171+
bool hasZValue = false;
172+
double x, y, z;
173+
unsigned char* currentWkbPtr = g->asWkb();
174+
175+
QGis::WkbType wkbType = g->wkbType();
176+
switch ( wkbType )
177+
{
178+
case QGis::WKBPoint25D:
179+
hasZValue = true;
180+
case QGis::WKBPoint:
181+
{
182+
currentWkbPtr += ( 1 + sizeof( int ) );
183+
x = *(( double * )( currentWkbPtr ) );
184+
currentWkbPtr += sizeof( double );
185+
y = *(( double * )( currentWkbPtr ) );
186+
if ( zCoord && hasZValue )
187+
{
188+
currentWkbPtr += sizeof( double );
189+
z = *(( double * )( currentWkbPtr ) );
190+
}
191+
else
192+
{
193+
z = attributeValue;
194+
}
195+
Point3D* thePoint = new Point3D( x, y, z );
196+
if ( mTriangulation->addPoint( thePoint ) == -100 )
197+
{
198+
return -1;
199+
}
200+
break;
201+
}
202+
case QGis::WKBLineString25D:
203+
hasZValue = true;
204+
case QGis::WKBLineString:
205+
{
206+
//maybe a structure or break line
207+
Line3D* line = 0;
208+
if ( type != POINTS )
209+
{
210+
line = new Line3D();
211+
}
212+
currentWkbPtr += ( 1 + sizeof( int ) );
213+
int* npoints = ( int* )currentWkbPtr;
214+
currentWkbPtr += sizeof( int );
215+
for ( int index = 0; index < *npoints; ++index )
216+
{
217+
x = *(( double * )( currentWkbPtr ) );
218+
currentWkbPtr += sizeof( double );
219+
y = *(( double * )( currentWkbPtr ) );
220+
currentWkbPtr += sizeof( double );
221+
if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
222+
{
223+
z = *(( double * )( currentWkbPtr ) );
224+
}
225+
else
226+
{
227+
z = attributeValue;
228+
}
229+
if ( hasZValue )
230+
{
231+
currentWkbPtr += sizeof( double );
232+
}
233+
234+
if ( type == POINTS )
235+
{
236+
//todo: handle error code -100
237+
mTriangulation->addPoint( new Point3D( x, y, z ) );
238+
}
239+
else
240+
{
241+
line->insertPoint( new Point3D( x, y, z ) );
242+
}
243+
}
244+
245+
if ( type != POINTS )
246+
{
247+
mTriangulation->addLine( line, type == BREAK_LINES );
248+
}
249+
break;
250+
}
251+
default:
252+
//todo: add the same for multiline, polygon, multipolygon
253+
break;
254+
}
255+
256+
return 0;
257+
}
258+

‎src/analysis/interpolation/qgstininterpolator.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,17 @@
1919
#define QGSTININTERPOLATOR_H
2020

2121
#include "qgsinterpolator.h"
22+
#include <QString>
2223

2324
class Triangulation;
2425
class TriangleInterpolator;
26+
class QgsFeature;
2527

2628
/**Interpolation in a triangular irregular network*/
2729
class ANALYSIS_EXPORT QgsTINInterpolator: public QgsInterpolator
2830
{
2931
public:
30-
QgsTINInterpolator( const QList<QgsVectorLayer*>& inputData );
32+
QgsTINInterpolator( const QList<LayerData>& inputData, bool showProgressDialog = false );
3133
~QgsTINInterpolator();
3234

3335
/**Calculates interpolation value for map coordinates x, y
@@ -37,12 +39,28 @@ class ANALYSIS_EXPORT QgsTINInterpolator: public QgsInterpolator
3739
@return 0 in case of success*/
3840
int interpolatePoint( double x, double y, double& result );
3941

42+
void setExportTriangulationToFile( bool e ) {mExportTriangulationToFile = e;}
43+
void setTriangulationFilePath( const QString& filepath ) {mTriangulationFilePath = filepath;}
44+
4045
private:
4146
Triangulation* mTriangulation;
4247
TriangleInterpolator* mTriangleInterpolator;
4348
bool mIsInitialized;
49+
bool mShowProgressDialog;
50+
/**If true: export triangulation to shapefile after initialisation*/
51+
bool mExportTriangulationToFile;
52+
/**File path to export the triangulation*/
53+
QString mTriangulationFilePath;
4454

55+
/**Create dual edge triangulation*/
4556
void initialize();
57+
/**Inserts the vertices of a geometry into the triangulation
58+
@param g the geometry
59+
@param zCoord true if the z coordinate is the interpolation attribute
60+
@param attr interpolation attribute index (if zCoord is false)
61+
@param type point/structure line, break line
62+
@return 0 in case of success, -1 if the feature could not be inserted because of numerical problems*/
63+
int insertData( QgsFeature* f, bool zCoord, int attr, InputType type );
4664
};
4765

4866
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.