[MOAB-dev] r3502 - MOAB/trunk
iulian at mcs.anl.gov
iulian at mcs.anl.gov
Thu Jan 28 11:11:54 CST 2010
Author: iulian
Date: 2010-01-28 11:11:54 -0600 (Thu, 28 Jan 2010)
New Revision: 3502
Added:
MOAB/trunk/ReadSmf.cpp
MOAB/trunk/ReadSmf.hpp
MOAB/trunk/SMF_State.cpp
MOAB/trunk/SMF_State.hpp
MOAB/trunk/WriteSmf.cpp
MOAB/trunk/WriteSmf.hpp
Modified:
MOAB/trunk/MBReaderWriterSet.cpp
Log:
add smf reader/writer for MOAB
smf file format is used by QSLIM (surface mesh decimation code)
export of sets is not yet implemented; all triangles from the mesh will be written to smf file
Modified: MOAB/trunk/MBReaderWriterSet.cpp
===================================================================
--- MOAB/trunk/MBReaderWriterSet.cpp 2010-01-28 17:10:23 UTC (rev 3501)
+++ MOAB/trunk/MBReaderWriterSet.cpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -30,6 +30,7 @@
#include "ReadSms.hpp"
#include "Tqdcfr.hpp"
#include "ReadTetGen.hpp"
+#include "ReadSmf.hpp"
#ifdef CGM
# include "ReadCGM.hpp"
#endif
@@ -39,6 +40,7 @@
#include "WriteGMV.hpp"
#include "WriteSTL.hpp"
#include "WriteGmsh.hpp"
+#include "WriteSmf.hpp"
#ifdef NETCDF_FILE
# include "ReadNCDF.hpp"
@@ -90,6 +92,8 @@
register_factory( ReadSms::factory, NULL, "RPI SMS", "sms", "SMS" );
register_factory( Tqdcfr::factory, NULL, "Cubit", "cub", "CUBIT" );
+
+ register_factory( ReadSmf::factory, WriteSmf::factory , "QSlim format", "smf", "SMF");
#ifdef CGM
const char* acis_sufxs[] = { "sat", "sab", NULL };
Added: MOAB/trunk/ReadSmf.cpp
===================================================================
--- MOAB/trunk/ReadSmf.cpp (rev 0)
+++ MOAB/trunk/ReadSmf.cpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -0,0 +1,423 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation. Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+/**
+ * \class ReadSmf
+ * \brief SMF reader from QSLIM
+ * \author Michael Garland
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "ReadSmf.hpp"
+#include "MBRange.hpp"
+#include "MBInternals.hpp"
+#include "MBInterface.hpp"
+#include "MBReadUtilIface.hpp"
+#include "FileOptions.hpp"
+#include "MBAffineXform.hpp"
+
+inline int streq(const char *a,const char *b) { return strcmp(a,b)==0; }
+
+ReadSmf::cmd_entry ReadSmf::read_cmds[] = {
+ { "v", &ReadSmf::vertex },
+ { ":vn", &ReadSmf::v_normal },
+ { ":vc", &ReadSmf::v_color },
+ { ":fc", &ReadSmf::f_color },
+ { "t", &ReadSmf::face },
+ { "f", &ReadSmf::face },
+
+ { "begin", &ReadSmf::begin },
+ { "end", &ReadSmf::end },
+ { "set", &ReadSmf::set },
+ { "inc", &ReadSmf::inc },
+ { "dec", &ReadSmf::dec },
+
+ { "mmult", &ReadSmf::mload },
+ { "mload", &ReadSmf::mmult },
+ { "trans", &ReadSmf::trans },
+ { "scale", &ReadSmf::scale },
+ { "rot", &ReadSmf::rot },
+
+ { NULL, NULL }
+};
+
+MBAffineXform mat_from_args(std::vector<std::string> & argv)
+{
+ double m3[9], offset[3];
+ for (int i=0; i<9; i++)
+ m3[i] = atof(argv[i].c_str());
+ for (int j=0; j<3; j++)
+ offset[j] = atof(argv[j+9].c_str());// only the first 12 are used, the last row (or column?) is 0001?
+ MBAffineXform M(m3, offset);
+ return M;
+}
+
+void bad_annotation(char *cmd)
+{
+ std::cerr << "SMF: Malformed annotation ["<< cmd << "]" << std::endl;
+}
+
+MBReaderIface* ReadSmf::factory( MBInterface* iface )
+ { return new ReadSmf( iface ); }
+
+ReadSmf::ReadSmf(MBInterface* impl)
+ : mdbImpl(impl)
+{
+ void* ptr = 0;
+ mdbImpl->query_interface("MBReadUtilIface", &ptr);
+ readMeshIface = reinterpret_cast<MBReadUtilIface*>(ptr);
+ _numNodes= _numFaces = 0;
+ _numNodesInFile = _numElementsInFile = 0;
+}
+
+ReadSmf::~ReadSmf()
+{
+ if (readMeshIface) {
+ mdbImpl->release_interface("MBReadUtilIface", readMeshIface);
+ readMeshIface = 0;
+ }
+}
+
+
+MBErrorCode ReadSmf::read_tag_values( const char* /* file_name */,
+ const char* /* tag_name */,
+ const FileOptions& /* opts */,
+ std::vector<int>& /* tag_values_out */,
+ const IDTag* /* subset_list */,
+ int /* subset_list_length */ )
+{
+ return MB_NOT_IMPLEMENTED;
+}
+
+
+MBErrorCode ReadSmf::load_file( const char *filename,
+ const MBEntityHandle* ,
+ const FileOptions& opts,
+ const MBReaderIface::IDTag* subset_list,
+ int subset_list_length,
+ const MBTag* file_id_tag)
+{
+ MBErrorCode result;
+
+ int major, minor;
+ char vendor_string[257];
+ std::vector<MBRange> element_list;
+ MBRange vertices;
+
+ if (subset_list && subset_list_length) {
+ readMeshIface->report_error( "Reading subset of files not supported for VTK." );
+ return MB_UNSUPPORTED_OPERATION;
+ }
+
+ // Does the caller want a field to be used for partitioning the entities?
+ // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions.
+ std::string partition_tag_name;
+ result = opts.get_option( "PARTITION", partition_tag_name );
+ if ( result == MB_SUCCESS )
+ mPartitionTagName = partition_tag_name;
+
+ std::ifstream smfFile;
+ smfFile.open( filename , std::ifstream::in);
+ if (!smfFile.is_open())
+ {
+ return MB_FILE_DOES_NOT_EXIST;
+ }
+ init();
+
+
+ while( !smfFile.eof() )
+ {
+ if( smfFile.getline(line, SMF_MAXLINE, '\n').good() )
+ parse_line(line);
+ }
+
+ // at this point we have _numNodesInFile vertices and _numElementsInFile triangles
+ // the coordinates are in _coords, and connectivities in _connec
+ // std::vector<double> _coords; // 3*numNodes; we might not know the number of nodes
+ // std::vector<int> _connec; // 3*num of elements; we might not know them;
+
+ // Create vertices
+ std::vector<double*> arrays;
+ MBEntityHandle start_handle_out;
+ start_handle_out = 0;
+ result = readMeshIface->get_node_arrays( 3, _numNodesInFile, MB_START_ID,
+ start_handle_out, arrays );
+
+ if (MB_SUCCESS != result)
+ return result;
+
+
+ // fill the arrays with data from _coords
+ for (int i=0; i<_numNodesInFile; i++)
+ {
+ int i3 = 3*i;
+ arrays[0][i] = _coords[i3];
+ arrays[1][i] = _coords[i3+1];
+ arrays[2][i] = _coords[i3+2];
+ }
+ // elements
+
+ MBEntityHandle start_handle_elem_out;
+ start_handle_elem_out = 0;
+ MBEntityHandle* conn_array_out;
+ result = readMeshIface->get_element_array( _numElementsInFile,
+ 3,
+ MBTRI , // MBEntityType
+ MB_START_ID,
+ start_handle_elem_out,
+ conn_array_out );
+ if (MB_SUCCESS != result)
+ return result;
+ for (int j=0; j<_numElementsInFile*3; j++)
+ {
+ conn_array_out[j] = _connec[j];
+ }
+
+ // notify MOAB of the new elements
+ result = readMeshIface->update_adjacencies(start_handle_elem_out, _numElementsInFile,
+ 3, conn_array_out);
+
+ if (MB_SUCCESS != result)
+ return result;
+
+ MBRange range(start_handle_out, start_handle_out+_numElementsInFile-1);
+
+
+ return MB_SUCCESS;
+}
+
+void ReadSmf::init( )
+{
+ ivar.next_face = 1;
+ ivar.next_vertex = 1;
+ state = new SMF_State(ivar);
+ line = new char [4096];
+ return;
+}
+
+
+
+void ReadSmf::annotation(char *cmd, std::vector<std::string> & argv)
+{
+ // Skip over the '#$' prefix
+ cmd+=2;
+
+ if( streq(cmd,"SMF") ) {
+ if( atof(argv[0].c_str() ) != 1.0 )
+ std::cerr << "SMF: Version mismatch ("
+ << argv[0] << " instead of "
+ << "1.0" << ")" << std::endl;
+ }
+ else if( streq(cmd,"vertices") )
+ {
+ if( argv.size() == 1 )
+ _numNodes = atoi(argv[0].c_str() );
+ else
+ bad_annotation(cmd);
+ }
+ else if( streq(cmd, "faces") )
+ {
+ if( argv.size() == 1 )
+ _numFaces = atoi(argv[0].c_str() );
+ else
+ bad_annotation(cmd);
+
+ }
+ else if( streq(cmd, "BBox") )
+ {
+ }
+ else if( streq(cmd, "BSphere") )
+ {
+ }
+ else if( streq(cmd, "PXform") )
+ {
+ if( argv.size() == 16 )
+ mat_from_args(argv);
+ else
+ bad_annotation(cmd);
+ }
+ else if( streq(cmd, "MXform") )
+ {
+ if( argv.size() == 16 )
+ mat_from_args(argv);
+ else
+ bad_annotation(cmd);
+ }
+
+}
+
+void ReadSmf::parse_line(char *line)
+{
+ char *cmd,*s;
+ std::vector<std::string> argv;
+
+ while( *line==' ' || *line=='\t' ) line++; // skip initial white space
+
+ // Ignore empty lines
+ if( line[0]=='\n' || line[0]=='\0' ) return;
+
+ // Ignore comments
+ if( line[0]=='#' && line[1]!='$' ) return;
+
+ //
+ // First, split the line into tokens
+ cmd = strtok(line, " \t\n");
+
+ while( (s=strtok(NULL, " \t\n")) )
+ {
+ std::string stg(s);
+ argv.push_back(stg);
+ }
+
+ //
+ // Figure out what command it is and execute it
+ if( cmd[0]=='#' && cmd[1]=='$' )
+ annotation(cmd,argv);
+ else
+ {
+ cmd_entry *entry = &read_cmds[0];
+ bool handled = 0;
+
+ while( entry->name && !handled )
+ if( streq(entry->name, cmd) )
+ {
+ (this->*(entry->cmd))(argv);
+ handled = 1;
+ }
+ else
+ entry++;
+
+ if( !handled )
+ {
+ // Invalid command:
+ std::cerr << "SMF: Illegal command [" << cmd << "]" << std::endl;
+ exit(1);
+ }
+ }
+}
+
+
+void ReadSmf::vertex(std::vector<std::string> & argv)
+{
+ double v[3];
+
+ for (int i=0; i<3; i++)
+ v[i] = atof(argv[i].c_str() );
+
+ state->vertex(v);
+ ivar.next_vertex++;
+ _numNodesInFile++;
+ for (int j=0; j<3; j++)
+ _coords.push_back(v[j]);
+ //model->in_Vertex(v);
+}
+void ReadSmf::v_normal( std::vector<std::string> & argv )
+{
+}
+void ReadSmf::v_color(std::vector<std::string> & argv)
+{
+}
+void ReadSmf::f_color(std::vector<std::string> & argv)
+{
+}
+void ReadSmf::face(std::vector<std::string> & argv )
+{
+ int vert[3];
+
+ for(int i=0; i<argv.size(); i++)
+ vert[i] = atoi(argv[i].c_str());
+
+ state->face(vert, ivar);
+ ivar.next_face++;
+ for (int j=0; j<3; j++)
+ _connec.push_back(vert[j]);
+ _numElementsInFile++;
+
+}
+
+void ReadSmf::begin(std::vector<std::string> & argv)
+{
+ state = new SMF_State(ivar,state);
+}
+void ReadSmf::end(std::vector<std::string> & argv)
+{
+ SMF_State *old = state;
+ state=state->pop();
+ delete old;
+}
+void ReadSmf::set(std::vector<std::string> & argv)
+{
+ state->set(argv);
+}
+void ReadSmf::inc(std::vector<std::string> & argv)
+{
+ std::cerr << "SMF: INC not yet implemented." << std::endl;
+}
+void ReadSmf::dec(std::vector<std::string> & argv)
+{
+ std::cerr << "SMF: DEC not yet implemented." << std::endl;
+}
+
+void ReadSmf::trans(std::vector<std::string> & argv)
+{
+ double v3[3];
+ for (int i=0; i<3; i++)
+ v3[i] = atof(argv[i].c_str());
+ MBAffineXform M = MBAffineXform::translation(v3);
+ //Mat4 M = Mat4::trans(atof(argv(0)), atof(argv(1)), atof(argv(2)));
+ state->mmult(M);
+}
+void ReadSmf::scale(std::vector<std::string> & argv)
+{
+ double v3[3];
+ for (int i=0; i<3; i++)
+ v3[i] = atof(argv[i].c_str());
+ MBAffineXform M = MBAffineXform::scale(v3);
+ //Mat4 M = Mat4::scale(atof(argv(0)), atof(argv(1)), atof(argv(2)));
+ state->mmult(M);
+}
+void ReadSmf::rot(std::vector<std::string> & argv)
+{
+ double angle = atof(argv[1].c_str() ) * M_PI /180.0;
+ double axis[3] = {0., 0., 0.};
+ switch( argv[0][0] )
+ {
+ case 'x':
+ axis[0] = 1.;
+ break;
+ case 'y':
+ axis[1] = 1.;
+ break;
+ case 'z':
+ axis[2] = 1.;
+ break;
+ default:
+ std::cerr << "SMF: Malformed rotation command" << std::endl;
+ break;
+ }
+ MBAffineXform M = MBAffineXform::rotation( angle, axis );
+ state->mmult(M);
+}
+void ReadSmf::mmult(std::vector<std::string> & argv)
+{
+ state->mmult(mat_from_args(argv));
+}
+void ReadSmf::mload(std::vector<std::string> & argv)
+{
+ state->mload(mat_from_args(argv));
+}
Added: MOAB/trunk/ReadSmf.hpp
===================================================================
--- MOAB/trunk/ReadSmf.hpp (rev 0)
+++ MOAB/trunk/ReadSmf.hpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -0,0 +1,123 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation. Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef READ_SMF_HPP
+#define READ_SMF_HPP
+
+#define SMF_MAXLINE 4096
+
+#include "MBForward.hpp"
+#include "MBReaderIface.hpp"
+
+#include "SMF_State.hpp"
+#include <iosfwd>
+#include <fstream>
+
+class MBReadUtilIface;
+class FileTokenizer;
+
+class ReadSmf : public MBReaderIface
+{
+
+public:
+
+ static MBReaderIface* factory( MBInterface* );
+
+ //! load a file
+ MBErrorCode load_file( const char *file_name,
+ const MBEntityHandle* file_set,
+ const FileOptions&,
+ const MBReaderIface::IDTag* subset_list = 0,
+ int subset_list_length = 0,
+ const MBTag* file_id_tag = 0 );
+
+ MBErrorCode read_tag_values( const char* file_name,
+ const char* tag_name,
+ const FileOptions& opts,
+ std::vector<int>& tag_values_out,
+ const IDTag* subset_list = 0,
+ int subset_list_length = 0 );
+
+ //! Constructor
+ ReadSmf(MBInterface* impl = NULL);
+
+ //! Destructor
+ virtual ~ReadSmf();
+
+
+ typedef void (ReadSmf::*read_cmd)( std::vector<std::string> & argv);
+ struct cmd_entry { char *name; read_cmd cmd; };
+ void init();
+
+protected:
+
+
+ void annotation(char *cmd, std::vector<std::string> & argv);
+
+ void vertex(std::vector<std::string> &);
+ void v_normal( std::vector<std::string> &);
+ void v_color(std::vector<std::string> &);
+ void f_color(std::vector<std::string> &);
+ void face(std::vector<std::string> &);
+
+ void begin(std::vector<std::string> &);
+ void end(std::vector<std::string> &);
+ void set(std::vector<std::string> &);
+ void inc(std::vector<std::string> &);
+ void dec(std::vector<std::string> &);
+
+ void trans(std::vector<std::string> &);
+ void scale(std::vector<std::string> &);
+ void rot(std::vector<std::string> &);
+ void mmult(std::vector<std::string> &);
+ void mload(std::vector<std::string> &);
+
+ void parse_line(char *line);
+private:
+
+ MBReadUtilIface* readMeshIface;
+
+ //------------member variables ------------//
+
+
+ //! interface instance
+ //! interface instance
+ MBInterface* mdbImpl;
+
+ //! Meshset Handle for the mesh that is currently being read
+ MBEntityHandle mCurrentMeshHandle;
+
+ //! A field which, if present and having a single integer for storage, should be used to partition the mesh by range. Defaults to MATERIAL_SET_TAG_NAME
+ std::string mPartitionTagName;
+
+ // these are from SMF_reader from qslim/gfx/SMF/smf.h
+ static cmd_entry read_cmds[];
+ char *line;
+ SMF_State *state;
+ SMF_ivars ivar;
+ int _numNodes;
+ int _numFaces;
+ std::vector<double> _coords; // 3*numNodes; we might not know the number of nodes
+ std::vector<int> _connec; // 3*num of elements; we might not know them;
+ int _numNodesInFile;
+ int _numElementsInFile;
+
+};
+
+#endif
+
+
+
+
Added: MOAB/trunk/SMF_State.cpp
===================================================================
--- MOAB/trunk/SMF_State.cpp (rev 0)
+++ MOAB/trunk/SMF_State.cpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -0,0 +1,68 @@
+
+
+#include "SMF_State.hpp"
+
+inline int streq(const char *a,const char *b) { return std::strcmp(a,b)==0; }
+
+
+SMF_State::SMF_State(const SMF_ivars& ivar, SMF_State *link)
+{
+ next = link;
+ first_vertex = ivar.next_vertex;
+ if( next )
+ {
+ vertex_correction = next->vertex_correction;
+ xform = next->xform;
+ }
+ else
+ {
+ vertex_correction = 0;
+ MBAffineXform identity;
+ xform = identity;
+ }
+
+}
+
+void SMF_State::vertex(double v[3])
+{
+ xform.xform_point(v);
+}
+
+void SMF_State::normal(double normal[3])
+{
+ xform.xform_vector(normal);
+}
+
+void SMF_State::face( int * verts, const SMF_ivars& ivar)
+{
+ for(int i=0; i<3; i++)
+ {
+ if( verts[i] < 0 )
+ verts[i] += ivar.next_vertex;
+ else
+ verts[i] += vertex_correction + (first_vertex - 1);
+ }
+}
+
+void SMF_State::set( std::vector<std::string> & argv)
+{
+ const char *cmd = argv[0].c_str();
+
+ if( streq(cmd, "vertex_correction") )
+ vertex_correction = atoi(argv[1].c_str());
+}
+
+void SMF_State::mmult(const MBAffineXform &M)
+{
+ // initially, we tried this:
+ // xform.accumulate(M);
+ // maybe we should do M.accumulate(xform)
+ MBAffineXform tmp=M;
+ tmp.accumulate(xform);
+ xform = tmp;
+}
+
+void SMF_State::mload(const MBAffineXform& M)
+{
+ xform = M;
+}
Added: MOAB/trunk/SMF_State.hpp
===================================================================
--- MOAB/trunk/SMF_State.hpp (rev 0)
+++ MOAB/trunk/SMF_State.hpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -0,0 +1,43 @@
+#ifndef GFXSMF_STATE_INCLUDED // -*- C++ -*-
+#define GFXSMF_STATE_INCLUDED
+
+#include "MBAffineXform.hpp"
+#include <string>
+#include <vector>
+
+struct SMF_ivars
+{
+ int next_vertex;
+ int next_face;
+};
+
+class SMF_State
+{
+private:
+ SMF_State *next;
+
+ //
+ // Standard state variables
+ int first_vertex;
+ int vertex_correction;
+ MBAffineXform xform;
+
+public:
+ SMF_State(const SMF_ivars& ivar,SMF_State *link=NULL);
+ SMF_State *pop() { return next; }
+
+ void set(std::vector<std::string> & argv);
+ void inc(const char *var, int delta=1);
+ void dec(const char *var, int delta=1);
+
+ void mmult(const MBAffineXform&);
+ void mload(const MBAffineXform&);
+
+ void vertex(double v[3]);
+ void normal(double n[3]);
+ void face(int *, const SMF_ivars& ivar);
+};
+
+
+// GFXSMF_STATE_INCLUDED
+#endif
Added: MOAB/trunk/WriteSmf.cpp
===================================================================
--- MOAB/trunk/WriteSmf.cpp (rev 0)
+++ MOAB/trunk/WriteSmf.cpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -0,0 +1,189 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation. Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+
+#ifdef WIN32
+#ifdef _DEBUG
+// turn off warnings that say they debugging identifier has been truncated
+// this warning comes up when using some STL containers
+#pragma warning(disable : 4786)
+#endif
+#endif
+
+
+#include "WriteSmf.hpp"
+
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <assert.h>
+#include <vector>
+#include <set>
+#include <iterator>
+#include <algorithm>
+
+#include "MBInterface.hpp"
+#include "MBRange.hpp"
+#include "MBCN.hpp"
+#include "MBTagConventions.hpp"
+#include "MBWriteUtilIface.hpp"
+#include "MBInternals.hpp"
+#include "FileOptions.hpp"
+#include "MBVersion.h"
+
+const int DEFAULT_PRECISION = 10;
+const bool DEFAULT_STRICT = true;
+
+MBWriterIface *WriteSmf::factory( MBInterface* iface )
+ { return new WriteSmf( iface ); }
+
+WriteSmf::WriteSmf(MBInterface *impl)
+ : mbImpl(impl), writeTool(0)
+{
+ assert(impl != NULL);
+
+ void* ptr = 0;
+ impl->query_interface( "MBWriteUtilIface", &ptr );
+ writeTool = reinterpret_cast<MBWriteUtilIface*>(ptr);
+}
+
+WriteSmf::~WriteSmf()
+{
+ mbImpl->release_interface("MBWriteUtilIface", writeTool);
+}
+
+MBErrorCode WriteSmf::write_file(const char *file_name,
+ const bool overwrite,
+ const FileOptions& opts,
+ const MBEntityHandle *output_list,
+ const int num_sets,
+ const std::vector<std::string>& ,
+ const MBTag* tag_list,
+ int num_tags,
+ int )
+{
+ MBErrorCode rval;
+
+ // Get precision for node coordinates
+ int precision;
+ if (MB_SUCCESS != opts.get_int_option( "PRECISION", precision ))
+ precision = DEFAULT_PRECISION;
+
+ // Honor overwrite flag
+ if (!overwrite)
+ {
+ rval = writeTool->check_doesnt_exist( file_name );
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+
+ // Create file
+ std::ofstream file( file_name );
+ if (!file)
+ {
+ writeTool->report_error("Could not open file: %s\n", file_name );
+ return MB_FILE_WRITE_ERROR;
+ }
+ file.precision( precision );
+ // Get entities to write
+
+ MBRange triangles;
+ if (!output_list || !num_sets)
+ {
+ rval = mbImpl->get_entities_by_type( 0, MBTRI, triangles, false);
+ if (MB_SUCCESS != rval) return rval;
+
+ // somehow get all the nodes from this range, order them, uniquify, then use binary search
+ }
+ else
+ {
+ // not implemented yet, get out
+ // support export only of all triangles from the mesh
+ return MB_NOT_IMPLEMENTED;
+ }
+ // use an array with all the connectivities in the triangles; it will be converted later to ints
+ int numTriangles = triangles.size();
+ int array_alloc = 3*numTriangles; // allocated size of 'array'
+ MBEntityHandle* array = new MBEntityHandle[array_alloc]; // ptr to working array of result handles
+ // fill up array with node handles; reorder and uniquify
+ if (!array)
+ return MB_MEMORY_ALLOCATION_FAILED;
+ int fillA = 0;
+ for (MBRange::const_iterator e = triangles.begin(); e != triangles.end(); ++e)
+ {
+ const MBEntityHandle* conn;
+ int conn_len;
+ rval = mbImpl->get_connectivity( *e, conn, conn_len );
+ if (MB_SUCCESS != rval )
+ return rval;
+ if ( 3!=conn_len)
+ return MB_INVALID_SIZE;
+
+ for (int i = 0; i < conn_len; ++i)
+ array[fillA++] = conn[i];
+ }
+ if (fillA != array_alloc)
+ return MB_INVALID_SIZE;
+
+ std::sort( array, array + array_alloc);
+ int numNodes = std::unique(array, array + array_alloc ) - array;
+
+ file << "#$SMF 1.0\n";
+ file << "#$vertices " << numNodes << std::endl;
+ file << "#$faces " << numTriangles << std::endl;
+ file << "# \n";
+ file << "# output from MOAB \n";
+ file << "# \n";
+
+ // output first the nodes
+ // num nodes??
+ // write the nodes
+ double coord[3];
+ for(int i=0; i<numNodes; i++)
+ {
+ MBEntityHandle node_handle = array[i];
+
+ rval = mbImpl->get_coords(&node_handle,1, coord);
+ if(rval !=MB_SUCCESS) return rval;
+
+ file << "v " << coord[0] << " " << coord[1] << " " << coord[2] << std::endl;
+ }
+ // write faces now
+ // leave a blank line for cosmetics
+ file << " \n";
+ for (MBRange::const_iterator e = triangles.begin(); e != triangles.end(); ++e)
+ {
+ const MBEntityHandle* conn;
+ int conn_len;
+ rval = mbImpl->get_connectivity( *e, conn, conn_len );
+ if (MB_SUCCESS != rval )
+ return rval;
+ if ( 3!=conn_len)
+ return MB_INVALID_SIZE;
+ file << "f ";
+ for (int i = 0; i < conn_len; ++i)
+ {
+ int indexInArray = std::lower_bound( array, array + numNodes, conn[i] ) - array;
+ file << indexInArray + 1 << " " ;
+ }
+ file << std::endl;
+ }
+
+ file.close();
+ delete [] array;
+ return MB_SUCCESS;
+}
+
+
Added: MOAB/trunk/WriteSmf.hpp
===================================================================
--- MOAB/trunk/WriteSmf.hpp (rev 0)
+++ MOAB/trunk/WriteSmf.hpp 2010-01-28 17:11:54 UTC (rev 3502)
@@ -0,0 +1,58 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation. Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+
+#ifndef WRITE_SMF_HPP
+#define WRITE_SMF_HPP
+
+#include <iosfwd>
+
+#include "MBForward.hpp"
+#include "MBWriterIface.hpp"
+
+class MBWriteUtilIface;
+
+//class MB_DLL_EXPORT WriteSmf : public MBWriterIface
+class WriteSmf : public MBWriterIface
+{
+
+public:
+
+ //! Constructor
+ WriteSmf(MBInterface *impl);
+
+ //! Destructor
+ virtual ~WriteSmf();
+
+ static MBWriterIface* factory( MBInterface* );
+
+ //! writes out a file
+ MBErrorCode write_file(const char *file_name,
+ const bool overwrite,
+ const FileOptions& opts,
+ const MBEntityHandle *output_list,
+ const int num_sets,
+ const std::vector<std::string>& qa_list,
+ const MBTag* tag_list,
+ int num_tags,
+ int export_dimension);
+
+ private:
+
+ MBInterface* mbImpl;
+ MBWriteUtilIface* writeTool;
+};
+
+#endif
More information about the moab-dev
mailing list