1
/***************************************************************************
2
NormVecDecorator.cc - description
4
copyright : (C) 2004 by Marco Hugentobler
5
email : mhugent@geo.unizh.ch
6
***************************************************************************/
8
/***************************************************************************
10
* This program is free software; you can redistribute it and/or modify *
11
* it under the terms of the GNU General Public License as published by *
12
* the Free Software Foundation; either version 2 of the License, or *
13
* (at your option) any later version. *
15
***************************************************************************/
17
#include "NormVecDecorator.h"
18
#include "qgslogger.h"
19
#include <QApplication>
20
#include <QProgressDialog>
22
NormVecDecorator::~NormVecDecorator()
24
//remove all the normals
25
if ( mNormVec->count() > 0 )
27
for ( int i = 0; i < mNormVec->count(); i++ )
29
delete( *mNormVec )[i];
42
int NormVecDecorator::addPoint( Point3D* p )
47
pointno = mTIN->addPoint( p );
49
if ( pointno == -100 )//a numerical error occured
51
// QgsDebugMsg("warning, numerical error");
55
//recalculate the necessary normals
56
if ( alreadyestimated )
58
estimateFirstDerivative( pointno );
59
//update also the neighbours of the new point
60
QList<int>* list = mTIN->getSurroundingTriangles( pointno );
61
QList<int>::iterator it = list->begin();//iterate through the list and analize it
62
while ( it != list->end() )
68
estimateFirstDerivative( point );
83
bool NormVecDecorator::calcNormal( double x, double y, Vector3D* result )
85
if ( alreadyestimated == false )
87
estimateFirstDerivatives();
88
alreadyestimated = true;
93
bool b = mInterpolator->calcNormVec( x, y, result );
98
QgsDebugMsg( "warning, null pointer" );
103
bool NormVecDecorator::calcNormalForPoint( double x, double y, int point, Vector3D* result )
105
if ( alreadyestimated == false )
107
estimateFirstDerivatives();
108
alreadyestimated = true;
113
int numberofbreaks = 0;//number of breaklines around the point
114
int ffirstbp = -1000; //numbers of the points related to the first breakline
115
int lfirstbp = -1000;
116
bool pointfound = false;//is set to true, if the triangle with the point in is found
117
int numberofruns = 0;//number of runs of the loop. This integer can be used to prevent endless loops
118
int limit = 100000;//ater this number of iterations, the method is terminated
124
QList<int>* vlist = getSurroundingTriangles( point );//get the value list
126
if ( !vlist )//an error occured in 'getSurroundingTriangles'
131
if ((( vlist->count() ) % 4 ) != 0 )//number of items in vlist has to be a multiple of 4
133
QgsDebugMsg( "warning, wrong number of items in vlist" );
137
QList<int>::iterator it = vlist->begin();
141
while ( true )//endless loop to analyze vlist
144
if ( numberofruns > limit )
146
QgsDebugMsg( "warning, a probable endless loop is detected" );
150
int p1, p2, p3, line;
151
firstrun = false;//flag which tells, if it is the first run with a breakline
161
if ( numberofbreaks > 0 )
164
if ( p1 != -1 && p2 != -1 && p2 != -1 )
166
if ( MathUtils::pointInsideTriangle( x, y, getPoint( p1 ), getPoint( p2 ), getPoint( p3 ) ) )
171
Vector3D addvec( 0, 0, 0 );
172
MathUtils::normalFromPoints( getPoint( p1 ), getPoint( p2 ), getPoint( p3 ), &addvec );
173
result->setX( result->getX() + addvec.getX() );
174
result->setY( result->getY() + addvec.getY() );
175
result->setZ( result->getZ() + addvec.getZ() );
179
if ( line == -10 )//we found a breakline
182
if ( numberofbreaks == 0 )//it is the first breakline
185
ffirstbp = p2;//set the marks to recognize the breakline later
189
if ( p2 == ffirstbp && p3 == lfirstbp && firstrun == false )//we are back at the first breakline
191
if ( pointfound == false )//the point with coordinates x, y was in no triangle
193
QgsDebugMsg( "warning: point (x,y) was in no triangle" );
196
result->standardise();
200
if ( numberofbreaks > 0 && pointfound == true )//we found the second break line and the point is between the first and the second
202
result->standardise();
203
numberofbreaks++;//to make the distinction between endpoints and points on a breakline easier
214
if ( it == vlist->end() )//restart at the beginning of the loop
215
{it = vlist->begin();}
228
QgsDebugMsg( "warning, null pointer" );
234
bool NormVecDecorator::calcPoint( double x, double y, Point3D* result )
237
if ( alreadyestimated == false )
239
estimateFirstDerivatives();
240
alreadyestimated = true;
245
bool b = mInterpolator->calcPoint( x, y, result );
250
QgsDebugMsg( "warning, null pointer" );
255
bool NormVecDecorator::getTriangle( double x, double y, Point3D* p1, Vector3D* v1, Point3D* p2, Vector3D* v2, Point3D* p3, Vector3D* v3 )
257
if ( p1 && p2 && p3 && v1 && v2 && v3 )
259
int* nr1 = new int();
260
int* nr2 = new int();
261
int* nr3 = new int();
263
if ( TriDecorator::getTriangle( x, y, p1, nr1, p2, nr2, p3, nr3 ) )//everything allright
265
if (( *mNormVec )[( *nr1 )] && ( *mNormVec )[( *nr2 )] && ( *mNormVec )[( *nr3 )] )
267
v1->setX(( *mNormVec )[( *nr1 )]->getX() );
268
v1->setY(( *mNormVec )[( *nr1 )]->getY() );
269
v1->setZ(( *mNormVec )[( *nr1 )]->getZ() );
271
v2->setX(( *mNormVec )[( *nr2 )]->getX() );
272
v2->setY(( *mNormVec )[( *nr2 )]->getY() );
273
v2->setZ(( *mNormVec )[( *nr2 )]->getZ() );
275
v3->setX(( *mNormVec )[( *nr3 )]->getX() );
276
v3->setY(( *mNormVec )[( *nr3 )]->getY() );
277
v3->setZ(( *mNormVec )[( *nr3 )]->getZ() );
281
QgsDebugMsg( "warning, null pointer" );
306
QgsDebugMsg( "warning, null pointer" );
311
NormVecDecorator::pointState NormVecDecorator::getState( int pointno ) const
315
return mPointState->at( pointno );
319
QgsDebugMsg( "warning, number below 0" );
320
return mPointState->at( 0 );//just to avoid a compiler warning
325
bool NormVecDecorator::getTriangle( double x, double y, Point3D* p1, int* ptn1, Vector3D* v1, pointState* state1, Point3D* p2, int* ptn2, Vector3D* v2, pointState* state2, Point3D* p3, int* ptn3, Vector3D* v3, pointState* state3 )
327
if ( p1 && p2 && p3 && v1 && v2 && v3 && ptn1 && ptn2 && ptn3 && state1 && state2 && state3 )
329
if ( TriDecorator::getTriangle( x, y, p1, ptn1, p2, ptn2, p3, ptn3 ) )//everything allright
331
v1->setX(( *mNormVec )[( *ptn1 )]->getX() );
332
v1->setY(( *mNormVec )[( *ptn1 )]->getY() );
333
v1->setZ(( *mNormVec )[( *ptn1 )]->getZ() );
335
( *state1 ) = ( *mPointState )[( *ptn1 )];
337
v2->setX(( *mNormVec )[( *ptn2 )]->getX() );
338
v2->setY(( *mNormVec )[( *ptn2 )]->getY() );
339
v2->setZ(( *mNormVec )[( *ptn2 )]->getZ() );
341
( *state2 ) = ( *mPointState )[( *ptn2 )];
343
v3->setX(( *mNormVec )[( *ptn3 )]->getX() );
344
v3->setY(( *mNormVec )[( *ptn3 )]->getY() );
345
v3->setZ(( *mNormVec )[( *ptn3 )]->getZ() );
347
( *state3 ) = ( *mPointState )[( *ptn3 )];
353
QgsDebugMsg( "warning, getTriangle returned false" );
360
QgsDebugMsg( "warning, null pointer" );
365
bool NormVecDecorator::estimateFirstDerivative( int pointno )
377
int numberofbreaks = 0;//number of counted breaklines
378
double weights = 0;//sum of the weights
379
double currentweight = 0;//current weight
382
QList<int>* vlist = getSurroundingTriangles( pointno );//get the value list
386
//something went wrong in getSurroundingTriangles, set the normal to (0,0,0)
387
if ( mNormVec->size() <= mNormVec->count() )//allocate more memory if necessary
389
QgsDebugMsg( QString( "resizing mNormVec from %1 to %2" ).arg( mNormVec->size() ).arg( mNormVec->size() + 1 ) );
390
mNormVec->resize( mNormVec->size() + 1 );
393
//todo:resize mNormVec if necessary
395
if ( !(( *mNormVec )[pointno] ) )//insert a pointer to a Vector3D, if there is none at this position
397
Vector3D* vec = new Vector3D( total.getX(), total.getY(), total.getZ() );
398
mNormVec->insert( pointno, vec );
402
( *mNormVec )[pointno]->setX( 0 );
403
( *mNormVec )[pointno]->setY( 0 );
404
( *mNormVec )[pointno]->setZ( 0 );
409
if (( vlist->count() % 4 ) != 0 ) //number of items in vlist has to be a multiple of 4
411
QgsDebugMsg( "warning, wrong number of items in vlist" );
415
QList<int>::iterator it = vlist->begin();//iterate through the list and analize it
416
while ( it != vlist->end() )
418
int p1, p2, p3, flag;
433
if ( flag == -10 )//we found a breakline.
438
if ( p1 != -1 && p2 != -1 && p3 != -1 )//don't calculate normal, if a point is a virtual point
440
MathUtils::normalFromPoints( getPoint( p1 ), getPoint( p2 ), getPoint( p3 ), &part );
441
double dist1 = getPoint( p3 )->dist3D( getPoint( p1 ) );
442
double dist2 = getPoint( p3 )->dist3D( getPoint( p2 ) );
443
//don't add the normal if the triangle is horizontal
444
if (( getPoint( p1 )->getZ() != getPoint( p2 )->getZ() ) || ( getPoint( p1 )->getZ() != getPoint( p3 )->getZ() ) )
446
currentweight = 1 / ( dist1 * dist1 * dist2 * dist2 );
447
total.setX( total.getX() + part.getX()*currentweight );
448
total.setY( total.getY() + part.getY()*currentweight );
449
total.setZ( total.getZ() + part.getZ()*currentweight );
450
weights += currentweight;
456
if ( total.getX() == 0 && total.getY() == 0 && total.getZ() == 0 )//we have a point surrounded by horizontal triangles
462
total.setX( total.getX() / weights );
463
total.setY( total.getY() / weights );
464
total.setZ( total.getZ() / weights );
469
if ( numberofbreaks == 0 )
473
else if ( numberofbreaks == 1 )
484
//insert the new calculated vector
485
if ( mNormVec->size() <= mNormVec->count() )//allocate more memory if necessary
487
mNormVec->resize( mNormVec->size() + 1 );
490
if ( !(( *mNormVec )[pointno] ) )//insert a pointer to a Vector3D, if there is none at this position
492
Vector3D* vec = new Vector3D( total.getX(), total.getY(), total.getZ() );
493
mNormVec->insert( pointno, vec );
497
( *mNormVec )[pointno]->setX( total.getX() );
498
( *mNormVec )[pointno]->setY( total.getY() );
499
( *mNormVec )[pointno]->setZ( total.getZ() );
502
//insert the new status
504
if ( pointno >= mPointState->size() )
506
mPointState->resize( mPointState->size() + 1 );
509
( *mPointState )[pointno] = status;
514
//weighted method of little
515
bool NormVecDecorator::estimateFirstDerivatives( QProgressDialog* d )
520
d->setMaximum( getNumberOfPoints() );
521
d->setCancelButton( 0 ); //we cannot cancel derivative estimation
525
for ( int i = 0; i < getNumberOfPoints(); i++ )
531
estimateFirstDerivative( i );
536
d->setValue( getNumberOfPoints() );
541
void NormVecDecorator::eliminateHorizontalTriangles()
545
if ( alreadyestimated )
547
mTIN->eliminateHorizontalTriangles();
548
estimateFirstDerivatives();
552
mTIN->eliminateHorizontalTriangles();
557
QgsDebugMsg( "warning, null pointer" );
561
void NormVecDecorator::setState( int pointno, pointState s )
565
( *mPointState )[pointno] = s;
569
QgsDebugMsg( "warning, pointno>0" );
573
bool NormVecDecorator::swapEdge( double x, double y )
578
if ( alreadyestimated )
580
QList<int>* list = getPointsAroundEdge( x, y );
583
b = mTIN->swapEdge( x, y );
584
QList<int>::iterator it;
585
for ( it = list->begin(); it != list->end(); ++it )
587
estimateFirstDerivative(( *it ) );
594
b = mTIN->swapEdge( x, y );
600
QgsDebugMsg( "warning, null pointer" );
605
bool NormVecDecorator::saveAsShapefile( const QString& fileName ) const
611
return mTIN->saveAsShapefile( fileName );