1
15
16
21
22 #ifdef _WIN32
23 #define _USE_MATH_DEFINES
24 #endif
25
26 #include <cassert>
27 #include <cstdlib>
28 #include <iostream>
29
30 #include "ReadSmf.hpp"
31 #include "moab/Range.hpp"
32 #include "Internals.hpp"
33 #include "moab/Interface.hpp"
34 #include "moab/ReadUtilIface.hpp"
35 #include "moab/FileOptions.hpp"
36 #include "AffineXform.hpp"
37
38 static inline int streq( const char* a, const char* b )
39 {
40 return strcmp( a, b ) == 0;
41 }
42
43 namespace moab
44 {
45
46 ReadSmf::cmd_entry ReadSmf::read_cmds[] = { { "v", &ReadSmf::vertex },
47 { ":vn", &ReadSmf::v_normal },
48 { ":vc", &ReadSmf::v_color },
49 { ":fc", &ReadSmf::f_color },
50 { "t", &ReadSmf::face },
51 { "f", &ReadSmf::face },
52
53 { "begin", &ReadSmf::begin },
54 { "end", &ReadSmf::end },
55 { "set", &ReadSmf::set },
56 { "inc", &ReadSmf::inc },
57 { "dec", &ReadSmf::dec },
58
59 { "mmult", &ReadSmf::mload },
60 { "mload", &ReadSmf::mmult },
61 { "trans", &ReadSmf::trans },
62 { "scale", &ReadSmf::scale },
63 { "rot", &ReadSmf::rot },
64
65 { NULL, NULL } };
66
67 ErrorCode ReadSmf::parse_mat( const std::vector< std::string >& argv, AffineXform& mat )
68 {
69 double values[12];
70 ErrorCode err = parse_doubles( 12, argv, values );
71 if( MB_SUCCESS != err ) return err;
72
73 mat = AffineXform( values, values + 9 );
74 return MB_SUCCESS;
75 }
76
77 void ReadSmf::bad_annotation( const char* cmd )
78 {
79 std::cerr << "SMF: Malformed annotation [" << cmd << "]" << std::endl;
80 }
81
82 ReaderIface* ReadSmf::factory( Interface* iface )
83 {
84 return new ReadSmf( iface );
85 }
86
87 ReadSmf::ReadSmf( Interface* impl )
88 : mdbImpl( impl ), mCurrentMeshHandle( 0 ), lineNo( 0 ), commandNo( 0 ), versionMajor( 0 ), versionMinor( 0 )
89 {
90 mdbImpl->query_interface( readMeshIface );
91 ivar.next_vertex = 0;
92 ivar.next_face = 0;
93 _numNodes = _numFaces = 0;
94 _numNodesInFile = _numElementsInFile = 0;
95 }
96
97 ReadSmf::~ReadSmf()
98 {
99 if( readMeshIface )
100 {
101 mdbImpl->release_interface( readMeshIface );
102 readMeshIface = 0;
103 }
104 }
105
106 ErrorCode ReadSmf::read_tag_values( const char* ,
107 const char* ,
108 const FileOptions& ,
109 std::vector< int >& ,
110 const SubsetList* )
111 {
112 return MB_NOT_IMPLEMENTED;
113 }
114
115 ErrorCode ReadSmf::load_file( const char* filename,
116 const EntityHandle* ,
117 const FileOptions& opts,
118 const ReaderIface::SubsetList* subset_list,
119 const Tag* file_id_tag )
120 {
121 ErrorCode result;
122 lineNo = 0;
123 commandNo = 0;
124 versionMajor = 0;
125 versionMinor = 0;
126
127 if( subset_list )
128 {
129 MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for VTK" );
130 }
131
132
133
134 std::string partition_tag_name;
135 result = opts.get_option( "PARTITION", partition_tag_name );
136 if( result == MB_SUCCESS ) mPartitionTagName = partition_tag_name;
137
138 std::ifstream smfFile( filename );
139 if( !smfFile ) return MB_FILE_DOES_NOT_EXIST;
140
141 ivar.next_face = 1;
142 ivar.next_vertex = 1;
143 state.push_back( SMF_State( ivar ) );
144
145 while( smfFile.getline( line, SMF_MAXLINE, '\n' ).good() )
146 {
147 ++lineNo;
148 result = parse_line( line );
149 if( MB_SUCCESS != result ) return result;
150 }
151
152 if( !smfFile.eof() )
153 {
154
155 return MB_FILE_WRITE_ERROR;
156 }
157
158
159
160
161
162
163
164 std::vector< double* > arrays;
165 EntityHandle start_handle_out;
166 start_handle_out = 0;
167 result = readMeshIface->get_node_coords( 3, _numNodesInFile, MB_START_ID, start_handle_out, arrays );
168
169 if( MB_SUCCESS != result ) return result;
170
171
172
173 for( int i = 0; i < _numNodesInFile; i++ )
174 {
175 int i3 = 3 * i;
176 arrays[0][i] = _coords[i3];
177 arrays[1][i] = _coords[i3 + 1];
178 arrays[2][i] = _coords[i3 + 2];
179 }
180
181
182 EntityHandle start_handle_elem_out;
183 start_handle_elem_out = 0;
184 EntityHandle* conn_array_out;
185 result = readMeshIface->get_element_connect( _numElementsInFile, 3,
186 MBTRI,
187 MB_START_ID, start_handle_elem_out, conn_array_out );
188 if( MB_SUCCESS != result ) return result;
189 for( int j = 0; j < _numElementsInFile * 3; j++ )
190 conn_array_out[j] = _connec[j];
191
192
193 result = readMeshIface->update_adjacencies( start_handle_elem_out, _numElementsInFile, 3, conn_array_out );
194
195 if( MB_SUCCESS != result ) return result;
196
197 if( file_id_tag )
198 {
199 Range nodes( start_handle_out, start_handle_out + _numNodesInFile - 1 );
200 Range elems( start_handle_elem_out, start_handle_elem_out + _numElementsInFile - 1 );
201 readMeshIface->assign_ids( *file_id_tag, nodes );
202 readMeshIface->assign_ids( *file_id_tag, elems );
203 }
204
205 return MB_SUCCESS;
206 }
207
208 ErrorCode ReadSmf::annotation( char* cmd, std::vector< std::string >& argv )
209 {
210
211 cmd += 2;
212
213 if( streq( cmd, "SMF" ) )
214 {
215
216
217 if( commandNo > 1 )
218 {
219 MB_SET_ERR( MB_FILE_WRITE_ERROR, "SMF file version specified at line " << lineNo );
220 }
221
222 if( 2 == sscanf( argv[0].c_str(), "%d.%d", &versionMajor, &versionMinor ) )
223 {
224 if( versionMajor != 1 || versionMinor != 0 )
225 {
226 MB_SET_ERR( MB_FILE_WRITE_ERROR,
227 "Unsupported SMF file version: " << versionMajor << "." << versionMinor );
228 }
229 }
230 else
231 {
232 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid SMF version annotation" );
233 }
234 }
235 else if( streq( cmd, "vertices" ) )
236 {
237 if( argv.size() == 1 )
238 _numNodes = atoi( argv[0].c_str() );
239 else
240 bad_annotation( cmd );
241 }
242 else if( streq( cmd, "faces" ) )
243 {
244 if( argv.size() == 1 )
245 _numFaces = atoi( argv[0].c_str() );
246 else
247 bad_annotation( cmd );
248 }
249 else if( streq( cmd, "BBox" ) )
250 {
251 }
252 else if( streq( cmd, "BSphere" ) )
253 {
254 }
255 else if( streq( cmd, "PXform" ) )
256 {
257 if( argv.size() == 16 )
258 {
259
260 }
261 else
262 bad_annotation( cmd );
263 }
264 else if( streq( cmd, "MXform" ) )
265 {
266 if( argv.size() == 16 )
267 {
268
269 }
270 else
271 bad_annotation( cmd );
272 }
273
274 return MB_SUCCESS;
275 }
276
277 ErrorCode ReadSmf::parse_line( char* ln )
278 {
279 char *cmd, *s;
280 std::vector< std::string > argv;
281 ErrorCode err;
282
283 while( *ln == ' ' || *ln == '\t' )
284 ln++;
285
286
287 if( ln[0] == '\n' || ln[0] == '\0' ) return MB_SUCCESS;
288
289
290 if( ln[0] == '#' && ln[1] != '$' ) return MB_SUCCESS;
291
292
293 cmd = strtok( ln, " \t\n" );
294
295 while( ( s = strtok( NULL, " \t\n" ) ) )
296 {
297 std::string stg( s );
298 argv.push_back( stg );
299 }
300
301
302 if( cmd[0] == '#' && cmd[1] == '$' )
303 {
304 err = annotation( cmd, argv );
305 if( MB_SUCCESS != err ) return err;
306 }
307 else
308 {
309 cmd_entry* entry = &read_cmds[0];
310 bool handled = false;
311
312 while( entry->name && !handled )
313 {
314 if( streq( entry->name, cmd ) )
315 {
316 err = ( this->*( entry->cmd ) )( argv );
317 if( MB_SUCCESS != err ) return err;
318 handled = true;
319 ++commandNo;
320 }
321 else
322 entry++;
323 }
324
325 if( !handled )
326 {
327
328
329
330
331 if( !versionMajor && !commandNo ) return MB_FILE_WRITE_ERROR;
332
333
334 MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Illegal SMF command at line " << lineNo << ": \"" << cmd << "\"" );
335 }
336 }
337
338 return MB_SUCCESS;
339 }
340
341 ErrorCode ReadSmf::check_length( int count, const std::vector< std::string >& argv )
342 {
343 if( ( argv.size() < (unsigned)count ) || ( argv.size() > (unsigned)count && argv[count][0] != '#' ) )
344 {
345 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Expect " << count << " arguments at line " << lineNo );
346 }
347
348 return MB_SUCCESS;
349 }
350
351 ErrorCode ReadSmf::parse_doubles( int count, const std::vector< std::string >& argv, double results[] )
352 {
353 ErrorCode rval = check_length( count, argv );
354 if( MB_SUCCESS != rval ) return rval;
355
356 char* endptr;
357 for( int i = 0; i < count; i++ )
358 {
359 results[i] = strtod( argv[i].c_str(), &endptr );
360 if( *endptr )
361 {
362 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid vertex coordinates at line " << lineNo );
363 }
364 }
365
366 return MB_SUCCESS;
367 }
368
369 ErrorCode ReadSmf::vertex( std::vector< std::string >& argv )
370 {
371 double v[3];
372 ErrorCode err = parse_doubles( 3, argv, v );
373 if( MB_SUCCESS != err ) return err;
374
375 state.back().vertex( v );
376 ivar.next_vertex++;
377 _numNodesInFile++;
378 for( int j = 0; j < 3; j++ )
379 _coords.push_back( v[j] );
380
381 return MB_SUCCESS;
382 }
383
384 ErrorCode ReadSmf::v_normal( std::vector< std::string >& )
385 {
386 return MB_SUCCESS;
387 }
388
389 ErrorCode ReadSmf::v_color( std::vector< std::string >& )
390 {
391 return MB_SUCCESS;
392 }
393
394 ErrorCode ReadSmf::f_color( std::vector< std::string >& )
395 {
396 return MB_SUCCESS;
397 }
398
399 ErrorCode ReadSmf::face( std::vector< std::string >& argv )
400 {
401 ErrorCode err = check_length( 3, argv );
402 if( MB_SUCCESS != err ) return err;
403
404 int vert[3] = {};
405 char* endptr;
406 for( unsigned int i = 0; i < argv.size(); i++ )
407 {
408 vert[i] = strtol( argv[i].c_str(), &endptr, 0 );
409 if( *endptr )
410 {
411 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid face spec at line " << lineNo );
412 }
413 }
414
415 state.back().face( vert, ivar );
416 ivar.next_face++;
417 for( int j = 0; j < 3; j++ )
418 _connec.push_back( vert[j] );
419 _numElementsInFile++;
420
421 return MB_SUCCESS;
422 }
423
424 ErrorCode ReadSmf::begin( std::vector< std::string >& )
425 {
426 state.push_back( SMF_State( ivar, &state.back() ) );
427
428 return MB_SUCCESS;
429 }
430
431 ErrorCode ReadSmf::end( std::vector< std::string >& )
432 {
433
434
435
436 if( state.size() == 1 )
437 {
438 MB_SET_ERR( MB_FILE_WRITE_ERROR, "End w/out Begin at line " << lineNo );
439 }
440
441 state.pop_back();
442
443 return MB_SUCCESS;
444 }
445
446 ErrorCode ReadSmf::set( std::vector< std::string >& argv )
447 {
448 if( argv.size() < 2 || argv[0] != "vertex_coorection" ) return MB_SUCCESS;
449
450 char* endptr;
451 int val = strtol( argv[1].c_str(), &endptr, 0 );
452 if( *endptr )
453 {
454 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid value at line " << lineNo );
455 }
456
457 state.back().set_vertex_correction( val );
458
459 return MB_SUCCESS;
460 }
461
462 ErrorCode ReadSmf::inc( std::vector< std::string >& )
463 {
464
465 return MB_SUCCESS;
466 }
467
468 ErrorCode ReadSmf::dec( std::vector< std::string >& )
469 {
470
471 return MB_SUCCESS;
472 }
473
474 ErrorCode ReadSmf::trans( std::vector< std::string >& argv )
475 {
476 double v3[3];
477 ErrorCode err = parse_doubles( 3, argv, v3 );
478 if( MB_SUCCESS != err ) return err;
479
480 AffineXform M = AffineXform::translation( v3 );
481
482 state.back().mmult( M );
483
484 return MB_SUCCESS;
485 }
486
487 ErrorCode ReadSmf::scale( std::vector< std::string >& argv )
488 {
489 double v3[3];
490 ErrorCode err = parse_doubles( 3, argv, v3 );
491 if( MB_SUCCESS != err ) return err;
492
493 AffineXform M = AffineXform::scale( v3 );
494
495 state.back().mmult( M );
496
497 return MB_SUCCESS;
498 }
499
500 ErrorCode ReadSmf::rot( std::vector< std::string >& argv )
501 {
502 ErrorCode err = check_length( 2, argv );
503 if( MB_SUCCESS != err ) return err;
504
505 double axis[3] = { 0., 0., 0. };
506 std::string axisname = argv.front();
507 argv.erase( argv.begin() );
508 if( axisname.size() != 1 )
509 {
510 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo );
511 }
512 switch( axisname[0] )
513 {
514 case 'x':
515 axis[0] = 1.;
516 break;
517 case 'y':
518 axis[1] = 1.;
519 break;
520 case 'z':
521 axis[2] = 1.;
522 break;
523 default:
524 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo );
525 }
526
527 double angle;
528 err = parse_doubles( 1, argv, &angle );
529 if( MB_SUCCESS != err ) return err;
530 angle *= M_PI / 180.0;
531
532 AffineXform M = AffineXform::rotation( angle, axis );
533 state.back().mmult( M );
534
535 return MB_SUCCESS;
536 }
537
538 ErrorCode ReadSmf::mmult( std::vector< std::string >& argv )
539 {
540 AffineXform mat;
541 ErrorCode rval = parse_mat( argv, mat );
542 if( MB_SUCCESS != rval ) return rval;
543
544 state.back().mmult( mat );
545
546 return MB_SUCCESS;
547 }
548
549 ErrorCode ReadSmf::mload( std::vector< std::string >& argv )
550 {
551 AffineXform mat;
552 ErrorCode rval = parse_mat( argv, mat );
553 if( MB_SUCCESS != rval ) return rval;
554
555 state.back().mload( mat );
556
557 return MB_SUCCESS;
558 }
559
560 }