Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /** 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00007 * retains certain rights in 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 */ 00015 00016 #ifdef WIN32 00017 #ifdef _DEBUG 00018 // turn off warnings that say they debugging identifier has been truncated 00019 // this warning comes up when using some STL containers 00020 #pragma warning( disable : 4786 ) 00021 #endif 00022 #endif 00023 00024 #include "WriteSmf.hpp" 00025 00026 #include <fstream> 00027 #include <iostream> 00028 #include <cstdio> 00029 #include <cassert> 00030 #include <vector> 00031 #include <set> 00032 #include <iterator> 00033 #include <algorithm> 00034 00035 #include "moab/Interface.hpp" 00036 #include "moab/Range.hpp" 00037 #include "moab/CN.hpp" 00038 #include "MBTagConventions.hpp" 00039 #include "moab/WriteUtilIface.hpp" 00040 #include "Internals.hpp" 00041 #include "moab/FileOptions.hpp" 00042 00043 namespace moab 00044 { 00045 00046 const int DEFAULT_PRECISION = 10; 00047 // const bool DEFAULT_STRICT = true; 00048 00049 WriterIface* WriteSmf::factory( Interface* iface ) 00050 { 00051 return new WriteSmf( iface ); 00052 } 00053 00054 WriteSmf::WriteSmf( Interface* impl ) : mbImpl( impl ), writeTool( 0 ) 00055 { 00056 assert( impl != NULL ); 00057 impl->query_interface( writeTool ); 00058 } 00059 00060 WriteSmf::~WriteSmf() 00061 { 00062 mbImpl->release_interface( writeTool ); 00063 } 00064 00065 ErrorCode WriteSmf::write_file( const char* file_name, 00066 const bool overwrite, 00067 const FileOptions& opts, 00068 const EntityHandle* output_list, 00069 const int num_sets, 00070 const std::vector< std::string >& /* qa_list */, 00071 const Tag* /* tag_list */, 00072 int /* num_tags */, 00073 int /* export_dimension */ ) 00074 { 00075 ErrorCode rval; 00076 00077 // Get precision for node coordinates 00078 int precision; 00079 if( MB_SUCCESS != opts.get_int_option( "PRECISION", precision ) ) precision = DEFAULT_PRECISION; 00080 00081 // Honor overwrite flag 00082 if( !overwrite ) 00083 { 00084 rval = writeTool->check_doesnt_exist( file_name ); 00085 if( MB_SUCCESS != rval ) return rval; 00086 } 00087 00088 // Create file 00089 std::ofstream file( file_name ); 00090 if( !file ) 00091 { 00092 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Could not open file: " << file_name ); 00093 } 00094 file.precision( precision ); 00095 00096 // Get entities to write 00097 Range triangles; 00098 if( !output_list || !num_sets ) 00099 { 00100 rval = mbImpl->get_entities_by_type( 0, MBTRI, triangles, false ); 00101 if( MB_SUCCESS != rval ) return rval; 00102 00103 // Somehow get all the nodes from this range, order them, uniquify, then use binary search 00104 } 00105 else 00106 { 00107 // Get all triangles from output sets 00108 for( int i = 0; i < num_sets; i++ ) 00109 rval = mbImpl->get_entities_by_type( output_list[i], MBTRI, triangles, false ); 00110 } 00111 // Use an array with all the connectivities in the triangles; it will be converted later to ints 00112 int numTriangles = triangles.size(); 00113 int array_alloc = 3 * numTriangles; // Allocated size of 'array' 00114 EntityHandle* array = new EntityHandle[array_alloc]; // ptr to working array of result handles 00115 // Fill up array with node handles; reorder and uniquify 00116 if( !array ) return MB_MEMORY_ALLOCATION_FAILED; 00117 int fillA = 0; 00118 for( Range::const_iterator e = triangles.begin(); e != triangles.end(); ++e ) 00119 { 00120 const EntityHandle* conn; 00121 int conn_len; 00122 rval = mbImpl->get_connectivity( *e, conn, conn_len ); 00123 if( MB_SUCCESS != rval ) 00124 { 00125 delete[] array; 00126 return rval; 00127 } 00128 if( 3 != conn_len ) 00129 { 00130 delete[] array; 00131 return MB_INVALID_SIZE; 00132 } 00133 00134 for( int i = 0; i < conn_len; ++i ) 00135 array[fillA++] = conn[i]; 00136 } 00137 if( fillA != array_alloc ) 00138 { 00139 delete[] array; 00140 return MB_INVALID_SIZE; 00141 } 00142 00143 std::sort( array, array + array_alloc ); 00144 int numNodes = std::unique( array, array + array_alloc ) - array; 00145 00146 file << "#$SMF 1.0\n"; 00147 file << "#$vertices " << numNodes << std::endl; 00148 file << "#$faces " << numTriangles << std::endl; 00149 file << "# \n"; 00150 file << "# output from MOAB \n"; 00151 file << "# \n"; 00152 00153 // Output first the nodes 00154 // num nodes?? 00155 // Write the nodes 00156 double coord[3]; 00157 for( int i = 0; i < numNodes; i++ ) 00158 { 00159 EntityHandle node_handle = array[i]; 00160 00161 rval = mbImpl->get_coords( &node_handle, 1, coord ); 00162 if( rval != MB_SUCCESS ) 00163 { 00164 delete[] array; 00165 return rval; 00166 } 00167 00168 file << "v " << coord[0] << " " << coord[1] << " " << coord[2] << std::endl; 00169 } 00170 // Write faces now 00171 // Leave a blank line for cosmetics 00172 file << " \n"; 00173 for( Range::const_iterator e = triangles.begin(); e != triangles.end(); ++e ) 00174 { 00175 const EntityHandle* conn; 00176 int conn_len; 00177 rval = mbImpl->get_connectivity( *e, conn, conn_len ); 00178 if( MB_SUCCESS != rval ) 00179 { 00180 delete[] array; 00181 return rval; 00182 } 00183 if( 3 != conn_len ) 00184 { 00185 delete[] array; 00186 return MB_INVALID_SIZE; 00187 } 00188 file << "f "; 00189 for( int i = 0; i < conn_len; ++i ) 00190 { 00191 int indexInArray = std::lower_bound( array, array + numNodes, conn[i] ) - array; 00192 file << indexInArray + 1 << " "; 00193 } 00194 file << std::endl; 00195 } 00196 00197 file.close(); 00198 delete[] array; 00199 return MB_SUCCESS; 00200 } 00201 00202 } // namespace moab