MOAB: Mesh Oriented datABase  (version 5.4.1)
untangle.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2010 Sandia National Laboratories.  Developed at the
00005     University of Wisconsin--Madison under SNL contract number
00006     624796.  The U.S. Government and the University of Wisconsin
00007     retain certain rights to this software.
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2.1 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     (2010) [email protected]
00024 
00025   ***************************************************************** */
00026 
00027 /** \file untangle.cpp
00028  *  \brief tast untangle wrapper
00029  *  \author Jason Kraftcheck
00030  */
00031 #include "TestUtil.hpp"
00032 
00033 #include "MeshImpl.hpp"
00034 #include "MsqError.hpp"
00035 #include "MsqVertex.hpp"
00036 #include "PlanarDomain.hpp"
00037 #include "UntangleWrapper.hpp"
00038 #include "QualityAssessor.hpp"
00039 
00040 #include <iostream>
00041 using std::cout;
00042 using std::endl;
00043 #include <cstdlib>
00044 
00045 using namespace MBMesquite;
00046 
00047 std::string VTK_2D_DIR = TestDir + "unittest/mesquite/2D/vtk/";
00048 
00049 // Test untangle wrapper
00050 // Assumes all meshes lie in a plane for which the normal is [0,0,1].
00051 int uwt( bool skip,
00052          UntangleWrapper::UntangleMetric metric,
00053          const char* input_file,
00054          int expected_number_of_remaining_inverted_elems,
00055          bool flip_domain = false );
00056 
00057 bool brief_output = false;
00058 bool write_output = false;
00059 double mu_sigma   = -1;
00060 double beta       = -1;
00061 
00062 void usage( const char* argv0 )
00063 {
00064     std::cerr << "Usage: " << argv0 << " [-<flags>] [-c <sigma>] [-b <beta>]" << std::endl
00065               << "       " << argv0 << " -h" << std::endl;
00066 }
00067 void help( const char* argv0 )
00068 {
00069     std::cout << "Usage: " << argv0 << " [-<flags>] [-c <sigma>] [-b <beta>]" << std::endl
00070               << "Flags: -q : brief output" << std::endl
00071               << "       -w : write result meshes" << std::endl
00072               << "       -B : skip tests using untangle beta target metric" << std::endl
00073               << "       -Z : skip tests using size untangle target metric" << std::endl
00074               << "       -P : skip tests using shapesize untangle target metric" << std::endl
00075               << "       -H : skip tests using 'tangled_horse1.vtk' as input" << std::endl
00076               << "       -Q : skip tests using 'hole_in_square_tanglap.vtk' as input" << std::endl
00077               << "       -I : skip tests using 'inverted-hole-2.vtk' as input" << std::endl
00078               << "       -S : skip tests using 'shest_grid32.vtk' as input" << std::endl
00079               << "       -c : specify sigma value for untangle metrics" << std::endl
00080               << "       -b : specify beta value for untangle beta metric" << std::endl
00081               << std::endl;
00082 }
00083 
00084 int main( int argc, char* argv[] )
00085 {
00086     bool skip_beta  = false;
00087     bool skip_size  = false;
00088     bool skip_shape = false;
00089     bool skip_horse = false;
00090     bool skip_hole  = false;
00091     bool skip_invrt = false;
00092     bool skip_shest = false;
00093     std::list< double* > expected;
00094 
00095     for( int i = 1; i < argc; ++i )
00096     {
00097         if( !expected.empty() )
00098         {
00099             char* endptr;
00100             *expected.front() = strtod( argv[i], &endptr );
00101             if( *endptr || *expected.front() <= 0 )
00102             {
00103                 std::cerr << "Expected positive number, found \"" << argv[i] << '"' << std::endl;
00104                 usage( argv[0] );
00105                 return 1;
00106             }
00107             expected.pop_front();
00108         }
00109         else if( argv[i][0] == '-' && argv[i][1] )
00110         {
00111             for( int j = 1; argv[i][j]; ++j )
00112             {
00113                 switch( argv[i][j] )
00114                 {
00115                     case 'q':
00116                         brief_output = true;
00117                         break;
00118                     case 'w':
00119                         write_output = true;
00120                         break;
00121                     case 'B':
00122                         skip_beta = true;
00123                         break;
00124                     case 'Z':
00125                         skip_size = true;
00126                         break;
00127                     case 'P':
00128                         skip_shape = true;
00129                         break;
00130                     case 'H':
00131                         skip_horse = true;
00132                         break;
00133                     case 'Q':
00134                         skip_hole = true;
00135                         break;
00136                     case 'I':
00137                         skip_invrt = true;
00138                         break;
00139                     case 'S':
00140                         skip_shest = true;
00141                         break;
00142                     case 'c':
00143                         expected.push_back( &mu_sigma );
00144                         break;
00145                     case 'b':
00146                         expected.push_back( &beta );
00147                         break;
00148                     case 'h':
00149                         help( argv[0] );
00150                         return 0;
00151                     default:
00152                         std::cerr << "Invalid flag: -" << argv[i][j] << std::endl;
00153                         usage( argv[0] );
00154                         return 1;
00155                 }
00156             }
00157         }
00158         else
00159         {
00160             std::cerr << "Unexpected argument: \"" << argv[i] << '"' << std::endl;
00161             usage( argv[0] );
00162             return 1;
00163         }
00164     }
00165 
00166     int result = 0;
00167 
00168     result += uwt( skip_beta || skip_horse, UntangleWrapper::BETA, "quads/tangled/tangled_horse1.vtk", 0 );
00169     result += uwt( skip_beta || skip_hole, UntangleWrapper::BETA, "quads/tangled/hole_in_square_tanglap.vtk", 0, true );
00170     result += uwt( skip_beta || skip_invrt, UntangleWrapper::BETA, "quads/tangled/inverted-hole-2.vtk", 0 );
00171     result += uwt( skip_beta || skip_shest, UntangleWrapper::BETA, "quads/untangled/shest_grid32.vtk", 0 );
00172 
00173     result += uwt( skip_size || skip_horse, UntangleWrapper::SIZE, "quads/tangled/tangled_horse1.vtk", 0 );
00174     result += uwt( skip_size || skip_hole, UntangleWrapper::SIZE, "quads/tangled/hole_in_square_tanglap.vtk", 6, true );
00175     result += uwt( skip_size || skip_invrt, UntangleWrapper::SIZE, "quads/tangled/inverted-hole-2.vtk", 0 );
00176     result += uwt( skip_size || skip_shest, UntangleWrapper::SIZE, "quads/untangled/shest_grid32.vtk", 0 );
00177 
00178     result += uwt( skip_shape || skip_horse, UntangleWrapper::SHAPESIZE, "quads/tangled/tangled_horse1.vtk", 0 );
00179     result +=
00180         uwt( skip_shape || skip_hole, UntangleWrapper::SHAPESIZE, "quads/tangled/hole_in_square_tanglap.vtk", 0, true );
00181     result += uwt( skip_shape || skip_invrt, UntangleWrapper::SHAPESIZE, "quads/tangled/inverted-hole-2.vtk", 8 );
00182     result += uwt( skip_shape || skip_shest, UntangleWrapper::SHAPESIZE, "quads/untangled/shest_grid32.vtk", 0 );
00183 
00184     return result;
00185 }
00186 
00187 const char* tostr( UntangleWrapper::UntangleMetric m )
00188 {
00189     static const char BETA[]      = "BETA";
00190     static const char SIZE[]      = "SIZE";
00191     static const char SHAPESIZE[] = "SHAPESIZE";
00192     switch( m )
00193     {
00194         case UntangleWrapper::BETA:
00195             return BETA;
00196         case UntangleWrapper::SIZE:
00197             return SIZE;
00198         case UntangleWrapper::SHAPESIZE:
00199             return SHAPESIZE;
00200     }
00201     return 0;
00202 }
00203 
00204 int uwt( bool skip,
00205          UntangleWrapper::UntangleMetric metric,
00206          const char* input_file_base,
00207          int expected,
00208          bool flip_domain )
00209 {
00210     if( skip ) return 0;
00211 
00212     if( !brief_output ) std::cout << std::endl << "**********************************************" << std::endl;
00213     std::cout << "Running \"" << input_file_base << "\" for " << tostr( metric ) << std::endl;
00214     if( !brief_output ) std::cout << "**********************************************" << std::endl << std::endl;
00215 
00216     // get mesh
00217     MsqError err;
00218     MeshImpl mesh;
00219     std::string input_file( VTK_2D_DIR );
00220     input_file += input_file_base;
00221     mesh.read_vtk( input_file.c_str(), err );
00222     if( err )
00223     {
00224         std::cerr << err << std::endl;
00225         std::cerr << "ERROR: " << input_file << " : failed to read file" << std::endl;
00226         return 1;
00227     }
00228     // get domain
00229     std::vector< Mesh::VertexHandle > verts;
00230     mesh.get_all_vertices( verts, err );
00231     if( err || verts.empty() ) abort();
00232     MsqVertex coords;
00233     mesh.vertices_get_coordinates( arrptr( verts ), &coords, 1, err );
00234     if( err ) abort();
00235     Vector3D norm( 0, 0, flip_domain ? -1 : 1 );
00236     PlanarDomain domain( norm, coords );
00237     // run wrapper
00238     UntangleWrapper wrapper( metric );
00239     wrapper.set_vertex_movement_limit_factor( 0.005 );
00240     double constant = ( metric == UntangleWrapper::BETA ) ? beta : mu_sigma;
00241     if( constant > 0 ) wrapper.set_metric_constant( constant );
00242     if( brief_output ) wrapper.quality_assessor().disable_printing_results();
00243     MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &mesh, &domain );
00244     wrapper.run_instructions( &mesh_and_domain, err );
00245     if( err )
00246     {
00247         std::cerr << err << std::endl;
00248         std::cerr << "ERROR: optimization failed" << std::endl;
00249         return 1;
00250     }
00251     // write output file
00252     if( write_output )
00253     {
00254         std::string result_file( tostr( metric ) );
00255         result_file += "-";
00256         result_file += input_file_base;
00257         mesh.write_vtk( result_file.c_str(), err );
00258         if( err )
00259         {
00260             std::cerr << err << std::endl;
00261             std::cerr << "ERROR: " << result_file << " : failed to write file" << std::endl;
00262             err.clear();
00263         }
00264         else
00265         {
00266             std::cerr << "Wrote file: " << result_file << std::endl;
00267         }
00268     }
00269 
00270     // test number of inverted elements
00271     int count, junk;
00272     wrapper.quality_assessor().get_inverted_element_count( count, junk, err );
00273     if( err ) abort();
00274     if( count < expected )
00275     {
00276         std::cout << "WARNING: expected " << expected << " inverted elements but finished with only " << count
00277                   << std::endl
00278                   << "Test needs to be updated?" << std::endl
00279                   << std::endl;
00280         return 0;
00281     }
00282     else if( count == expected )
00283     {
00284         std::cout << "Completed with " << count << " inverted elements remaining" << std::endl << std::endl;
00285         return 0;
00286     }
00287     else
00288     {
00289         std::cerr << "ERROR: expected " << expected << " inverted elements but finished with " << count << std::endl
00290                   << std::endl;
00291         return 1;
00292     }
00293 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines