MOAB: Mesh Oriented datABase  (version 5.4.1)
deforming.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 deform.cpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #include "TestUtil.hpp"
00033 #include "Mesquite.hpp"
00034 #include "DeformingDomainWrapper.hpp"
00035 #include "MeshImpl.hpp"
00036 #include "MsqError.hpp"
00037 #include "MeshDomain1D.hpp"
00038 #include "PlanarDomain.hpp"
00039 #include "QualityAssessor.hpp"
00040 #include "MsqVertex.hpp"
00041 
00042 #include <iostream>
00043 #include <cstdlib>
00044 #include <algorithm>
00045 
00046 using namespace MBMesquite;
00047 
00048 std::string INPUT_FILE = std::string( STRINGIFY( SRCDIR ) ) + "/sph-10-zsquare.vtk";
00049 // const char INPUT_FILE[] = "test.vtk";
00050 const double Z = 7.0;
00051 // size of new domain
00052 const double HD = 4.5;
00053 
00054 void usage( const char* argv0 )
00055 {
00056     std::cerr << "Usage: " << argv0 << " [-t <file>] [-d <file>] [-f <file>]" << std::endl
00057               << "\t-t : write initial mesh with tags containing reference mesh" << std::endl
00058               << "\t-d : write file containing deformed mesh with smoothed curves " << std::endl
00059               << "\t-f : write file containing final mesh" << std::endl
00060               << std::endl;
00061     std::exit( 1 );
00062 }
00063 
00064 void classify_boundary( Mesh* mesh,
00065                         Mesh::VertexHandle corners_out[4],
00066                         std::vector< Mesh::VertexHandle > curves_out[4],
00067                         MsqError& err );
00068 
00069 void cond_write_file( MeshImpl& mesh, const char* filename )
00070 {
00071     if( filename )
00072     {
00073         MsqPrintError err( std::cerr );
00074         mesh.write_vtk( filename, err );
00075         if( MSQ_CHKERR( err ) )
00076         {
00077             std::cerr << filename << ": failed to write file" << std::endl;
00078             exit( 1 );
00079         }
00080         std::cout << "Wrote file: " << filename << std::endl;
00081     }
00082 }
00083 
00084 int main( int argc, char* argv[] )
00085 {
00086     const char* deformed_file = 0;
00087     const char* smoothed_file = 0;
00088     const char* tag_file      = 0;
00089     struct
00090     {
00091         const char* flag;
00092         const char** name_ptr;
00093     } flags[] = { { "-d", &deformed_file }, { "-t", &tag_file }, { "-f", &smoothed_file }, { 0, 0 } };
00094 
00095     for( int i = 1; i < argc; ++i )
00096     {
00097         int j;
00098         for( j = 0; flags[j].flag && strcmp( flags[j].flag, argv[i] ); ++j )
00099             ;
00100         if( !flags[j].flag )
00101         {
00102             std::cerr << "Invalid argument: \"" << argv[i] << '"' << std::endl;
00103             usage( argv[0] );
00104         }
00105         else if( ++i == argc )
00106         {
00107             std::cerr << "Expected argument following \"" << argv[i - 1] << '"' << std::endl;
00108             usage( argv[0] );
00109         }
00110         *( flags[j].name_ptr ) = argv[i];
00111     }
00112 
00113     // load mesh
00114     MsqPrintError err( std::cerr );
00115     MeshImpl mesh;
00116     mesh.read_vtk( INPUT_FILE.c_str(), err );
00117     if( MSQ_CHKERR( err ) ) return 1;
00118 
00119     // find boundary vertices
00120     std::vector< Mesh::VertexHandle > curves[4];
00121     Mesh::VertexHandle corners[4];
00122     classify_boundary( &mesh, corners, curves, err );
00123     if( MSQ_CHKERR( err ) ) return 1;
00124 
00125     // new, "deformed" domain will be an 2HDx2HD planar square
00126     const double corner_coords[][3] = { { -HD, -HD, Z }, { HD, -HD, Z }, { HD, HD, Z }, { -HD, HD, Z } };
00127     LineDomain lines[4]             = { LineDomain( Vector3D( corner_coords[0] ), Vector3D( 1, 0, 0 ) ),
00128                             LineDomain( Vector3D( corner_coords[1] ), Vector3D( 0, 1, 0 ) ),
00129                             LineDomain( Vector3D( corner_coords[2] ), Vector3D( -1, 0, 0 ) ),
00130                             LineDomain( Vector3D( corner_coords[3] ), Vector3D( 0, -1, 0 ) ) };
00131     PlanarDomain surface( PlanarDomain::XY, Z );
00132 
00133     // save initial mesh state
00134     DeformingCurveSmoother curve_tool;
00135     for( int i = 0; i < 4; ++i )
00136     {
00137         curve_tool.store_initial_mesh( &mesh, &curves[i][0], curves[i].size(), &lines[i], err );
00138         if( MSQ_CHKERR( err ) ) return 1;
00139     }
00140     DeformingDomainWrapper wrapper;
00141     wrapper.store_initial_mesh( &mesh, err );
00142     if( MSQ_CHKERR( err ) ) return 1;
00143 
00144     cond_write_file( mesh, tag_file );
00145 
00146     // move corner vertices to new location
00147     for( int i = 0; i < 4; ++i )
00148     {
00149         Vector3D vect( corner_coords[i] );
00150         mesh.vertex_set_coordinates( corners[i], vect, err );
00151         if( MSQ_CHKERR( err ) ) return 1;
00152     }
00153     std::vector< bool > fixed( 4, true );
00154     mesh.vertices_set_fixed_flag( corners, fixed, 4, err );
00155     if( MSQ_CHKERR( err ) ) return 1;
00156 
00157     // smooth curves
00158     for( int i = 0; i < 4; ++i )
00159     {
00160         curve_tool.smooth_curve( &mesh, &curves[i][0], curves[i].size(), &lines[i],
00161                                  DeformingCurveSmoother::PROPORTIONAL, err );
00162         if( MSQ_CHKERR( err ) ) return 1;
00163         fixed.resize( curves[i].size(), true );
00164         mesh.vertices_set_fixed_flag( &curves[i][0], fixed, curves[i].size(), err );
00165         if( MSQ_CHKERR( err ) ) return 1;
00166     }
00167 
00168     cond_write_file( mesh, deformed_file );
00169 
00170     // smooth surface mesh
00171     MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &mesh, &surface );
00172     wrapper.run_instructions( &mesh_and_domain, err );
00173     if( MSQ_CHKERR( err ) ) return 1;
00174 
00175     cond_write_file( mesh, smoothed_file );
00176     return wrapper.quality_assessor().invalid_elements();
00177 }
00178 
00179 #define CHKMESH( COND, ERR )                                                         \
00180     do                                                                               \
00181     {                                                                                \
00182         if( !( COND ) )                                                              \
00183         {                                                                            \
00184             MSQ_SETERR( err )( "Unexpected mesh topology", MsqError::INVALID_MESH ); \
00185             return;                                                                  \
00186         }                                                                            \
00187     } while( false )
00188 
00189 void classify_boundary( Mesh* mesh,
00190                         Mesh::VertexHandle corners_out[4],
00191                         std::vector< Mesh::VertexHandle > curves_out[4],
00192                         MsqError& err )
00193 {
00194     std::vector< Mesh::VertexHandle > verts;
00195     mesh->get_all_vertices( verts, err );MSQ_ERRRTN( err );
00196 
00197     // Find the corner vertex that has negative X and Y coordinates
00198     Mesh::VertexHandle start;
00199     bool have_start = false;
00200     std::vector< Mesh::ElementHandle > elems;
00201     std::vector< size_t > offsets;
00202     for( size_t i = 0; i < verts.size(); ++i )
00203     {
00204         elems.clear();
00205         offsets.clear();
00206         mesh->vertices_get_attached_elements( &verts[i], 1, elems, offsets, err );MSQ_ERRRTN( err );
00207         if( elems.size() == 1 )
00208         {
00209             MsqVertex coords;
00210             mesh->vertices_get_coordinates( &verts[i], &coords, 1, err );MSQ_ERRRTN( err );
00211             if( coords[0] < 0.0 && coords[1] < 0.0 )
00212             {
00213                 CHKMESH( !have_start, err );
00214                 have_start = true;
00215                 start      = verts[i];
00216             }
00217         }
00218     }
00219     CHKMESH( have_start, err );
00220 
00221     // starting at a a corner vertex, find skin vertices
00222     std::vector< Mesh::VertexHandle > boundary;
00223     boundary.push_back( start );
00224     elems.clear();
00225     offsets.clear();
00226     mesh->vertices_get_attached_elements( &start, 1, elems, offsets, err );MSQ_ERRRTN( err );
00227     Mesh::ElementHandle prev = elems.front();
00228     corners_out[0]           = start;
00229     int ncorner              = 1;
00230     do
00231     {
00232         verts.clear();
00233         offsets.clear();
00234         mesh->elements_get_attached_vertices( &prev, 1, verts, offsets, err );
00235         size_t idx = std::find( verts.begin(), verts.end(), boundary.back() ) - verts.begin();
00236         CHKMESH( idx < verts.size(), err );
00237 
00238         Mesh::VertexHandle next = verts[( idx + 1 ) % verts.size()];
00239         elems.clear();
00240         offsets.clear();
00241         mesh->vertices_get_attached_elements( &next, 1, elems, offsets, err );MSQ_ERRRTN( err );
00242         CHKMESH( elems.size() == 1 || elems.size() == 2, err );
00243         if( elems.size() == 2 )
00244         {
00245             idx = std::find( elems.begin(), elems.end(), prev ) - elems.begin();
00246             CHKMESH( idx < 2, err );
00247             prev = elems[1 - idx];
00248         }
00249 
00250         if( elems.size() == 1 )
00251         {
00252             CHKMESH( ncorner < 5, err );
00253             if( ncorner < 4 )  // don't add start vertx twice
00254                 corners_out[ncorner] = next;
00255             ++ncorner;
00256         }
00257 
00258         boundary.push_back( next );
00259     } while( boundary.front() != boundary.back() );
00260     CHKMESH( ncorner == 5, err );
00261 
00262     // find curve vertices
00263     size_t idx = 0;
00264     for( int c = 0; c < 4; ++c )
00265     {
00266         Mesh::VertexHandle s, e;
00267         s = corners_out[c];
00268         e = corners_out[( c + 1 ) % 4];
00269         CHKMESH( idx < boundary.size(), err );
00270         CHKMESH( boundary[idx] == s, err );
00271         for( ; boundary[idx] != e; ++idx )
00272             curves_out[c].push_back( boundary[idx] );
00273         curves_out[c].push_back( e );
00274     }
00275 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines