MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 }