HyperSurface.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by Universidad Nacional de Colombia                *
00003  *   http://www.unal.edu.co                                                *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "HyperSurface.h"
00021 
00022 #include <iomanip>
00023 using namespace std ;
00024 
00025 #include <GTL/components.h>
00026 #include <TarisApplication.h>
00027 
00028 HyperSurface::HyperSurface( string name )
00029 {
00030         this->name = name ;
00031 }
00032 
00033 HyperSurface::~HyperSurface()
00034 {
00035         delete mole ;
00036 }
00037 
00042 void HyperSurface::load( const string& filename )
00043 {
00044         mole = new Mol( filename.c_str() ) ;
00045         
00046         if( TarisApplication::Instance()->getDebugLevel() >= 1 )
00047                 cerr << "Cargando archivo " << filename << " ... " ;
00048         
00049         read_gcube( mole, filename.c_str() ) ;
00050         
00051         if( TarisApplication::Instance()->getDebugLevel() >= 1 )
00052                 cerr << "OK" << endl ;
00053 }
00054 
00055 Surface HyperSurface::getIsosurface( double cutoff, bool debug )
00056 {
00057         Surface ouput ;
00058         
00059         if( TarisApplication::Instance()->getDebugLevel() >= 2 ){
00060                 cerr << endl ;
00061                 cerr << "**************************************************************" << endl ;
00062                 cerr << endl ;
00063                 cerr << "                ALGORITMO DE TRIANGULARIZACION                " << endl ;
00064                 cerr << "                ------------------------------                " << endl ;
00065                 cerr << endl ;
00066         }
00067         
00068         list<Surfdot> dotList ;
00069         list<Tria> triList ;
00070         
00071         mole->cutoff = cutoff ;
00072         
00073         if( TarisApplication::Instance()->getDebugLevel() >= 2 )
00074                 cerr << "Triangularizando superficie ... " ;
00075         
00076         /* ***************************************************************
00077         * Esta es la funci贸n de molekel que genera la lista de triangulos
00078         * y de pubntos
00079         */
00080         
00081         cubes( mole, dotList, triList ) ;
00082                 
00083         if( TarisApplication::Instance()->getDebugLevel() >= 2 )
00084                 cerr << "OK" << endl ;
00085         
00086         TriangleVector ltri ;
00087         PointVector lpo ;
00088         
00089         if( TarisApplication::Instance()->getDebugLevel() >= 2 ){
00090                 cerr << "Reconstruyendo puntos ... " ;
00091         }
00092         
00093         int i=0 ;
00094         for( list<Surfdot>::iterator it = dotList.begin(); it != dotList.end(); it++, i++ ){
00095                 lpo.push_back( Point( i, (*it).v[0], (*it).v[1], (*it).v[2] ) ) ;
00096         }
00097         
00098         if( TarisApplication::Instance()->getDebugLevel() >= 2 ){
00099                 cerr << "OK" << endl ;
00100                         
00101                 cerr << "Reconstruyendo triangulos ... " ;
00102         }
00103         
00104         i=0 ;
00105         for( list<Tria>::iterator it = triList.begin(); it != triList.end(); it++, i++ )
00106                 ltri.push_back( Triangle( i, lpo[it->p1], lpo[it->p2], lpo[it->p3] ) ) ;
00107         
00108         if( TarisApplication::Instance()->getDebugLevel() >= 2 ){
00109                 cerr << "OK" << endl ;
00110                 cerr << endl ;
00111                 cerr << "**************************************************************" << endl ;
00112                 cerr << endl ;
00113         }
00114         
00115         /******************************************
00116         * Se le asignan a la superficie la lista
00117         * de puntos, de triangulos
00118         */
00119         ouput.setPoints( lpo ) ;
00120         ouput.setTriangles( ltri ) ;
00121         
00122         return ouput ;
00123 }
00124 
00125 
00126 Tree HyperSurface::buildAreaTree( double cutoffBegin, double cutoffEnd, double stepSize )
00127 {
00128         if( cutoffBegin < 0.0 ){
00129                 
00130                 Tree tree ;
00131                 
00132                 Surface s ;  // Esta es una superficie temporal
00133                 
00134                 /***********************************************
00135                 * En el trancurso de construcci贸n del arbol
00136                 * se debe tener el conjunto de componentes
00137                 * a un valor de potencial x y almismo tiempo
00138                 * al un valor de potencial x + stepSize,
00139                 * para en un siguiente procedimiento verificar
00140                 * la contenencia de unas con respecto a otras
00141                 * y de esta manera crear las aristas. De igual
00142                 * manera los nodos que representan
00143                 */
00144                 SurfacesVector currentSurfaces ;
00145                 SurfacesVector nextSurfaces ;
00146                 
00147                 map<int, node> currentNodeMap ;
00148                 map<int, node> nextNodeMap ;
00149                 //**********************************************
00150                 
00151                 //-----------13------------------24----------------
00152                 cout << " +-------------+------------------------+" << endl ;
00153                 cout << " |  Potential  |  Number of Components  |" << endl ;
00154                 cout << " +-------------+------------------------+" << endl ;
00155                 
00156                 /**************************************************************
00157                 * Se inicializa la primera fila de nodos, partiendo de las
00158                 * componentes calculadas al valor de potencial cuttoffBegin
00159                 */
00160                 s = this->getIsosurface( cutoffBegin ) ;
00161                 currentSurfaces = s.computeComponents() ;
00162                         
00163                 
00164                 int i = 0 ;
00165                 for( SurfacesVector::iterator it1 = currentSurfaces.begin(); it1 != currentSurfaces.end(); it1++, i++ ){
00166                                                 
00167                         /*****************************************************
00168                         * El weightValue ahora depende tanto del potencial como
00169                         * del area superficial de las componentes
00170                         */
00171                         node n = tree.newNode( NodeWeight( cutoffBegin, it1->computeArea() ) ) ;
00172                         currentNodeMap[ i ] = n ;
00173                         
00174                 }
00175                 
00176                 cout.precision(5) ;
00177                 cout.setf( ios::fixed ) ;
00178                 if(currentSurfaces.size() != 0){
00179                         cout << " | " << setw(11) << cutoffBegin << " | " << setw(22)<< currentSurfaces.size() << " |" << endl ;
00180                 }else{
00181                         cout << " | " << setw(11) << cutoffBegin << " | " << setw(22)<< currentSurfaces.size() << " |" << endl ;
00182                 }
00183                 
00184                 
00185                 
00186                 for( double potential = cutoffBegin + stepSize; potential < cutoffEnd + 0.0005 ; potential += stepSize ){
00187                         
00188                         s = this->getIsosurface( potential ) ;
00189                         nextSurfaces = s.computeComponents() ;
00190                         
00191                         nextNodeMap.clear() ;
00192                         
00193                         i = 0 ;
00194                         for( SurfacesVector::iterator it2 = nextSurfaces.begin(); it2 != nextSurfaces.end(); it2++, i++ ){
00195                                 
00196                                 /*****************************************************
00197                                 * El weightValue ahora depende tanto del potencial como
00198                                 * del area superficial de las componentes
00199                                 */
00200                                 node n = tree.newNode( NodeWeight( potential, it2->computeArea() ) ) ;
00201                                 nextNodeMap[ i ] = n ;
00202                         }
00203                         
00204                         cout << " | " << setw(11) << potential << " | " << setw(22)<< nextSurfaces.size() << " |" << endl ;
00205                                 
00206                         
00207                         // Aca se inicializan los parametros a y b que se le introducen a la funcion isContainedIn
00208                         int a = 0, b = 0 ;
00209                         
00210                         i = 0 ;
00211                         
00212                         // Este primer ciclo while se asegura de que ningun nodo quede sin papa
00213                         SurfacesVector::iterator it1 = currentSurfaces.begin();
00214                         while( it1 != currentSurfaces.end() ){
00215                                 
00216                                 
00217                                 // Este segundo siclo while se asegura de que ningun nodo quede con mas de dos papas
00218                                 int j = 0 ;
00219                                 SurfacesVector::iterator it2 = nextSurfaces.begin();
00220                                 while(  it2 != nextSurfaces.end() && currentNodeMap[i].outdeg() < 1){
00221                                         
00222                                         if( (it1->isContainedIn( *it2, a , b ) ) ){
00223                                                 
00224                                                 tree.new_edge( currentNodeMap[i], nextNodeMap[j] ) ;
00225                                         }
00226                                         
00227                                         it2++ ;
00228                                         j++ ;
00229                                         
00230                                 }
00231                                 
00232                                 if(currentNodeMap[i].outdeg() == 0){
00233                                         a++ ;
00234                                         b++ ;
00235                                 }else{
00236                                         it1++ ;
00237                                         i++ ;
00238                                 }
00239                                 
00240                         }
00241                         
00242                         currentSurfaces = nextSurfaces ;
00243                         currentNodeMap = nextNodeMap ;
00244                         
00245                 }
00246                 
00247                 /**************************************************************
00248                 * Se crea el nodo raiz
00249                 */
00250                 
00251                 node n = tree.newNode( NodeWeight(0.0, true) ) ;
00252                 
00253                 i = 0 ;
00254                 for( SurfacesVector::iterator it2 = currentSurfaces.begin(); it2 != currentSurfaces.end(); it2++, i++ ){
00255                         
00256                         tree.new_edge( currentNodeMap[i], n ) ;
00257                         
00258                 }
00259                 //**************************************************************
00260                 
00261                 cout << " +-------------+------------------------+" << endl ;
00262                 cout << endl ;
00263                 
00264                 
00265                 /****************************************************************
00266                 * Se define el atributo deepestNoNodes para todos los nodos
00267                 */
00268                 
00269                 node child ;
00270                 node parent ;
00271         
00272                 for( Tree::node_iterator it = tree.nodes_begin(); it != tree.nodes_end(); it++ ){
00273 
00274                         if( it->indeg() == 0 ){
00275 
00276                                 parent = *it ;
00277                          
00278                                 int i = 0 ;
00279                         
00280                                 while( (tree.inf( parent ).isRoot() == false )  && ( tree.inf( parent ).getDeepestNoNodes() < i ) ){
00281                                         tree.inf( parent ).setDeepestNoNodes( i ) ;
00282                                         parent = parent.out_edges_begin()->opposite( parent ) ;
00283                                         i++ ;
00284                                         if( (tree.inf( parent ).isRoot() == true )  && ( tree.inf( parent ).getDeepestNoNodes() < i ) ){
00285                                                 tree.inf( parent ).setDeepestNoNodes( i ) ;     
00286                                         }
00287                                 
00288                                 }
00289 
00290                                 
00291                                                         
00292                         }
00293 
00294                 }
00295 
00296                 
00297                 
00298                 /***************************************************************
00299                 * Ahora hay que crear el arbol, pero quitando redundacias, es
00300                 * decir nodos con un solo hijo, excepto el nodo raiz y sus hijos
00301                 */
00302                 
00303                         
00304                 vector<node> nodesToErase ;
00305                 vector<node> nodesTMP ;
00306                         
00307                 for( Tree::node_iterator it = tree.nodes_begin(); it != tree.nodes_end(); it++ ){
00308                         if( ( it->indeg() != 1 ) && ( !tree.inf(*it).isRoot() ) ){
00309                                 nodesTMP.push_back( *it ) ;
00310                         }
00311                 }
00312                         
00313                 for( vector<node>::iterator it = nodesTMP.begin(); it != nodesTMP.end(); it++ ){
00314                                 
00315                         child = *it ;
00316                         parent = *it ;
00317                                 
00318                         /****************************************************
00319                         * Esta parte se asegura de que no se borren los nodos
00320                         * hijos del raiz, es decir lo que se consideraria como las
00321                         * raices de las distintas ramas que conformar铆an el arbol. Esto
00322                         * se hace para restar peso a los componentes que aparecen en
00323                         * potenciales altos, que son peque帽os y que no se unen a nada
00324                         */
00325                         while( (parent.out_edges_begin()->opposite( parent ).indeg() == 1 ) && 
00326                                                      ( !tree.inf(parent.out_edges_begin()->opposite( parent ).out_edges_begin()->
00327                                                      opposite( parent.out_edges_begin()->opposite( parent ) ) ).isRoot() )){
00328                                 
00329                                 
00330                                 parent = parent.out_edges_begin()->opposite( parent ) ;
00331                                 nodesToErase.push_back( parent ) ;
00332                         }
00333                                 
00334                         if( child != parent ){
00335                                 tree.new_edge( child, parent.out_edges_begin()->opposite( parent ) ) ;
00336                                 tree.inf(child).setDeepestNoNodes(tree.inf(parent).getDeepestNoNodes()) ;
00337                         }
00338                 }
00339                         
00340                 /*
00341                 * Finalmente eliminamos los nodos que se han rotulado como para ser borrados
00342                 * que fueron almacenados en la lista
00343                 */
00344                 for( vector<node>::iterator it = nodesToErase.begin(); it != nodesToErase.end(); it++ )
00345                         tree.removeNode( *it ) ;
00346                         
00347                 
00348                 // Por omisi贸n el arbol es numerado en postOrder
00349                 tree.postOrderRay() ;
00350                 
00351                 return tree ;
00352                 
00353         }else{
00354                 
00355                 Tree tree ;
00356                 
00357                 Surface s ;  // Esta es una superficie temporal
00358                 
00359                 /***********************************************
00360                 * En el trancurso de construcci贸n del arbol
00361                 * se debe tener el conjunto de componentes
00362                 * a un valor de potencial x y almismo tiempo
00363                 * al un valor de potencial x + stepSize,
00364                 * para en un siguiente procedimiento verificar
00365                 * la contenencia de unas con respecto a otras
00366                 * y de esta manera crear las aristas. De igual
00367                 * manera los nodos que representan
00368                 */
00369                 SurfacesVector currentSurfaces ;
00370                 SurfacesVector nextSurfaces ;
00371                 
00372                 map<int, node> currentNodeMap ;
00373                 map<int, node> nextNodeMap ;
00374                 //**********************************************
00375                 
00376                 cout << " -------------------------------------------" << endl ;
00377                 cout << "      Potential  |  Number of Components    " << endl ;
00378                 cout << " -------------------------------------------" << endl ;
00379                 
00380                 /**************************************************************
00381                 * Se inicializa la primera fila de nodos, partiendo de las
00382                 * componentes calculadas al valor de potencial cuttoffBegin
00383                 */
00384                 s = this->getIsosurface( cutoffBegin ) ;
00385                 currentSurfaces = s.computeComponents() ;
00386                         
00387                 
00388                 int i = 0 ;
00389                 for( SurfacesVector::iterator it1 = currentSurfaces.begin(); it1 != currentSurfaces.end(); it1++, i++ ){
00390                         
00391                         /*****************************************************
00392                         * El weightValue ahora depende tanto del potencial como
00393                         * del area superficial de las componentes
00394                         */
00395                         node n = tree.newNode( NodeWeight( cutoffBegin, it1->computeArea() ) ) ;
00396                         currentNodeMap[ i ] = n ;
00397                         
00398                 }
00399                 
00400                 if(currentSurfaces.size() != 0){
00401                         cout << "\t" << cutoffBegin << "\t\t" << currentSurfaces.size() << endl ;
00402                 }else{
00403                         cout << "\t" << cutoffBegin << "\t\t" << currentSurfaces.size() << endl ;
00404                 }
00405                 
00406                 
00407                 
00408                 for( double potential = cutoffBegin - stepSize; potential > cutoffEnd - 0.0005 ; potential -= stepSize ){
00409                         
00410                         s = this->getIsosurface( potential ) ;
00411                         nextSurfaces = s.computeComponents() ;
00412                         
00413                         nextNodeMap.clear() ;
00414                         
00415                         i = 0 ;
00416                         for( SurfacesVector::iterator it2 = nextSurfaces.begin(); it2 != nextSurfaces.end(); it2++, i++ ){
00417                                 
00418                                 /*****************************************************
00419                                 * El weightValue ahora depende tanto del potencial como
00420                                 * del area superficial de las componentes
00421                                 */
00422                                 node n = tree.newNode( NodeWeight( potential, it2->computeArea() ) ) ;
00423                                 nextNodeMap[ i ] = n ;
00424                         }
00425                         
00426                         
00427                         cout << "\t" << potential << "\t\t" << nextSurfaces.size() << endl ;//********************************
00428                                 
00429                         
00430                         // Aca se inicializan los parametros a y b que se le introducen a la funcion isContainedIn
00431                         int a = 0, b = 0 ;
00432                         
00433                         i = 0 ;
00434                         
00435                         // Este primer ciclo while se asegura de que ningun nodo quede sin papa
00436                         SurfacesVector::iterator it1 = currentSurfaces.begin();
00437                         while( it1 != currentSurfaces.end() ){
00438                                 
00439                                 
00440                                 // Este segundo siclo while se asegura de que ningun nodo quede con mas de dos papas
00441                                 int j = 0 ;
00442                                 SurfacesVector::iterator it2 = nextSurfaces.begin();
00443                                 while(  it2 != nextSurfaces.end() && currentNodeMap[i].outdeg() < 1){
00444                                         
00445                                         if( (it1->isContainedIn( *it2, a , b ) ) ){
00446                                                 
00447                                                 tree.new_edge( currentNodeMap[i], nextNodeMap[j] ) ;
00448                                         }
00449                                         
00450                                         it2++ ;
00451                                         j++ ;
00452                                         
00453                                 }
00454                                 
00455                                 if(currentNodeMap[i].outdeg() == 0){
00456                                         a++ ;
00457                                         b++ ;
00458                                 }else{
00459                                         it1++ ;
00460                                         i++ ;
00461                                 }
00462                                 
00463                         }
00464                         
00465                         currentSurfaces = nextSurfaces ;
00466                         currentNodeMap = nextNodeMap ;
00467                         
00468                 }
00469                 
00470                 /**************************************************************
00471                 * Se crea el nodo raiz
00472                 */
00473                 
00474                 node n = tree.newNode( NodeWeight(0.0, true) ) ;
00475                 
00476                 i = 0 ;
00477                 for( SurfacesVector::iterator it2 = currentSurfaces.begin(); it2 != currentSurfaces.end(); it2++, i++ ){
00478                         
00479                         tree.new_edge( currentNodeMap[i], n ) ;
00480                         
00481                 }
00482                 //**************************************************************
00483                 
00484                 cout << " ----------------------------------------" << endl ;
00485                 cout << endl ;
00486                 
00487                 
00488                 /****************************************************************
00489                 * Se define el atributo deepestNoNodes para todos los nodos
00490                 */
00491                 
00492                 node child ;
00493                 node parent ;
00494         
00495                 for( Tree::node_iterator it = tree.nodes_begin(); it != tree.nodes_end(); it++ ){
00496 
00497                         if( it->indeg() == 0 ){
00498 
00499                                 parent = *it ;
00500                          
00501                                 int i = 0 ;
00502                         
00503                                 while( (tree.inf( parent ).isRoot() == false )  && ( tree.inf( parent ).getDeepestNoNodes() < i ) ){
00504                                         tree.inf( parent ).setDeepestNoNodes( i ) ;
00505                                         parent = parent.out_edges_begin()->opposite( parent ) ;
00506                                         i++ ;
00507                                         if( (tree.inf( parent ).isRoot() == true )  && ( tree.inf( parent ).getDeepestNoNodes() < i ) ){
00508                                                 tree.inf( parent ).setDeepestNoNodes( i ) ;     
00509                                         }
00510                                 
00511                                 }
00512 
00513                                 
00514                                                         
00515                         }
00516 
00517                 }
00518 
00519                 
00520                 
00521                 /***************************************************************
00522                 * Ahora hay que crear el arbol, pero quitando redundacias, es
00523                 * decir nodos con un solo hijo, excepto el nodo raiz y sus hijos
00524                 */
00525                 
00526                         
00527                 vector<node> nodesToErase ;
00528                 vector<node> nodesTMP ;
00529                         
00530                 for( Tree::node_iterator it = tree.nodes_begin(); it != tree.nodes_end(); it++ ){
00531                         if( ( it->indeg() != 1 ) && ( !tree.inf(*it).isRoot() ) ){
00532                                 nodesTMP.push_back( *it ) ;
00533                         }
00534                 }
00535                         
00536                 for( vector<node>::iterator it = nodesTMP.begin(); it != nodesTMP.end(); it++ ){
00537                                 
00538                         child = *it ;
00539                         parent = *it ;
00540                                 
00541                         /****************************************************
00542                         * Esta parte se asegura de que no se borren los nodos
00543                         * hijos del raiz, es decir lo que se consideraria como las
00544                         * raices de las distintas ramas que conformar铆an el arbol. Esto
00545                         * se hace para restar peso a los componentes que aparecen en
00546                         * potenciales altos, que son peque帽os y que no se unen a nada
00547                         */
00548                         while( (parent.out_edges_begin()->opposite( parent ).indeg() == 1 ) && 
00549                                                      ( !tree.inf(parent.out_edges_begin()->opposite( parent ).out_edges_begin()->
00550                                                      opposite( parent.out_edges_begin()->opposite( parent ) ) ).isRoot() )){
00551                                 
00552                                 
00553                                 parent = parent.out_edges_begin()->opposite( parent ) ;
00554                                 nodesToErase.push_back( parent ) ;
00555                                                      }
00556                                 
00557                                                      if( child != parent ){
00558                                                              tree.new_edge( child, parent.out_edges_begin()->opposite( parent ) ) ;
00559                                                              tree.inf(child).setDeepestNoNodes(tree.inf(parent).getDeepestNoNodes()) ;
00560                                                      }
00561                 }
00562                         
00563                 /*
00564                 * Finalmente eliminamos los nodos que se han rotulado como para ser borrados
00565                 * que fueron almacenados en la lista
00566                 */
00567                 for( vector<node>::iterator it = nodesToErase.begin(); it != nodesToErase.end(); it++ )
00568                         tree.removeNode( *it ) ;
00569                         
00570                 
00571                 // Por omisi贸n el arbol es numerado en postOrder
00572                 tree.postOrderRay() ;
00573                 
00574                 return tree ;
00575         }
00576 }

Generated on Mon May 26 20:29:46 2008 for TARIS by  doxygen 1.5.4