00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "ConstrainedVertex.h"
00019 #include "octree_instanciation.h"
00020
00021 #include <set>
00022 #include "SFVec3fCellConstrained.h"
00023 #include <iostream>
00024 using std::cerr;
00025 using std::endl;
00026
00027 #include "Octree.h"
00028
00029
00030 namespace animal
00031 {
00032 namespace octree
00033 {
00037 ConstrainedVertex::ConstrainedVertex( Vec3d position, CVertex *cv1, CVertex *cv2, CVertex *cv3, CVertex *cv4,
00038 CVertex *cv5, CVertex *cv6, CVertex *cv7, CVertex *cv8,
00039 Cell *connectedCell ) :
00040 _position(position),
00041 _velocity(0,0,0),
00042 _mass(0),
00043 _fatherCell(connectedCell), _mainCell(NULL), _geoLink(NULL)
00044 , _lastConstrainedDepth(0)
00045 {
00046
00047 std::vector<ConstrainedVertex*> parents(8);
00048 std::vector<unsigned short> empty(0);
00049 parents[0] = cv1;
00050 parents[1] = cv2;
00051 parents[2] = cv3;
00052 parents[3] = cv4;
00053 parents[4] = cv5;
00054 parents[5] = cv6;
00055 parents[6] = cv7;
00056 parents[7] = cv8;
00057
00058 _geoLink = new GeoLink( parents, empty, true, this );
00059
00060
00061 Ensure( isFree() );
00062 }
00063
00064
00065 ConstrainedVertex::ConstrainedVertex( Vec3d position, Cell *connectedCell ) :
00066 _position(position),
00067 _velocity(0,0,0),
00068 _mass(0),
00069 _fatherCell(connectedCell), _mainCell(NULL), _geoLink(NULL)
00070 ,_lastConstrainedDepth(0)
00071 {
00072
00073 Ensure( (isFree()) && (this->get_Vec3d() == position) );
00074 Ensure( nChildren() == 0 );
00075
00076
00077 }
00078
00079
00080 ConstrainedVertex::ConstrainedVertex( FloatingPointType x, FloatingPointType y, FloatingPointType z, Cell *connectedCell ) :
00081 _position(Vec3d(x,y,z)),
00082 _velocity(0,0,0),
00083 _mass(0),
00084 _fatherCell(connectedCell), _mainCell(NULL), _geoLink(NULL)
00085 ,_lastConstrainedDepth(0)
00086 {
00087
00088 Ensure( (isFree()) && (this->get_Vec3d() == Vec3d(x,y,z)) );
00089 Ensure( nChildren() == 0 );
00090 }
00091
00092
00093 ConstrainedVertex::ConstrainedVertex( const ConstrainedVertex & cmsv )
00094 {
00095 copyAllData( cmsv );
00096 }
00097
00098
00099 ConstrainedVertex & ConstrainedVertex ::operator=( const ConstrainedVertex & cmsv )
00100 {
00101 copyAllData( cmsv );
00102 return *this;
00103 }
00104
00105
00106
00107
00108
00109 ConstrainedVertex::~ConstrainedVertex()
00110 {
00111 Require( nChildren() == 0 );
00112 if( nChildren() != 0 )
00113 {
00114 std::cerr << "This is " << this << " of depth " << this->getDepth() << "\n";
00115 std::cerr << *(getMainCell()) << "\n";
00116 std::cerr << "My children are :\n";
00117 for( unsigned int i=0 ; i<nChildren(); ++i )
00118 {
00119 std::cerr << "\tchild["<<i<<"] = " << child(i) << " of depth " << child(i)->getDepth() << "\n";
00120 std::cerr << "\t\tIt's main cell is " << child(i)->getMainCell() << " of depth " << child(i)->getMainCell()->getData()._depth << "and vId is " << child(i)->getMainCellVertexId() << "\n";
00121 std::cerr << "\t\t" << *(child(i)->getMainCell()) << "\n";
00122 }
00123 exit(0);
00124 }
00125
00126 if( _geoLink != NULL )
00127 {
00128 delete _geoLink;
00129 _geoLink = NULL;
00130 }
00131
00132
00133 Require( nConnectedCells() ==0 );
00134 while( nConnectedCells() !=0 )
00135 {
00136 this->unregisterCell(this->connectedCell(0));
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 }
00156
00157
00158 void ConstrainedVertex::copyAllData( const ConstrainedVertex & cmsv )
00159 {
00160
00161 for( unsigned short i = 0 ; i<3 ; ++i )
00162 _positionROPointer[i] = cmsv._positionROPointer[i];
00163
00164 _connectedCells = cmsv._connectedCells;
00165
00166 _position = cmsv._position;
00167 _childs = cmsv._childs;
00168 _data = cmsv._data;
00169 _geoLink = new GeoLink( *cmsv._geoLink );
00170 _fatherCell = cmsv._fatherCell;
00171 _frame = cmsv._frame;
00172 _vertexId = cmsv._vertexId;
00173 _mainCell = cmsv._mainCell;
00174
00175 std::cerr << "WARNING : copy All Data :\n";
00176 if( _mainCell != NULL )
00177 std::cerr << "\tmaincell is " << *_mainCell << "\n";
00178 getchar();
00179 }
00180
00181
00182
00183
00184
00185
00188 bool ConstrainedVertex::isFree() const
00189 {
00190 if( _geoLink == NULL )
00191
00192 return true;
00193 else
00194 return _geoLink->isFree();
00195 }
00196
00198 Vec3d ConstrainedVertex::get_Vec3d() const
00199 {
00200 return _position;
00201 }
00202
00203
00207 ConstrainedVertex::operator const FloatingPointType*()
00208 {
00209 Vec3d vec3d = this->get_Vec3d();
00210
00211 _positionROPointer[0] = vec3d[0];
00212 _positionROPointer[1] = vec3d[1];
00213 _positionROPointer[2] = vec3d[2];
00214
00215 return _positionROPointer;
00216 }
00217
00218 FloatingPointType ConstrainedVertex::operator[]( int id ) const
00219 {
00220 return this->get_Vec3d()[id];
00221 }
00222
00223 FloatingPointType* ConstrainedVertex::get_FloatingPointTypePointerCopy() const
00224 {
00225 Vec3d vec3d = this->get_Vec3d();
00226
00227 FloatingPointType *toReturn = (FloatingPointType*) malloc( sizeof(FloatingPointType)*3 );
00228 toReturn[0] = vec3d[0];
00229 toReturn[1] = vec3d[1];
00230 toReturn[2] = vec3d[2];
00231
00232 return toReturn;
00233 }
00234
00235
00236
00237
00238
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 typedef struct
00267 {
00268 ConstrainedVertex *_vertex;
00269 Vec3d _vecToAdd;
00270 }
00271 UpdateChildrensPositionOptimizedData;
00272
00273 struct UpdateChildrensPositionOptimizedDataLess
00274 {
00275 bool operator()( const UpdateChildrensPositionOptimizedData & d1,
00276 const UpdateChildrensPositionOptimizedData &d2 ) const
00277 {
00278 return d1._vertex < d2._vertex;
00279 }
00280 };
00281
00282 bool operator<( const UpdateChildrensPositionOptimizedData & d1,
00283 const UpdateChildrensPositionOptimizedData &d2 )
00284 {
00285 return d1._vertex < d2._vertex;
00286 }
00287 bool operator!=( const UpdateChildrensPositionOptimizedData & d1,
00288 const UpdateChildrensPositionOptimizedData &d2 )
00289 {
00290 return d1._vertex != d2._vertex;
00291 }
00292
00293
00294 void ConstrainedVertex::updateChildrensPositionOptimized( Vec3d v, unsigned int depth )
00295 {
00296
00297
00298
00299
00300 typedef std::map<ConstrainedVertex*,Vec3d> map;
00301 typedef std::deque<ConstrainedVertex*> list;
00302
00303 map toAddMap;
00304 list vertexList;
00305
00306 for( unsigned int i=0 ; i<_childs.size() ; i++ )
00307 {
00308
00309 if( (_childs[i]->getDepth() > depth) || !_childs[i]->isFree() )
00310 {
00311 if( _childs[i]->getGeoLink()->isGeoLinkParent(this) )
00312 {
00313 _childs[i]->setDelta( Vec3d(0,0,0) );
00314 toAddMap[_childs[i]] = v / _childs[i]->getGeoLink()->getNGeoParents();
00315 vertexList.push_back( _childs[i] );
00316 }
00317 }
00318 }
00319
00320 for( list::iterator it = vertexList.begin() ; it != vertexList.end() ; ++it )
00321 {
00322 (*it)->setDelta( Vec3d(0,0,0) );
00323 }
00324
00325 while( !vertexList.empty() )
00326 {
00327 ConstrainedVertex* d = vertexList.front();
00328 vertexList.pop_front();
00329
00330 for( unsigned i=0 ; i<d->_childs.size() ; ++i )
00331 {
00332 if( d->_childs[i]->getGeoLink()->isGeoLinkParent(d) )
00333 {
00334
00335 Vec3d vecToAdd = toAddMap[d] / d->_childs[i]->getGeoLink()->getNGeoParents();
00336
00337
00338
00339 if( toAddMap.find(d->_childs[i]) == toAddMap.end() )
00340 {
00341
00342
00343 d->_childs[i]->setDelta( Vec3d(0,0,0) );
00344 toAddMap[d->_childs[i]] = vecToAdd;
00345 vertexList.push_back(d->_childs[i]);
00346 }
00347 else
00348 {
00349
00350 toAddMap[d->_childs[i]] += vecToAdd;
00351 }
00352 }
00353 else
00354 {
00355
00356 }
00357 }
00358
00359 d->setPosition( d->_position + toAddMap[d] );
00360
00361 d->setDelta( d->getDelta() + toAddMap[d] );
00362 }
00363
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 void ConstrainedVertex::updateChildrensPositionOptimizedNotFree( Vec3d v )
00383 {
00384
00385
00386
00387
00388 Require( !isFree() );
00389
00390 typedef std::map<ConstrainedVertex*,Vec3d> map;
00391 typedef std::deque<ConstrainedVertex*> list;
00392
00393 map toAddMap;
00394 list vertexList;
00395
00396
00397
00398 list tmpParents;
00399 tmpParents.push_front( this );
00400 while( !tmpParents.empty() )
00401 {
00402 ConstrainedVertex* cour = tmpParents.front();
00403 Require( !cour->isFree() );
00404
00405 tmpParents.pop_front();
00406
00407 for( unsigned int i=0 ; i<cour->getGeoLink()->getNGeoParents() ; ++i )
00408 {
00409 ConstrainedVertex* parent = cour->getGeoLink()->getGeoParent(cour->getGeoLink()->getGeoParentId(i));
00410 if( !parent->isFree() )
00411 {
00412 tmpParents.push_back( parent );
00413 }
00414 else
00415 {
00416
00417
00418 if( toAddMap.find(parent) == toAddMap.end() )
00419 {
00420 toAddMap[ parent ] = v;
00421 vertexList.push_back( parent );
00422 }
00423 }
00424 }
00425 }
00426
00427 for( list::iterator it = vertexList.begin() ; it != vertexList.end() ; ++it )
00428 {
00429 (*it)->setDelta( Vec3d(0,0,0) );
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 while( !vertexList.empty() )
00447 {
00448 ConstrainedVertex* d = vertexList.front();
00449 vertexList.pop_front();
00450
00451 for( unsigned i=0 ; i<d->_childs.size() ; ++i )
00452 {
00453 if( d->_childs[i]->getGeoLink()->isGeoLinkParent(d) )
00454 {
00455
00456 Vec3d vecToAdd = toAddMap[d] / d->_childs[i]->getGeoLink()->getNGeoParents();
00457
00458
00459
00460 if( toAddMap.find(d->_childs[i]) == toAddMap.end() )
00461 {
00462
00463
00464 d->_childs[i]->setDelta( Vec3d(0,0,0) );
00465 toAddMap[d->_childs[i]] = vecToAdd;
00466 vertexList.push_back(d->_childs[i]);
00467 }
00468 else
00469 {
00470
00471 toAddMap[d->_childs[i]] += vecToAdd;
00472 }
00473 }
00474 else
00475 {
00476
00477 }
00478 }
00479
00480 d->_position += toAddMap[d];
00481 d->setDelta( d->getDelta() + toAddMap[d] );
00482 }
00483
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 void ConstrainedVertex::updateChildrensPosition( Vec3d v, unsigned int depth )
00497 {
00498 for( unsigned int i=0 ; i<_childs.size() ; i++ )
00499 {
00500 if( _childs[i]->getDepth() > depth )
00501 {
00502 _childs[i]->updatePosition( this, v );
00503 }
00504 else if( !_childs[i]->isFree() )
00505 {
00506
00507 _childs[i]->updateConstrainedChildrensPosition( v, depth );
00508 }
00509 }
00510 }
00511
00512 void ConstrainedVertex::updateConstrainedChildrensPosition( Vec3d v, unsigned int depth )
00513 {
00514 depth = 0;
00515 exit(0);
00516 Require( !isFree() );
00517
00518 Vec3d newPos = _position + v / this->getGeoLink()->getNGeoParents();
00519 for( unsigned int i=0 ; i<_childs.size() ; i++ )
00520 {
00521 if( !_childs[i]->isFree() )
00522
00523 updateConstrainedChildrensPosition( newPos - _position, 0 );
00524
00525 }
00526 _position = newPos;
00527 }
00528
00529
00530
00531
00532 void ConstrainedVertex::updatePosition( ConstrainedVertex *parent, Vec3d v )
00533 {
00534 Require( _geoLink != NULL );
00535 if( this->getGeoLink()->isGeoLinkParent(parent) )
00536 {
00537 Vec3d newPos = _position + v / this->getGeoLink()->getNGeoParents();
00538
00539 updateChildrensPosition( newPos - _position, 0 );
00540 _position = newPos;
00541 }
00542
00543 }
00544
00545
00546
00547
00548 ConstrainedVertex::operator const Vec3d() const
00549 {
00550 return get_Vec3d();
00551 }
00552
00556 void ConstrainedVertex::freeIt()
00557 {
00558 Require( !isFree() );
00559 Require( _geoLink != NULL );
00560
00561 this->getGeoLink()->freeIt();
00562
00563 Ensure( isFree() );
00564
00565 }
00566
00567
00568
00569
00570
00571 void ConstrainedVertex::softLinkIt( ConstrainedVertex* cv1, ConstrainedVertex* cv2 )
00572 {
00573 Require( _geoLink != NULL );
00574
00575 this->getGeoLink()->softLinkIt( cv1, cv2 );
00576
00577 setValue( POS, getPosition() );
00578
00579 computeValueFromRelatives( VEL );
00580
00581 }
00582 void ConstrainedVertex::softLinkIt( ConstrainedVertex* cv1, ConstrainedVertex* cv2, ConstrainedVertex* cv3, ConstrainedVertex* cv4 )
00583 {
00584 Require( _geoLink != NULL );
00585
00586 this->getGeoLink()->softLinkIt( cv1, cv2, cv3, cv4 );
00587
00588 setValue( POS, getPosition() );
00589
00590 computeValueFromRelatives( VEL );
00591 }
00592
00593 void ConstrainedVertex::softLinkIt( ConstrainedVertex* cv1, ConstrainedVertex* cv2, ConstrainedVertex* cv3, ConstrainedVertex* cv4, ConstrainedVertex* cv5, ConstrainedVertex* cv6, ConstrainedVertex* cv7, ConstrainedVertex* cv8 )
00594 {
00595 Require( _geoLink != NULL );
00596
00597 this->getGeoLink()->softLinkIt( cv1, cv2, cv3, cv4, cv5, cv6, cv7, cv8 );
00598
00599 setValue( POS, getPosition() );
00600
00601 computeValueFromRelatives( VEL );
00602 }
00603
00604
00605 void ConstrainedVertex::hardLinkIt( ConstrainedVertex* cv1, ConstrainedVertex* cv2, ConstrainedVertex* cv3, ConstrainedVertex* cv4 )
00606 {
00607 Require( isFree() );
00608 Require( _geoLink != NULL );
00609
00610 this->getGeoLink()->hardLinkIt( cv1, cv2, cv3, cv4 );
00611
00612
00613
00614 Ensure( !isFree() );
00615
00616
00617 setValue( POS, getPosition() );
00618 computeValueFromParents( VEL );
00619
00620
00621
00622
00623
00624
00625 }
00629 void ConstrainedVertex::hardLinkIt( ConstrainedVertex* cv1, ConstrainedVertex* cv2 )
00630 {
00631 Require( isFree() );
00632 Require( _geoLink != NULL );
00633
00634 this->getGeoLink()->hardLinkIt( cv1, cv2 );
00635
00636
00637
00638
00639
00640 Ensure( !isFree() );
00641
00642
00643 setValue( POS, getPosition() );
00644
00645 computeValueFromParents( VEL );
00646
00647
00648
00649 }
00650
00651
00652
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00686 bool ConstrainedVertex::isChild( const ConstrainedVertex *cv ) const
00687 {
00688 for( unsigned int i=0 ; i<_childs.size() ; i++ )
00689 if( _childs[i] == cv )
00690 return true;
00691
00692 return false;
00693 }
00694
00699 void ConstrainedVertex::addChild( ConstrainedVertex *cv )
00700 {
00701 Require( !isChild(cv) );
00702
00703
00704
00705 _childs.push_back(cv);
00706
00707 Ensure( isChild(cv) );
00708 }
00713 void ConstrainedVertex::removeChild( ConstrainedVertex *cv )
00714 {
00715 Require( isChild(cv) );
00716 _childs.erase( _childs.begin() + getChildPos(cv) );
00717 Ensure( !isChild(cv) );
00718 }
00719
00723 unsigned int ConstrainedVertex::getChildPos( ConstrainedVertex *cv ) const
00724 {
00725 Require( isChild(cv) );
00726 unsigned int i;
00727 for( i=0 ; i<_childs.size() ; i++ )
00728 if( _childs[i] == cv )
00729 break;
00730
00731 return i;
00732 }
00733
00734
00738 ConstrainedVertex * ConstrainedVertex::child( const unsigned int pos ) const
00739 {
00740 Require( pos < nChildren() );
00741 return _childs[pos];
00742 }
00743
00744 unsigned int ConstrainedVertex::nChildren() const
00745 {
00746 return _childs.size();
00747 }
00748
00749
00750
00751 bool ConstrainedVertex::isParent( const ConstrainedVertex *cv ) const
00752 {
00753 std::cerr << "isParent() : cv is " << cv << " and this is " << this << "\n";
00754 return getGeoLink()->isParent(cv);
00755 }
00756
00757
00758
00759
00760
00767 void ConstrainedVertex::registerCell( Cell *connectedCell )
00768 {
00769 Require( !isConnected( connectedCell ) );
00770
00771
00772
00773 _connectedCells.push_back( connectedCell );
00774
00775 Ensure( isConnected( connectedCell ) );
00776
00777 }
00778
00782 void ConstrainedVertex::unregisterCell( const Cell* unconnectedCell )
00783 {
00784 Require( isConnected( unconnectedCell ) );
00785
00786 deque<Cell*>::iterator it;
00787 for( it = _connectedCells.begin() ; (it != _connectedCells.end()) && (*it != unconnectedCell) ; ++it )
00788 ;
00789
00790 Require( it != _connectedCells.end() );
00791 _connectedCells.erase( it );
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 Ensure( !isConnected( unconnectedCell ) );
00804 }
00807 unsigned short ConstrainedVertex::nConnectedCells() const
00808 {
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 return _connectedCells.size();
00820 }
00824 Cell* ConstrainedVertex::connectedCell( unsigned short id ) const
00825 {
00826 Require( id < nConnectedCells() );
00827
00828 return _connectedCells[id];
00829 }
00831 bool ConstrainedVertex::isConnected( const Cell* cell ) const
00832 {
00833 unsigned short c;
00834 for( c=0 ; c<nConnectedCells() ; ++c )
00835 if( connectedCell( c ) == cell )
00836 break;
00837 if( c == nConnectedCells() )
00838 return false;
00839 else
00840 return true;
00841 }
00842
00843
00844 Cell* ConstrainedVertex::fatherCell() const
00845 {
00846 return _fatherCell;
00847 }
00848
00849 unsigned int ConstrainedVertex::getDepth() const
00850 {
00851
00852
00853
00854
00855
00856
00857 return getMainCell()->getData()._depth;
00858 }
00859
00860
00861 void ConstrainedVertex::setData( const ConstrainedVertexData& d )
00862 {
00863 _data = d;
00864 }
00865 ConstrainedVertexData ConstrainedVertex::getData( ) const
00866 {
00867 return _data;
00868 }
00869
00870
00871 Vec3d ConstrainedVertex::getPosition() const
00872 {
00873 return get_Vec3d();
00874 }
00875
00876 GeoLink* ConstrainedVertex::getGeoLink() const
00877 {
00878 Require( _geoLink != NULL );
00879 return _geoLink;
00880 }
00881
00882
00883 ConstrainedVertex* ConstrainedVertex::getSmallestCellsFreeVertexSharingFaceForVertex( Cell *neighbour, unsigned int face, unsigned int vertex )
00884 {
00885
00886
00887 unsigned int direction;
00888 if( face <= 1 )
00889 direction = 0;
00890 else if( face >= 4 )
00891 direction = 2;
00892 else
00893 direction = 1;
00894
00895 Cell* res = neighbour;
00896
00897
00898 if( !res->vertex(vertex)->isFree() )
00899 {
00900 do
00901 {
00902 res = res->father();
00903 }
00904 while( !res->vertex(vertex)->isFree() );
00905 Ensure( res->vertex(vertex)->isFree() );
00906 return res->vertex(vertex);
00907 }
00908
00909 Cell *prec = NULL;
00910
00911 while( !res->isLeaf() && res->vertex(vertex)->isFree() )
00912 {
00913 prec = res;
00914 res = res->child(vertex);
00915 }
00916
00917 if( !res->vertex(vertex)->isFree() )
00918 {
00919 Require( prec != NULL );
00920 Ensure( prec->vertex(vertex)->isFree() );
00921 return prec->vertex(vertex);
00922 }
00923 else
00924 {
00925 Ensure( res->vertex(vertex)->isFree() );
00926 return res->vertex(vertex);
00927 }
00928 }
00929
00930
00931
00932
00933
00934
00935 Cell* ConstrainedVertex::getCellWithFreeVertexConnectedToVertex( Cell *cell, unsigned int direction, unsigned int vertexId ) const
00936 {
00937 Require( direction < 3 );
00938 Require( vertexId < 8 );
00939 Require( cell != NULL );
00940
00941 Cell* res = cell;
00942 unsigned int connectedVertexId = TempOctree::Cell::connectedVertices[vertexId][direction];
00943
00944 if( !res->vertex(connectedVertexId)->isFree() )
00945 {
00946 return res;
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 }
00958
00959 Cell *prec = NULL;
00960
00961 while( !res->isLeaf() && res->vertex(connectedVertexId)->isFree() )
00962 {
00963 prec = res;
00964 res = res->child(vertexId);
00965 }
00966
00967 if( !res->vertex(connectedVertexId)->isFree() )
00968 {
00969 Require( prec != NULL );
00970 Ensure( prec->vertex(connectedVertexId)->isFree() );
00971 return prec;
00972 }
00973 else
00974 {
00975 Ensure( res->vertex(connectedVertexId)->isFree() );
00976 return res;
00977 }
00978 }
00979
00980
00984 void ConstrainedVertex::updateFrame()
00985 {
00986 _frame = computeFrame();
00987 }
00988
00989
00990 Frame ConstrainedVertex::computeFrame()
00991 {
00992
00993
00994
00995 Require( hasMainCell() );
00996
00997 Cell *neighbours[3];
00998
00999 for( unsigned int i=0 ; i<3 ; ++i )
01000 {
01001 neighbours[i] = _mainCell->uncleSharingFace(TempOctree::verticesConnectedFaces[_vertexId][i]);
01002 }
01003
01004 Vec3d vecs[3];
01005
01006 Cell *cell = _mainCell ;
01007
01008 while( !cell->isLeaf() )
01009 {
01010 cell = cell->child( this->getMainCellVertexId() );
01011 }
01012
01013 cell = getVertexFreeCell(cell,this);
01014
01015
01016 for( unsigned short i=0 ; i<3 ; ++i )
01017 {
01018 neighbours[i] = cell->uncleSharingFace(TempOctree::verticesConnectedFaces[_vertexId][i]);
01019
01020 Cell *connectedCell = getCellWithFreeVertexConnectedToVertex( cell, i, _vertexId );
01021
01022 vecs[i] = connectedCell->vertex(Cell::connectedVertices[_vertexId][i])->getPosition() - this->getPosition();
01023
01024 _connectedVertices[i][0] = connectedCell->vertex(Cell::connectedVertices[_vertexId][i]);
01025 _connectedVertices[i][1] = NULL;
01026
01027 _connectedVerticesFactors[i][0] = 1.0;
01028 _connectedVerticesFactors[i][1] = 0.0;
01029
01030
01031
01032 if( neighbours[i] == NULL )
01033 {
01034
01035 }
01036 else
01037 {
01038 vecs[i] = Vec3d(0,0,0);
01039 unsigned int dim = 0;
01040
01041 vecs[i] += this->getPosition() - neighbours[i]->vertex(_vertexId)->getPosition();
01042 dim++;
01043
01044
01045 Cell *cFather = connectedCell;
01046
01047 while( cFather->getData()._depth > neighbours[i]->getData()._depth )
01048 {
01049 cFather = cFather->father();
01050 }
01051
01052 vecs[i] += cFather->vertex(Cell::connectedVertices[_vertexId][i])->getPosition() - this->getPosition();
01053 dim++;
01054
01055
01056 vecs[i] /= dim;
01057
01058 _connectedVertices[i][0] = cFather->vertex(Cell::connectedVertices[_vertexId][i]);
01059 _connectedVertices[i][1] = neighbours[i]->vertex(_vertexId);
01060
01061 _connectedVerticesFactors[i][0] = 0.5;
01062 _connectedVerticesFactors[i][1] = -0.5;
01063 }
01064
01065 }
01066
01067
01068 if( TempOctree::hasBrotherAlongFace[_vertexId][0] )
01069 {
01070 vecs[0] *= -1;
01071 _connectedVerticesFactors[0][0] *= -1.0;
01072 _connectedVerticesFactors[0][1] *= -1.0;
01073 }
01074 if( TempOctree::hasBrotherAlongFace[_vertexId][2] )
01075 {
01076 vecs[1] *= -1;
01077 _connectedVerticesFactors[1][0] *= -1.0;
01078 _connectedVerticesFactors[1][1] *= -1.0;
01079 }
01080 if( TempOctree::hasBrotherAlongFace[_vertexId][4] )
01081 {
01082 vecs[2] *= -1;
01083 _connectedVerticesFactors[2][0] *= -1.0;
01084 _connectedVerticesFactors[2][1] *= -1.0;
01085 }
01086
01087
01088 return Frame(this->getPosition(),vecs[0],vecs[1],vecs[2]);
01089 }
01090
01091
01092
01093
01094 unsigned int ConstrainedVertex::getConstrainedDepth() const
01095 {
01096 int maxNCells = 0;
01097
01098 Cell *neighbours[3];
01099 neighbours[0] = this->getMainCell()->getNeighbour( TempOctree::verticesConnectedFaces[_vertexId][0] );
01100 neighbours[1] = this->getMainCell()->getNeighbour( TempOctree::verticesConnectedFaces[_vertexId][1] );
01101 neighbours[2] = this->getMainCell()->getNeighbour( TempOctree::verticesConnectedFaces[_vertexId][2] );
01102
01103 if( neighbours[0] )
01104 maxNCells++;
01105 if( neighbours[1] )
01106 maxNCells++;
01107 if( neighbours[2] )
01108 maxNCells++;
01109
01110 if( maxNCells == 0 )
01111 {
01112 maxNCells = 1;
01113 }
01114 else
01115 {
01116 maxNCells = 1 << maxNCells;
01117 }
01118
01119
01120
01121
01122
01123
01124
01125 std::map< int, int> nCellsOfDepth;
01126 for( unsigned int i=0 ; i<this->nConnectedCells() ; ++i )
01127 {
01128 nCellsOfDepth[this->connectedCell(i)->getData()._depth] += 1;
01129 }
01130
01131 int deepest = -1;
01132 for( std::map< int, int>::iterator it=nCellsOfDepth.begin() ;
01133 it != nCellsOfDepth.end() ; ++it )
01134 {
01135
01136
01137
01138 if( (it->second == maxNCells) && (it->first > deepest) )
01139 {
01140
01141 deepest = it->first;
01142 }
01143 }
01144
01145 Require( deepest != -1 );
01146 if( deepest == -1 )
01147 {
01148 std::cerr << "Weup deepest !\n";
01149 }
01150
01151 return deepest;
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 Frame & ConstrainedVertex::getFrame()
01374 {
01375 return _frame;
01376 }
01377
01378 bool ConstrainedVertex::hasMainCell( ) const
01379 {
01380 return _mainCell != NULL;
01381 }
01382 void ConstrainedVertex::setMainCell( Cell* mainCell, unsigned int vId )
01383 {
01384
01385
01386
01387
01388 if( (_geoLink != NULL) && (_mainCell != NULL) && (mainCell->father() != _mainCell->father()) )
01389 {
01390
01391 _geoLink->changeCell( mainCell );
01392 }
01393
01394 _mainCell = mainCell;
01395 _vertexId = vId;
01396
01397 }
01398
01399
01400
01406 Vec3d ConstrainedVertex::getParameters( Cell *cStart, unsigned short vId )
01407 {
01408 Cell *curCell = cStart;
01409 ConstrainedVertex *curCV = curCell->vertex(vId);
01410
01411 Vec3d params;
01412 unsigned int diffDepth = 0;
01413 while( !curCV->isFree() )
01414 {
01415 if( (curCell->fatherPos()%2) != 0 )
01416 params[0] += 1.0;
01417 if( (curCell->fatherPos()%4) >= 2 )
01418 params[1] += 1.0;
01419 if( curCell->fatherPos() >= 4 )
01420 params[2] += 1.0;
01421
01422 params /= 2.0;
01423
01424 curCell = curCell->father();
01425 curCV = curCell->vertex(vId);
01426 diffDepth++;
01427 }
01428
01429 FloatingPointType pos = 1.0;
01430 if( diffDepth != 0 )
01431 {
01432 pos /= (FloatingPointType)(2<<(diffDepth-1));
01433 }
01434
01435 if( (vId%2) != 0 )
01436 params[0] += pos;
01437 if( (vId%4) >= 2 )
01438 params[1] += pos;
01439 if( vId >= 4 )
01440 params[2] += pos;
01441
01442 return params;
01443 }
01444
01450 ConstrainedVertex* ConstrainedVertex::getFathersFreeVertex( Cell *cStart, unsigned short vId )
01451 {
01452 Cell *curCell = cStart;
01453 ConstrainedVertex *curCV = curCell->vertex(vId);
01454
01455 while( !curCV->isFree() )
01456 {
01457 curCell = curCell->father();
01458 curCV = curCell->vertex(vId);
01459 }
01460
01461 Ensure( curCV->isFree() ) ;
01462
01463 return curCV;
01464 }
01465
01466 Cell* ConstrainedVertex::getFathersFreeVertexCell( Cell *cStart, unsigned short vId )
01467 {
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482 return getFathersFreeVertex( cStart, vId )->getMainCell();
01483 }
01484
01485
01486
01492 Vec3d ConstrainedVertex::getParameters( Cell *cStart, unsigned int depth, unsigned short vId )
01493 {
01494 unsigned int curDepth = depth;
01495
01496 Cell *curCell = cStart;
01497 ConstrainedVertex *curCV = curCell->vertex(vId);
01498
01499 Vec3d params;
01500 unsigned int diffDepth = 0;
01501 while( curDepth-- > 0 )
01502 {
01503 if( (curCell->fatherPos()%2) != 0 )
01504 params[0] += 1.0;
01505 if( (curCell->fatherPos()%4) >= 2 )
01506 params[1] += 1.0;
01507 if( curCell->fatherPos() >= 4 )
01508 params[2] += 1.0;
01509
01510 params /= 2.0;
01511
01512 curCell = curCell->father();
01513 curCV = curCell->vertex(vId);
01514 diffDepth++;
01515 }
01516
01517 FloatingPointType pos = 1.0;
01518 if( diffDepth != 0 )
01519 {
01520 pos /= (FloatingPointType)(2<<(diffDepth-1));
01521 }
01522
01523 if( (vId%2) != 0 )
01524 params[0] += pos;
01525 if( (vId%4) >= 2 )
01526 params[1] += pos;
01527 if( vId >= 4 )
01528 params[2] += pos;
01529
01530 return params;
01531 }
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 FloatingPointType ConstrainedVertex::getAlpha( Cell *cell, unsigned int faceId, unsigned int vId, unsigned int diffDepth )
01542 {
01543 FloatingPointType alpha = 0.0;
01544
01545 std::deque<unsigned int> alphaFactors = getAlphaFactors( cell, faceId, diffDepth );
01546 Require( !alphaFactors.empty() );
01547
01548 unsigned int denom = 2<<(alphaFactors.size()-1);
01549 unsigned int num = 0;
01550
01551
01552 for( unsigned int i=0 ; i<alphaFactors.size() ; ++i )
01553 {
01554 num += alphaFactors[i] * (denom>>(i+1));
01555 }
01556 alpha = (FloatingPointType)num / (FloatingPointType)denom;
01557
01558
01559 if( (vId%2) == 1 )
01560 {
01561 alpha += 1.0 / (FloatingPointType)denom;
01562 }
01563
01564 return alpha;
01565 }
01566
01567 FloatingPointType ConstrainedVertex::getBeta( Cell *cell, unsigned int faceId, unsigned int vId, unsigned int diffDepth )
01568 {
01569 FloatingPointType beta = 0.0;
01570
01571 std::deque<unsigned int> betaFactors = getBetaFactors( cell, faceId, diffDepth );
01572 Require( !betaFactors.empty() );
01573
01574 unsigned int denom = 2<<(betaFactors.size()-1);
01575 unsigned int num = 0;
01576
01577
01578 for( unsigned int i=0 ; i<betaFactors.size() ; ++i )
01579 {
01580 num += betaFactors[i] * (denom>>(i+1));
01581 }
01582 beta = (FloatingPointType)num / (FloatingPointType)denom;
01583
01584
01585 if( !((vId%4) <= 1) )
01586 {
01587 beta += 1.0 / (FloatingPointType)denom;
01588 }
01589
01590 return beta;
01591 }
01592
01593 FloatingPointType ConstrainedVertex::getGamma( Cell *cell, unsigned int faceId, unsigned int vId, unsigned int diffDepth )
01594 {
01595 FloatingPointType gamma = 0.0;
01596
01597 std::deque<unsigned int> gammaFactors = getGammaFactors( cell, faceId, diffDepth );
01598 Require( !gammaFactors.empty() );
01599
01600 unsigned int denom = 2<<(gammaFactors.size()-1);
01601 unsigned int num = 0;
01602
01603
01604 for( unsigned int i=0 ; i<gammaFactors.size() ; ++i )
01605 {
01606 num += gammaFactors[i] * (denom>>(i+1));
01607 }
01608 gamma = (FloatingPointType)num / (FloatingPointType)denom;
01609
01610
01611 if( vId >= 4 )
01612 {
01613 gamma += 1.0 / (FloatingPointType)denom;
01614 }
01615
01616 return gamma;
01617 }
01618
01619 std::deque<unsigned int> ConstrainedVertex::getAlphaFactors( Cell *cell, unsigned int faceId, unsigned int depthLeft )
01620 {
01621
01622 Require( !cell->isRoot() );
01623
01624 if( depthLeft == 0 )
01625 {
01626 return std::deque<unsigned int>(0);
01627 }
01628 else
01629 {
01630 std::deque<unsigned int> parents = getAlphaFactors( cell->father(), faceId, depthLeft-1 );
01631
01632 unsigned int myId = cell->fatherPos();
01633 if( (myId%2) == 0 )
01634
01635 parents.push_back(0);
01636 else
01637 parents.push_back(1);
01638
01639 return parents;
01640 }
01641 }
01642
01643 std::deque<unsigned int> ConstrainedVertex::getBetaFactors( Cell *cell, unsigned int faceId, unsigned int depthLeft )
01644 {
01645
01646 Require( !cell->isRoot() );
01647
01648 if( depthLeft == 0 )
01649 {
01650 return std::deque<unsigned int>(0);
01651 }
01652 else
01653 {
01654 std::deque<unsigned int> parents = getBetaFactors( cell->father(), faceId, depthLeft-1 );
01655
01656 unsigned int myId = cell->fatherPos();
01657 if( (myId%4) <= 1 )
01658
01659 parents.push_back(0);
01660 else
01661 parents.push_back(1);
01662
01663 return parents;
01664 }
01665 }
01666
01667 std::deque<unsigned int> ConstrainedVertex::getGammaFactors( Cell *cell, unsigned int faceId, unsigned int depthLeft )
01668 {
01669 if( depthLeft == 0 )
01670 {
01671 return std::deque<unsigned int>(0);
01672 }
01673 else
01674 {
01675 std::deque<unsigned int> parents = getGammaFactors( cell->father(), faceId, depthLeft-1 );
01676
01677 unsigned int myId = cell->fatherPos();
01678 if( myId <= 3 )
01679
01680 parents.push_back(0);
01681 else
01682 parents.push_back(1);
01683
01684 return parents;
01685 }
01686 }
01687
01688
01694 Cell* ConstrainedVertex::getMainCell() const
01695 {
01696 return _mainCell;
01697 }
01698
01699
01700
01701
01702 std::set
01703 <ConstrainedVertex*> ConstrainedVertex::getFreeParentVertices( Cell *cell )
01704 {
01705 std::list<ConstrainedVertex*> queueVertices;
01706 std::set
01707 <ConstrainedVertex*> freeVertices, seenVertices;
01708
01709 for( unsigned short vId=0 ; vId<8 ; ++vId )
01710 {
01711 queueVertices.push_back( cell->vertex(vId) );
01712
01713 }
01714
01715
01716
01717 while( !queueVertices.empty() )
01718 {
01719 ConstrainedVertex *cv = queueVertices.front();
01720 queueVertices.pop_front();
01721
01722
01723
01724 seenVertices.insert( cv );
01725
01726 if( cv->isFree() )
01727 {
01728 freeVertices.insert(cv);
01729 }
01730 else
01731 {
01732 for( unsigned short i=0 ; i<cv->getGeoLink()->getNGeoParents() ; ++i )
01733 {
01734 ConstrainedVertex *parent = cv->getGeoLink()->getGeoParent( cv->getGeoLink()->getGeoParentId(i) );
01735 if( seenVertices.find(parent) == seenVertices.end() )
01736 {
01737 queueVertices.push_back(parent);
01738 }
01739 }
01740 }
01741 }
01742
01743 return freeVertices;
01744 }
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01794 Vec3d ConstrainedVertex::computePosition() const
01795 {
01796 Require( !isFree() );
01797
01798 Vec3d res;
01799
01800 for( unsigned short i=0 ; i<getGeoLink()->getNGeoParents() ; ++i )
01801 {
01802 res += getGeoLink()->getGeoParent( getGeoLink()->getGeoParentId(i) )->getPosition();
01803 }
01804
01805 res /= getGeoLink()->getNGeoParents();
01806
01807 return res;
01808 }
01809
01810
01814 void ConstrainedVertex::setPosition( Vec3d newPos )
01815 {
01816 _position = newPos;
01817 this->getFrame().setOrigin( _position );
01818 }
01819
01824 void ConstrainedVertex::setPositionAndPropagate( Vec3d newPos )
01825 {
01826 Require( isFree() );
01827
01828
01829 this->setPosition( newPos );
01830
01831 std::list<ConstrainedVertex*> queue;
01832
01833 for( unsigned int i=0 ; i<this->nChildren() ; ++i )
01834 {
01835 if( ! this->child(i)->isFree() )
01836 {
01837 queue.push_back( this->child(i) );
01838 }
01839 }
01840
01841 for( std::list<ConstrainedVertex*>::iterator it = queue.begin() ;
01842 it != queue.end(); ++it )
01843 {
01844 Require( !(*it)->isFree() );
01845
01846 (*it)->setPosition( (*it)->computePosition() );
01847
01848 for( unsigned int i=0 ; i<(*it)->nChildren() ; ++i )
01849 {
01850 if( ! (*it)->child(i)->isFree() )
01851 {
01852 queue.push_back( (*it)->child(i) );
01853 }
01854 }
01855
01856 }
01857 }
01858
01864 void ConstrainedVertex::setPositionAndPropagateAll( Vec3d newPos, unsigned int depth )
01865 {
01866 if( isFree() )
01867 {
01868
01869 updateChildrensPositionOptimized( newPos - _position, depth );
01870 setDelta( Vec3d(0,0,0) );
01871 setDelta( getDelta() + newPos-_position );
01872 setPosition( newPos );
01873 }
01874
01875 else
01876 {
01877 updateChildrensPositionOptimizedNotFree( newPos - _position );
01878 }
01879 }
01880
01881
01882
01883
01886 Vec3d ConstrainedVertex::getDelta() const
01887 {
01888 return _delta;
01889 }
01890 void ConstrainedVertex::setDelta( Vec3d d )
01891 {
01892 _delta = d;
01893 }
01894 Vec3d ConstrainedVertex::computeDelta() const
01895 {
01896 Require( !isFree() );
01897
01898 Vec3d res;
01899 unsigned short nParents = getGeoLink()->getNGeoParents();
01900
01901 for( unsigned short i=0 ; i<nParents ; ++i )
01902 {
01903 res += getGeoLink()->getGeoParent( getGeoLink()->getGeoParentId(i) )->getDelta();
01904 }
01905
01906 res /= nParents;
01907
01908 return res;
01909 }
01910
01911
01912
01913
01914
01915 Vec3d ConstrainedVertex::computeValue(int value_id ) const
01916 {
01917 Require( !isFree() );
01918
01919 Vec3d res;
01920
01921 for( unsigned short i=0 ; i<getGeoLink()->getNGeoParents() ; ++i )
01922 {
01923 res += getGeoLink()->getGeoParent( getGeoLink()->getGeoParentId(i) )->value( value_id );
01924 }
01925
01926 res /= getGeoLink()->getNGeoParents();
01927
01928 return res;
01929 }
01930
01931 void ConstrainedVertex::computeValueFromParents(int value_id )
01932 {
01933 Require( !isFree() );
01934
01935 Vec3d res;
01936
01937 for( unsigned short i=0 ; i<getGeoLink()->getNGeoParents() ; ++i )
01938 {
01939 res += getGeoLink()->getGeoParent( getGeoLink()->getGeoParentId(i) )->value( value_id );
01940 }
01941
01942 res /= getGeoLink()->getNGeoParents();
01943
01944 setValue(value_id, res);
01945 }
01946
01947 void ConstrainedVertex::computeValueFromRelatives(int value_id )
01948 {
01949 Require( isFree() );
01950
01951 Vec3d res;
01952
01953 for( unsigned short i=0 ; i<getGeoLink()->getNGeoParents() ; ++i )
01954 {
01955 res += getGeoLink()->getGeoParent( getGeoLink()->getGeoParentId(i) )->value( value_id );
01956 }
01957
01958 res /= getGeoLink()->getNGeoParents();
01959
01960 setValue(value_id, res);
01961 }
01962
01963 void ConstrainedVertex::setValue( int value_id, Vec3d newPos )
01964 {
01965 _aux[value_id] = newPos;
01966 }
01967
01968 Vec3d& ConstrainedVertex::value( int value_id )
01969 {
01970 return _aux[value_id];
01971 }
01972
01973 const Vec3d& ConstrainedVertex::value( int value_id ) const
01974 {
01975 return _aux[value_id];
01976 }
01977
01978 void ConstrainedVertex::setValueAndPropagate( int value_id, Vec3d newPos )
01979 {
01980 Require( isFree() );
01981
01982 this->_aux[value_id] = newPos;
01983
01984 std::list<ConstrainedVertex*> queue;
01985
01986 for( unsigned int i=0 ; i<this->nChildren() ; ++i )
01987 {
01988 if( ! this->child(i)->isFree() )
01989 {
01990 queue.push_back( this->child(i) );
01991 }
01992 }
01993
01994 for( std::list<ConstrainedVertex*>::iterator it = queue.begin() ;
01995 it != queue.end(); ++it )
01996 {
01997 Require( !(*it)->isFree() );
01998
01999 (*it)->setValue( value_id, (*it)->computeValue(value_id) );
02000
02001 for( unsigned int i=0 ; i<(*it)->nChildren() ; ++i )
02002 {
02003 if( ! (*it)->child(i)->isFree() )
02004 {
02005 queue.push_back( (*it)->child(i) );
02006 }
02007 }
02008
02009 }
02010 }
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023 Cell::vertex_connected_iterator::vertex_connected_iterator( ConstrainedVertex* vertex, Cell *cell, unsigned int vPos )
02024 {
02025
02026
02027 for( unsigned short dir=0 ; dir<3 ; ++dir )
02028 {
02029 _vList.push_back( cell->vertex(connectedVertices[vPos][dir]) );
02030
02031 Cell *neighbour = cell->uncleSharingFace(TempOctree::verticesConnectedFaces[vPos][dir]);
02032 if( (neighbour != NULL) && vertex->isConnected(neighbour) )
02033 {
02034 Cell *otherCell = vertex->getCellWithFreeVertexConnectedToVertex( neighbour, dir, vPos );
02035
02036 _vList.push_back( otherCell->vertex(vPos) );
02037 }
02038 }
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064 }
02065
02066 Cell::vertex_connected_iterator::~vertex_connected_iterator()
02067 {}
02068
02069 TempOctree::Vertex* Cell::vertex_connected_iterator::operator++()
02070 {
02071 Require( !empty() );
02072
02073
02074
02075
02076
02077 Vertex* res = _vList.front();
02078 _vList.pop_front();
02079
02080 return res;
02081 }
02082 bool Cell::vertex_connected_iterator::empty()
02083 {
02084 return _vList.empty();
02085
02086 }
02087
02088
02089 }
02090 }
02091
02092
02093