Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
moab::WriteSTL Class Reference

ASCII and Binary Stereo Lithography File writers. More...

#include <WriteSTL.hpp>

+ Inheritance diagram for moab::WriteSTL:
+ Collaboration diagram for moab::WriteSTL:

Public Member Functions

 WriteSTL (Interface *impl)
 Constructor. More...
 
virtual ~WriteSTL ()
 Destructor. More...
 
ErrorCode write_file (const char *file_name, const bool overwrite, const FileOptions &opts, const EntityHandle *output_list, const int num_sets, const std::vector< std::string > &qa_list, const Tag *tag_list=NULL, int num_tags=0, int export_dimension=3)
 writes out a file More...
 
- Public Member Functions inherited from moab::WriterIface
virtual ~WriterIface ()
 

Static Public Member Functions

static WriterIfacefactory (Interface *)
 factory method forSTL writer More...
 

Protected Types

enum  ByteOrder { STL_BIG_ENDIAN , STL_LITTLE_ENDIAN , STL_UNKNOWN_BYTE_ORDER }
 

Protected Member Functions

ErrorCode ascii_write_triangles (FILE *file, const char header[81], const Range &triangles, int precision)
 Write list of triangles to an STL file. More...
 
ErrorCode binary_write_triangles (FILE *file, const char header[81], ByteOrder byte_order, const Range &triangles)
 Write list of triangles to an STL file. More...
 
ErrorCode get_triangle_data (const double vtx_coords[9], float v1[3], float v2[3], float v3[3], float n[3])
 Given an array of vertex coordinates for a triangle, pass back individual point coordinates as floats and calculate triangle normal. More...
 
ErrorCode get_triangle_data (const double vtx_coords[9], CartVect &v1, CartVect &v2, CartVect &v3, CartVect &n)
 

Protected Attributes

InterfacembImpl
 interface instance More...
 
WriteUtilIfacemWriteIface
 

Private Member Functions

ErrorCode make_header (char header[81], const std::vector< std::string > &qa_list)
 Construct 80-byte, null-terminated description string from qa_list. Unused space in header will be null-char padded. More...
 
ErrorCode get_triangles (const EntityHandle *set_array, int set_array_length, Range &triangles)
 Get triangles to write from input array of entity sets. If no sets, gets all triangles. More...
 
FILE * open_file (const char *name, bool overwrite, bool binary)
 Open a file, respecting passed overwrite value and subclass-specified value for need_binary_io(). More...
 

Detailed Description

ASCII and Binary Stereo Lithography File writers.

Author
Jason Kraftcheck

This writer will write only the MBTRI elements in the mesh. It will not decompose other 2-D elements into triangles, nor will it skin the mesh or do any other high-level operation to generate triangles from 3-D elements.

Binary files will be written with a little-endian byte order by default. The byte order can be controlled with writer options.

Definition at line 42 of file WriteSTL.hpp.

Member Enumeration Documentation

◆ ByteOrder

enum moab::WriteSTL::ByteOrder
protected
Enumerator
STL_BIG_ENDIAN 
STL_LITTLE_ENDIAN 
STL_UNKNOWN_BYTE_ORDER 

Definition at line 67 of file WriteSTL.hpp.

68  {
72  };

Constructor & Destructor Documentation

◆ WriteSTL()

WriteSTL::WriteSTL ( Interface impl)

Constructor.

Definition at line 59 of file WriteSTL.cpp.

59  : mbImpl( impl )
60 {
62 }

References mWriteIface, and moab::Interface::query_interface().

Referenced by factory().

◆ ~WriteSTL()

WriteSTL::~WriteSTL ( )
virtual

Destructor.

Definition at line 64 of file WriteSTL.cpp.

65 {
67 }

References mbImpl, mWriteIface, and moab::Interface::release_interface().

Member Function Documentation

◆ ascii_write_triangles()

ErrorCode WriteSTL::ascii_write_triangles ( FILE *  file,
const char  header[81],
const Range triangles,
int  precision 
)
protected

Write list of triangles to an STL file.

Definition at line 234 of file WriteSTL.cpp.

235 {
236  const char solid_name[] = "MOAB";
237 
238  char myheader[81] = "solid ";
239  strcat( myheader, solid_name );
240  strncat( myheader, header, 80 );
241 
242  if( EOF == fputs( myheader, file ) || EOF == fputs( "\n", file ) ) return MB_FILE_WRITE_ERROR;
243 
244  ErrorCode rval;
245  double coords[9];
246  CartVect v1, v2, v3, n;
247  for( Range::const_iterator iter = triangles.begin(); iter != triangles.end(); ++iter )
248  {
249  const EntityHandle* conn;
250  int num_vtx;
251 
252  rval = mbImpl->get_connectivity( *iter, conn, num_vtx );
253  if( MB_SUCCESS != rval ) return rval;
254  if( num_vtx != 3 ) return MB_FAILURE;
255 
256  rval = mbImpl->get_coords( conn, 3, coords );
257  if( MB_SUCCESS != rval ) return rval;
258 
259  rval = get_triangle_data( coords, v1, v2, v3, n );
260  if( MB_SUCCESS != rval ) return rval;
261 
262  fprintf( file, "facet normal %e %e %e\n", n[0], n[1], n[2] );
263  fprintf( file, "outer loop\n" );
264  fprintf( file, "vertex %.*e %.*e %.*e\n", prec, (float)v1[0], prec, (float)v1[1], prec, (float)v1[2] );
265  fprintf( file, "vertex %.*e %.*e %.*e\n", prec, (float)v2[0], prec, (float)v2[1], prec, (float)v2[2] );
266  fprintf( file, "vertex %.*e %.*e %.*e\n", prec, (float)v3[0], prec, (float)v3[1], prec, (float)v3[2] );
267  fprintf( file, "endloop\n" );
268  fprintf( file, "endfacet\n" );
269  }
270 
271  fprintf( file, "endsolid %s\n", solid_name );
272  return MB_SUCCESS;
273 }

References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), get_triangle_data(), MB_FILE_WRITE_ERROR, MB_SUCCESS, and mbImpl.

Referenced by write_file().

◆ binary_write_triangles()

ErrorCode WriteSTL::binary_write_triangles ( FILE *  file,
const char  header[81],
ByteOrder  byte_order,
const Range triangles 
)
protected

Write list of triangles to an STL file.

Definition at line 284 of file WriteSTL.cpp.

288 {
289  ErrorCode rval;
290  if( 1 != fwrite( header, 80, 1, file ) ) return MB_FILE_WRITE_ERROR;
291 
292  // Default to little endian if byte_order == UNKNOWN_BYTE_ORDER
293  const bool want_big_endian = ( byte_order == STL_BIG_ENDIAN );
294  const bool am_big_endian = !SysUtil::little_endian();
295  const bool swap_bytes = ( want_big_endian == am_big_endian );
296 
297  if( triangles.size() > INT_MAX ) // Can't write that many triangles
298  return MB_FAILURE;
299 
300  uint32_t count = (uint32_t)triangles.size();
301  if( swap_bytes ) SysUtil::byteswap( &count, 1 );
302  if( 1 != fwrite( &count, 4, 1, file ) ) return MB_FILE_WRITE_ERROR;
303 
304  double coords[9];
305  BinTri tri;
306  tri.pad[0] = tri.pad[1] = '\0';
307  for( Range::const_iterator iter = triangles.begin(); iter != triangles.end(); ++iter )
308  {
309  const EntityHandle* conn;
310  int num_vtx;
311 
312  rval = mbImpl->get_connectivity( *iter, conn, num_vtx );
313  if( MB_SUCCESS != rval ) return rval;
314  if( num_vtx != 3 ) return MB_FAILURE;
315 
316  rval = mbImpl->get_coords( conn, 3, coords );
317  if( MB_SUCCESS != rval ) return rval;
318 
319  rval = get_triangle_data( coords, tri.vertex1, tri.vertex2, tri.vertex3, tri.normal );
320  if( MB_SUCCESS != rval ) return rval;
321 
322  if( swap_bytes )
323  {
324  SysUtil::byteswap( tri.normal, 3 );
325  SysUtil::byteswap( tri.vertex1, 3 );
326  SysUtil::byteswap( tri.vertex2, 3 );
327  SysUtil::byteswap( tri.vertex3, 3 );
328  }
329 
330  if( 1 != fwrite( &tri, 50, 1, file ) ) return MB_FILE_WRITE_ERROR;
331  }
332 
333  return MB_SUCCESS;
334 }

References moab::Range::begin(), moab::SysUtil::byteswap(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), get_triangle_data(), moab::SysUtil::little_endian(), MB_FILE_WRITE_ERROR, MB_SUCCESS, mbImpl, moab::BinTri::normal, moab::BinTri::pad, moab::Range::size(), STL_BIG_ENDIAN, moab::SysUtil::swap_bytes(), moab::BinTri::vertex1, moab::BinTri::vertex2, and moab::BinTri::vertex3.

Referenced by write_file().

◆ factory()

WriterIface * WriteSTL::factory ( Interface iface)
static

factory method forSTL writer

Definition at line 54 of file WriteSTL.cpp.

55 {
56  return new WriteSTL( iface );
57 }

References iface, and WriteSTL().

Referenced by moab::ReaderWriterSet::ReaderWriterSet().

◆ get_triangle_data() [1/2]

ErrorCode WriteSTL::get_triangle_data ( const double  vtx_coords[9],
CartVect v1,
CartVect v2,
CartVect v3,
CartVect n 
)
protected

Definition at line 221 of file WriteSTL.cpp.

222 {
223  v1 = coords;
224  v2 = coords + 3;
225  v3 = coords + 6;
226 
227  n = ( v2 - v1 ) * ( v3 - v1 );
228 
229  n.normalize();
230 
231  return MB_SUCCESS;
232 }

References MB_SUCCESS, and moab::CartVect::normalize().

◆ get_triangle_data() [2/2]

ErrorCode WriteSTL::get_triangle_data ( const double  vtx_coords[9],
float  v1[3],
float  v2[3],
float  v3[3],
float  n[3] 
)
protected

Given an array of vertex coordinates for a triangle, pass back individual point coordinates as floats and calculate triangle normal.

Definition at line 207 of file WriteSTL.cpp.

208 {
209  CartVect cv1, cv2, cv3, cn;
210  ErrorCode rval = get_triangle_data( coords, cv1, cv2, cv3, cn );
211  if( MB_SUCCESS != rval ) return rval;
212 
213  cv1.get( v1 );
214  cv2.get( v2 );
215  cv3.get( v3 );
216  cn.get( n );
217 
218  return MB_SUCCESS;
219 }

References ErrorCode, moab::CartVect::get(), and MB_SUCCESS.

Referenced by ascii_write_triangles(), and binary_write_triangles().

◆ get_triangles()

ErrorCode WriteSTL::get_triangles ( const EntityHandle set_array,
int  set_array_length,
Range triangles 
)
private

Get triangles to write from input array of entity sets. If no sets, gets all triangles.

Definition at line 190 of file WriteSTL.cpp.

191 {
192  if( !set_array || 0 == set_array_length ) return mbImpl->get_entities_by_type( 0, MBTRI, triangles );
193 
194  const EntityHandle* iter = set_array;
195  const EntityHandle* end = iter + set_array_length;
196  for( ; iter != end; ++iter )
197  {
198  Range r;
199  ErrorCode rval = mbImpl->get_entities_by_type( *iter, MBTRI, r, true );
200  if( MB_SUCCESS != rval ) return rval;
201  triangles.merge( r );
202  }
203 
204  return MB_SUCCESS;
205 }

References ErrorCode, moab::Interface::get_entities_by_type(), MB_SUCCESS, mbImpl, MBTRI, and moab::Range::merge().

Referenced by write_file().

◆ make_header()

ErrorCode WriteSTL::make_header ( char  header[81],
const std::vector< std::string > &  qa_list 
)
private

Construct 80-byte, null-terminated description string from qa_list. Unused space in header will be null-char padded.

Definition at line 172 of file WriteSTL.cpp.

173 {
174  memset( header, 0, 81 );
175 
176  std::string result;
177  for( std::vector< std::string >::const_iterator i = qa_list.begin(); i != qa_list.end(); ++i )
178  {
179  result += " ";
180  result += *i;
181  }
182 
183  size_t len = result.size();
184  if( len > 80 ) len = 80;
185  memcpy( header, result.c_str(), len );
186 
187  return MB_SUCCESS;
188 }

References MB_SUCCESS.

Referenced by write_file().

◆ open_file()

FILE * WriteSTL::open_file ( const char *  name,
bool  overwrite,
bool  binary 
)
private

Open a file, respecting passed overwrite value and subclass-specified value for need_binary_io().

Definition at line 134 of file WriteSTL.cpp.

135 {
136  // Open file with write access, and create it if it doesn't exist.
137  int flags = O_WRONLY | O_CREAT;
138  // Select behavior if the named file already exists. If
139  // overwrite is true, truncate the file. If it is false,
140  // make the call to open() fail.
141  if( overwrite )
142  flags |= O_TRUNC;
143  else
144  flags |= O_EXCL;
145  // If platform defines a "binary" bit in the file access
146  // flags (i.e. we're building on windows), then set it
147  // if we're writing a binary file.
148 #ifdef O_BINARY
149  if( binary ) flags |= O_BINARY;
150 #endif
151 
152  // Give everyone read and write, but not execute, permission.
153  // These are not the final permissions for the file. Permissions
154  // are removed according to the user's umask. All we want to
155  // say here is that the executable bits should not be set because
156  // this isn't an executable file. Everything else is a user
157  // preference and should be left up to the umask.
158  int creat_mode = _S_IREAD | _S_IWRITE;
159 
160  // Open the file.
161  int fd = open( name, flags, creat_mode );
162  if( fd < 0 )
163  {
164  MB_SET_ERR_RET_VAL( name << ": " << strerror( errno ), NULL );
165  }
166  FILE* result = fdopen( fd, binary ? "wb" : "w" );
167  if( !result ) close( fd );
168 
169  return result;
170 }

References _S_IREAD, _S_IWRITE, and MB_SET_ERR_RET_VAL.

Referenced by write_file().

◆ write_file()

ErrorCode WriteSTL::write_file ( const char *  file_name,
const bool  overwrite,
const FileOptions opts,
const EntityHandle output_list,
const int  num_sets,
const std::vector< std::string > &  qa_list,
const Tag tag_list = NULL,
int  num_tags = 0,
int  export_dimension = 3 
)
virtual

writes out a file

Implements moab::WriterIface.

Definition at line 69 of file WriteSTL.cpp.

78 {
79  char header[81];
80  Range triangles;
81  ErrorCode rval;
82 
83  if( tag_list && num_tags )
84  {
85  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "STL file does not support tag data" );
86  }
87 
88  rval = make_header( header, qa_list );
89  if( MB_SUCCESS != rval ) return rval;
90 
91  rval = get_triangles( ent_handles, num_sets, triangles );
92  if( MB_SUCCESS != rval ) return rval;
93 
94  if( triangles.empty() )
95  {
96  MB_SET_ERR( MB_ENTITY_NOT_FOUND, "No triangles to write" );
97  }
98 
99  bool is_ascii = false, is_binary = false;
100  if( MB_SUCCESS == opts.get_null_option( "ASCII" ) ) is_ascii = true;
101  if( MB_SUCCESS == opts.get_null_option( "BINARY" ) ) is_binary = true;
102  if( is_ascii && is_binary )
103  {
104  MB_SET_ERR( MB_FAILURE, "Conflicting options: BINARY ASCII" );
105  }
106 
107  bool big_endian = false, little_endian = false;
108  if( MB_SUCCESS == opts.get_null_option( "BIG_ENDIAN" ) ) big_endian = true;
109  if( MB_SUCCESS == opts.get_null_option( "LITTLE_ENDIAN" ) ) little_endian = true;
110  if( big_endian && little_endian )
111  {
112  MB_SET_ERR( MB_FAILURE, "Conflicting options: BIG_ENDIAN LITTLE_ENDIAN" );
113  }
115 
116  FILE* file = open_file( file_name, overwrite, is_binary );
117  if( !file ) return MB_FILE_DOES_NOT_EXIST;
118 
119  if( is_binary )
120  rval = binary_write_triangles( file, header, byte_order, triangles );
121  else
122  {
123  // Get precision for node coordinates
124  int precision;
125  if( MB_SUCCESS != opts.get_int_option( "PRECISION", precision ) ) precision = DEFAULT_PRECISION;
126 
127  rval = ascii_write_triangles( file, header, triangles, precision );
128  }
129 
130  fclose( file );
131  return rval;
132 }

References ascii_write_triangles(), moab::SysUtil::big_endian(), binary_write_triangles(), moab::DEFAULT_PRECISION, moab::Range::empty(), ErrorCode, moab::FileOptions::get_int_option(), moab::FileOptions::get_null_option(), get_triangles(), moab::SysUtil::little_endian(), make_header(), MB_ENTITY_NOT_FOUND, MB_FILE_DOES_NOT_EXIST, MB_SET_ERR, MB_SUCCESS, MB_TYPE_OUT_OF_RANGE, open_file(), STL_BIG_ENDIAN, STL_LITTLE_ENDIAN, and STL_UNKNOWN_BYTE_ORDER.

Member Data Documentation

◆ mbImpl

Interface* moab::WriteSTL::mbImpl
protected

interface instance

Definition at line 87 of file WriteSTL.hpp.

Referenced by ascii_write_triangles(), binary_write_triangles(), get_triangles(), and ~WriteSTL().

◆ mWriteIface

WriteUtilIface* moab::WriteSTL::mWriteIface
protected

Definition at line 88 of file WriteSTL.hpp.

Referenced by WriteSTL(), and ~WriteSTL().


The documentation for this class was generated from the following files: