Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
WriteSmf.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines