[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