stl.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 
33 #ifndef __INCLUDE_MIST_STL__
34 #define __INCLUDE_MIST_STL__
35 
36 
37 #ifndef __INCLUDE_MIST_H__
38 #include "../mist.h"
39 #endif
40 
41 // ポリゴンオブジェクトの型を読み込む
42 #ifndef __INCLUDE_MIST_FACET__
43 #include "../facet.h"
44 #endif
45 
46 
47 #include <iostream>
48 #include <string>
49 #include <vector>
50 
51 
52 // mist名前空間の始まり
54 
55 
56 namespace __stl_controller__
57 {
58  struct _facet_
59  {
60  enum{ bytes = 50 };
61  float nX;
62  float nY;
63  float nZ;
64  float p1X;
65  float p1Y;
66  float p1Z;
67  float p2X;
68  float p2Y;
69  float p2Z;
70  float p3X;
71  float p3Y;
72  float p3Z;
73  unsigned short dmy;
74  } _MIST_PACKED;
75 
76  template < class T >
77  struct stl_controller
78  {
79  typedef facet_list< T > facet_list_type;
80  typedef typename facet_list_type::facet_type facet_type;
81  typedef typename facet_type::vector_type vector_type;
82  typedef typename facet_type::size_type size_type;
83 
84  static const unsigned char *get_line( const unsigned char *s, const unsigned char *e, std::string &line )
85  {
86  line = "";
87  while( s < e )
88  {
89  if( s[ 0 ] == '\r' )
90  {
91  if( s + 1 != e && s[ 1 ] == '\n' )
92  {
93  s = s + 2;
94  }
95  else
96  {
97  s++;
98  }
99  break;
100  }
101  else if( s[ 0 ] == '\n' )
102  {
103  s = s + 1;
104  break;
105  }
106  line += *s;
107  s++;
108  }
109  return( s > e ? e : s );
110  }
111 
112  static const unsigned char *get_value( const unsigned char *s, const unsigned char *e, std::string &line, bool &flag )
113  {
114  line = "";
115  // 先頭の空白(改行やタブを含む)を飛ばす
116  while( s < e )
117  {
118  if( flag && s[ 0 ] == '#' )
119  {
120  // コメント行なのですっ飛ばす
121  while( s < e )
122  {
123  if( s[ 0 ] == '\r' )
124  {
125  if( s + 1 != e && s[ 1 ] == '\n' )
126  {
127  s = s + 2;
128  }
129  else
130  {
131  s++;
132  }
133  break;
134  }
135  else if( s[ 0 ] == '\n' )
136  {
137  s++;
138  break;
139  }
140  s++;
141  }
142  }
143  else if( s[ 0 ] == '\r' )
144  {
145  if( s + 1 != e && s[ 1 ] == '\n' )
146  {
147  s = s + 2;
148  }
149  else
150  {
151  s = s + 1;
152  }
153  flag = true;
154  }
155  else if( s[ 0 ] == '\n' )
156  {
157  s++;
158  flag = true;
159  }
160  else if( s[ 0 ] == ' ' || s[ 0 ] == '\t' )
161  {
162  s++;
163  }
164  else
165  {
166  break;
167  }
168  }
169 
170  // 次に空白が来る前まで進める
171  flag = false;
172  while( s < e )
173  {
174  if( s[ 0 ] == '\r' )
175  {
176  if( s + 1 != e && s[ 1 ] == '\n' )
177  {
178  s = s + 2;
179  }
180  else
181  {
182  s++;
183  }
184  flag = true;
185  break;
186  }
187  else if( s[ 0 ] == '\n' )
188  {
189  s++;
190  flag = true;
191  break;
192  }
193  else if( s[ 0 ] == ' ' || s[ 0 ] == '\t' )
194  {
195  s++;
196  break;
197  }
198  line += *s;
199  s++;
200  }
201  return( s > e ? e : s );
202  }
203 
204  static size_type split_string( const std::string &line, const char ch, std::vector< std::string > &elements )
205  {
206  std::string str = "";
207  size_type i = 0;
208  elements.clear( );
209  while( i < line.size( ) )
210  {
211  for( ; i < line.size( ) && line[ i ] == ch ; i++ );
212 
213  str = "";
214  for( ; i < line.size( ) && line[ i ] != ch ; i++ )
215  {
216  str += line[ i ];
217  }
218 
219  if( str != "" )
220  {
221  elements.push_back( str );
222  }
223  }
224  return( elements.size( ) );
225  }
226 
227  static std::string to_lower( std::string line )
228  {
229  for( size_t i = 0 ; i < line.size( ) ; i++ )
230  {
231  if( 'A' <= line[ i ] && line[ i ] <= 'Z' )
232  {
233  line[ i ] += 'a' - 'A';
234  }
235  }
236  return( line );
237  }
238 
239  static bool convert_from_stl_ascii_data( facet_list_type &facets, const unsigned char *buff, size_type len )
240  {
241  const unsigned char *p = buff;
242  const unsigned char *e = buff + len;
243  std::string line = "";
244  std::vector< std::string > elements;
245 
246  facet_type facet;
247 
248  int stage = 0;
249  int vcount = 0;
250  bool eol = true;
251  while( p < e )
252  {
253  p = get_value( p, e, line, eol );
254  line = to_lower( line );
255 
256  switch( stage )
257  {
258  case 0:
259  if( line == "solid" )
260  {
261  stage++;
262  if( !eol )
263  {
264  p = get_line( p, e, facets.name );
265  eol = true;
266  }
267  }
268  else
269  {
270  std::cerr << "File does not start with 'solid'" << std::endl;
271  return( false );
272  }
273  break;
274 
275  case 1:
276  if( line == "endsolid" )
277  {
278  stage--;
279  return( true );
280  }
281  else if( line == "facet" )
282  {
283  stage++;
284  vcount = 0;
285  facet.normal = vector_type( 0, 0, 1 );
286  facet.p1 = facet.p2 = facet.p3 = vector_type( );
287 
288  if( !eol )
289  {
290  p = get_line( p, e, line );
291  eol = true;
292  std::vector< std::string > elements;
293  split_string( line, ' ', elements );
294 
295  if( elements.size( ) == 4 )
296  {
297  if( to_lower( elements[ 0 ] ) == "normal" )
298  {
299  facet.normal.x = atof( elements[ 1 ].c_str( ) );
300  facet.normal.y = atof( elements[ 2 ].c_str( ) );
301  facet.normal.z = atof( elements[ 3 ].c_str( ) );
302  }
303  else
304  {
305  std::cerr << "'facet' does not have 'normal'" << std::endl;
306  }
307  }
308  else
309  {
310  std::cerr << "'facet' does not have 'normal'" << std::endl;
311  }
312  }
313  else
314  {
315  std::cerr << "'facet' does not have 'normal'" << std::endl;
316  return( false );
317  }
318  }
319  else
320  {
321  std::cerr << "Line does not start with 'facet'" << std::endl;
322  return( false );
323  }
324  break;
325 
326  case 2:
327  if( line == "endfacet" )
328  {
329  stage--;
330 
331  // ポリゴンを登録する
332  if( vcount >= 3 )
333  {
334  if( facet.normal.inner( ( facet.p2 - facet.p1 ).outer( facet.p3 - facet.p1 ) ) < 0 )
335  {
336  vector_type tmp = facet.p2;
337  facet.p2 = facet.p3;
338  facet.p3 = tmp;
339  }
340 
341  facets.push_back( facet );
342  }
343  else
344  {
345  std::cerr << "Facet does not have enough vertices" << std::endl;
346  return( false );
347  }
348  }
349  else if( line == "outer" )
350  {
351  stage++;
352 
353  // 次の単語を読み込む
354  p = get_value( p, e, line, eol );
355  line = to_lower( line );
356 
357  if( line != "loop" )
358  {
359  std::cerr << "Line does not start with 'outer loop'" << std::endl;
360  return( false );
361  }
362  }
363  else
364  {
365  std::cerr << "Line does not start with 'outer loop'" << std::endl;
366  return( false );
367  }
368  break;
369 
370  case 3:
371  if( line == "endloop" )
372  {
373  stage--;
374  }
375  else if( line == "vertex" )
376  {
377  if( !eol )
378  {
379  p = get_line( p, e, line );
380  eol = true;
381  std::vector< std::string > elements;
382  split_string( line, ' ', elements );
383 
384  if( elements.size( ) == 3 )
385  {
386  switch( vcount )
387  {
388  case 0:
389  facet.p1.x = atof( elements[ 0 ].c_str( ) );
390  facet.p1.y = atof( elements[ 1 ].c_str( ) );
391  facet.p1.z = atof( elements[ 2 ].c_str( ) );
392  break;
393 
394  case 1:
395  facet.p2.x = atof( elements[ 0 ].c_str( ) );
396  facet.p2.y = atof( elements[ 1 ].c_str( ) );
397  facet.p2.z = atof( elements[ 2 ].c_str( ) );
398  break;
399 
400  case 2:
401  facet.p3.x = atof( elements[ 0 ].c_str( ) );
402  facet.p3.y = atof( elements[ 1 ].c_str( ) );
403  facet.p3.z = atof( elements[ 2 ].c_str( ) );
404  break;
405 
406  default:
407  break;
408  }
409 
410  vcount++;
411  }
412  else
413  {
414  std::cerr << "'facet' does not have 'vertex'" << std::endl;
415  }
416  }
417  else
418  {
419  std::cerr << "'facet' does not have 'vertex'" << std::endl;
420  return( false );
421  }
422  }
423  else
424  {
425  // error
426  std::cerr << "Line does not start with 'vertex'" << std::endl;
427  return( false );
428  }
429  break;
430 
431  default:
432  std::cerr << "Unknown error occured" << std::endl;
433  break;
434  }
435 
436  if( !eol )
437  {
438  // 行末までポインタを進める
439  p = get_line( p, e, line );
440  }
441  }
442 
443  return( false );
444  }
445 
446  static bool convert_from_stl_binary_data( facet_list_type &facets, const unsigned char *buff, size_type len )
447  {
448  const unsigned char *p = buff;
449  const unsigned char *e = buff + len;
450 
451  if( len < 80 + 4 )
452  {
453  return( false );
454  }
455 
456  size_type num_facets = ( ( unsigned int * )( buff + 80 ) )[ 0 ];
457 
458  if( len < 80 + 4 + num_facets * _facet_::bytes )
459  {
460  return( false );
461  }
462 
463  facets.name = std::string( ( std::string::value_type * )buff, 80 );
464 
465  for( size_type i = 0 ; i < num_facets ; i++ )
466  {
467  _facet_ *F = ( _facet_ * )( buff + 80 + 4 + _facet_::bytes * i );
468  facet_type f( vector_type( F->nX, F->nY, F->nZ ), vector_type( F->p1X, F->p1Y, F->p1Z ), vector_type( F->p2X, F->p2Y, F->p2Z ), vector_type( F->p3X, F->p3Y, F->p3Z ) );
469 
470  if( f.normal.length( ) == 0 )
471  {
472  f.normal = ( ( f.p2 - f.p1 ).outer( f.p3 - f.p1 ) ).unit( );
473  }
474  else if( f.normal.inner( ( f.p2 - f.p1 ).outer( f.p3 - f.p1 ) ) < 0 )
475  {
476  vector_type tmp = f.p2;
477  f.p2 = f.p3;
478  f.p3 = tmp;
479  }
480 
481  facets.push_back( f );
482  }
483 
484  return( true );
485  }
486 
487  static bool read( facet_list_type &facets, const std::string &filename )
488  {
489  // データをクリアする
490  facets.clear( );
491 
492  size_type filesize;
493  FILE *fp;
494  if( ( fp = fopen( filename.c_str( ), "rb" ) ) == NULL ) return( false );
495  // ファイルサイズを取得
496  fseek( fp, 0, SEEK_END );
497  filesize = ftell( fp );
498  fseek( fp, 0, SEEK_SET );
499 
500  // すべてのデータをファイルから読み込む
501  unsigned char *buff = new unsigned char[ filesize + 1 ];
502  unsigned char *pointer = buff;
503  size_type read_size = 0;
504  while( feof( fp ) == 0 )
505  {
506  read_size = fread( pointer, sizeof( unsigned char ), 1024, fp );
507  if( read_size < 1024 )
508  {
509  break;
510  }
511  pointer += read_size;
512  }
513  fclose( fp );
514 
515  bool ret = false;
516 
517  if( filesize > 5 )
518  {
519  std::string sss = to_lower( std::string( ( char * )buff, 5 ) );
520  if( sss == "solid" )
521  {
522  convert_from_stl_ascii_data( facets, buff, filesize );
523  }
524  else
525  {
526  convert_from_stl_binary_data( facets, buff, filesize );
527  }
528  }
529 
530  delete [] buff;
531 
532  return( ret );
533  }
534 
535  static bool write( const facet_list_type &facets, const std::string &filename, bool use_ascii_format )
536  {
537  if( facets.empty( ) )
538  {
539  std::cerr << "There is no facet!" << std::endl;
540  return( false );
541  }
542 
543  if( use_ascii_format )
544  {
545  FILE *fp;
546  if( ( fp = fopen( filename.c_str( ), "wt" ) ) == NULL )
547  {
548  return( false );
549  }
550 
551  fprintf( fp, "solid %s\n", facets.name.c_str( ) );
552 
553  for( size_type i = 0 ; i < facets.size( ) ; i++ )
554  {
555  const facet_type &f = facets[ i ];
556  fprintf( fp, "\tfacet normal %f %f %f\n", f.normal.x, f.normal.y, f.normal.z );
557  fprintf( fp, "\t\touter loop\n" );
558 
559  if( f.normal.inner( ( f.p2 - f.p1 ).outer( f.p3 - f.p1 ) ) >= 0 )
560  {
561  fprintf( fp, "\t\t\tvertex %f %f %f\n", f.p1.x, f.p1.y, f.p1.z );
562  fprintf( fp, "\t\t\tvertex %f %f %f\n", f.p2.x, f.p2.y, f.p2.z );
563  fprintf( fp, "\t\t\tvertex %f %f %f\n", f.p3.x, f.p3.y, f.p3.z );
564  }
565  else
566  {
567  fprintf( fp, "\t\t\tvertex %f %f %f\n", f.p1.x, f.p1.y, f.p1.z );
568  fprintf( fp, "\t\t\tvertex %f %f %f\n", f.p3.x, f.p3.y, f.p3.z );
569  fprintf( fp, "\t\t\tvertex %f %f %f\n", f.p2.x, f.p2.y, f.p2.z );
570  }
571 
572  fprintf( fp, "\t\tendloop\n" );
573  fprintf( fp, "\tendfacet\n" );
574  }
575 
576  fprintf( fp, "endsolid %s\n", facets.name.c_str( ) );
577 
578  fclose( fp );
579  }
580  else
581  {
582  FILE *fp;
583  if( ( fp = fopen( filename.c_str( ), "wb" ) ) == NULL )
584  {
585  return( false );
586  }
587 
588  unsigned int num_facets = static_cast< unsigned int >( facets.size( ) );
589  unsigned char dmy[ 80 ];
590  memset( dmy, 0, sizeof( unsigned char ) * 80 );
591 
592  {
593  std::string tmp = std::string( "Binary STL output by MIST: " ) + facets.name;
594  if( tmp.size( ) < 80 )
595  {
596  memcpy( dmy, tmp.c_str( ), tmp.size( ) );
597  }
598  else
599  {
600  memcpy( dmy, tmp.c_str( ), 80 );
601  }
602  }
603 
604  // ヘッダ情報を書き込む
605  fwrite( dmy, sizeof( unsigned char ), 80, fp );
606  fwrite( &num_facets, sizeof( unsigned int ), 1, fp );
607 
608  // ポリゴンデータを書き込む
609  for( size_type i = 0 ; i < facets.size( ) ; i++ )
610  {
611  const facet_type &f = facets[ i ];
612  _facet_ F;
613  F.nX = ( float )f.normal.x;
614  F.nY = ( float )f.normal.y;
615  F.nZ = ( float )f.normal.z;
616  F.p1X = ( float )f.p1.x;
617  F.p1Y = ( float )f.p1.y;
618  F.p1Z = ( float )f.p1.z;
619  F.p2X = ( float )f.p2.x;
620  F.p2Y = ( float )f.p2.y;
621  F.p2Z = ( float )f.p2.z;
622  F.p3X = ( float )f.p3.x;
623  F.p3Y = ( float )f.p3.y;
624  F.p3Z = ( float )f.p3.z;
625  F.dmy = 0x0000;
626 
627  fwrite( &F, 1, _facet_::bytes, fp );
628  }
629 
630  fclose( fp );
631  }
632 
633  return( true );
634  }
635  };
636 }
637 
638 
641 
653 
654 
663 template < class T >
664 bool read_stl( facet_list< T > &facets, const std::wstring &filename )
665 {
666  return( read_stl( facets, wstr2str( filename ) ) );
667 }
668 
669 
678 template < class T >
679 bool read_stl( facet_list< T > &facets, const std::string &filename )
680 {
681  return( __stl_controller__::stl_controller< T >::read( facets, filename ) );
682 }
683 
684 
694 template < class T >
695 inline bool write_stl( const facet_list< T > &facets, const std::wstring &filename, bool use_ascii_format = true )
696 {
697  return( write_stl( facets, wstr2str( filename ), use_ascii_format ) );
698 }
699 
700 
701 
702 
712 template < class T >
713 inline bool write_stl( const facet_list< T > &facets, const std::string &filename, bool use_ascii_format = true )
714 {
715  return( __stl_controller__::stl_controller< T >::write( facets, filename, use_ascii_format ) );
716 }
717 
718 
719 
721 // STL形式のポリゴンデータの入出力グループの終わり
722 
724 // CADデータ入出力グループの終わり
725 
726 
727 // mist名前空間の終わり
728 _MIST_END
729 
730 
731 #endif // __INCLUDE_MIST_STL__
732 

Generated on Wed Nov 12 2014 19:44:25 for MIST by doxygen 1.8.1.2