- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

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名前空間の始まり
53 _MIST_BEGIN
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