Skip to content

Commit e25e8a9

Browse files
author
mhugent
committed
Updated interpolation classes with the changes in trunk
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@11553 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent aa71b1e commit e25e8a9

15 files changed

+409
-99
lines changed

src/analysis/CMakeLists.txt

+1
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

+119-33
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

+11-3
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

0 commit comments

Comments
 (0)