33 #ifndef __INCLUDE_MIST_MESH__
34 #define __INCLUDE_MIST_MESH__
37 #ifndef __INCLUDE_MIST_CONF_H__
38 #include "../config/mist_conf.h"
41 #ifndef __INCLUDE_MIST_MATRIX__
42 #include "../matrix.h"
45 #ifndef __INCLUDE_MIST_VECTOR__
46 #include "../vector.h"
49 #ifndef __INCLUDE_CONVERTER__
50 #include "../converter.h"
53 #ifndef __INCLUDE_MIST_LABELING__
54 #include "../filter/labeling.h"
57 #ifndef __INCLUDE_MIST_DRAWING__
58 #include "../drawing.h"
78 namespace __mesh_utility__
80 struct __mesh_information__
82 typedef size_t size_type;
83 typedef ptrdiff_t difference_type;
84 typedef vector2< double > vector_type;
86 difference_type label;
87 difference_type count;
96 __mesh_information__( ) : label( -1 ), count( 0 ), round( 0.0 ), pos( 0.0, 0.0 ), enabled( true ), mark( -1 ), row( -1 ), col( -1 ), length( 1.0e10 )
101 bool operator <(
const __mesh_information__ &m )
const
103 return( this->round > m.round );
106 static bool sort_by_round(
const __mesh_information__ &m1,
const __mesh_information__ &m2 )
108 return( m1.round > m2.round );
111 static bool sort_by_length(
const __mesh_information__ &m1,
const __mesh_information__ &m2 )
113 return( m1.length < m2.length );
117 inline double __minimum__(
double v1,
double v2 )
119 return( v1 < v2 ? v1 : v2 );
122 inline double __compute_border_distance__(
const vector2< double > &pos,
double image_width,
double image_height )
124 double xmin = __minimum__( std::abs( pos.x ), std::abs( image_width - pos.x ) );
125 double ymin = __minimum__( std::abs( pos.y ), std::abs( image_height - pos.y ) );
126 return( __minimum__( xmin, ymin ) );
147 template <
class T,
class Allocator >
150 typedef __mesh_utility__::__mesh_information__ __mesh_information__;
154 typedef std::deque< __mesh_information__ > mesh_list_type;
155 typedef typename mesh_list_type::iterator mesh_iterator;
156 typedef typename mesh_list_type::reverse_iterator mesh_reverse_iterator;
164 difference_type r, c;
165 difference_type rows = grid.rows( );
166 difference_type cols = grid.cols( );
168 size_type labelnum =
labeling4( binary, binary );
171 mesh_list_type mesh_list;
174 for( i = 0 ; i <= labelnum ; i++ )
176 meshes[ i ].label = i;
180 for( size_type i = 0 ; i < grid.size( ) ; i++ )
187 meshes[ 0 ].enabled =
false;
190 const double _2 = std::sqrt( 2.0 );
191 for( j = 0 ; j < chart.
height( ) - 1 ; j++ )
193 for( i = 0 ; i < chart.
width( ) - 1 ; i++ )
195 __mesh_information__ &mesh = meshes[ binary( i, j ) ];
201 __mesh_information__ &m0 = mesh;
202 __mesh_information__ &m1 = meshes[ binary( i + 1, j ) ];
203 __mesh_information__ &m2 = meshes[ binary( i , j + 1 ) ];
204 __mesh_information__ &m3 = meshes[ binary( i + 1, j + 1 ) ];
205 size_type l0 = m0.label;
206 size_type l1 = m1.label;
207 size_type l2 = m2.label;
208 size_type l3 = m3.label;
212 size_type num_eq = 0;
213 if( l1 == l0 ) num_eq++;
214 if( l2 == l0 ) num_eq++;
215 if( l3 == l0 ) num_eq++;
221 else if( num_eq == 1 && l0 != l3 )
252 for( i = 1 ; i <= labelnum ; i++ )
254 __mesh_information__ &mesh = meshes[ i ];
255 mesh.pos.x /= mesh.count;
256 mesh.pos.y /= mesh.count;
260 for( i = 0 ; i < chart.
width( ) ; i++ )
262 meshes[ binary( i, 0 ) ].enabled =
false;
263 meshes[ binary( i, chart.
height( ) - 1 ) ].enabled =
false;
267 for( j = 0 ; j < chart.
height( ) ; j++ )
269 meshes[ binary( 0, j ) ].enabled =
false;
270 meshes[ binary( chart.
width( ) - 1, j ) ].enabled =
false;
274 difference_type minimum_count = 15;
275 for( i = 1 ; i <= labelnum ; i++ )
277 __mesh_information__ &mesh = meshes[ i ];
278 if( mesh.count < minimum_count )
280 mesh.enabled =
false;
282 else if( mesh.enabled )
284 const double pai = 3.1415926535897932384626433832795;
285 const double S = mesh.count;
286 const double L = mesh.round;
287 double e = 4.0 * pai * S / ( L * L );
288 if( e < threshold_for_circular_ratio )
290 mesh.enabled =
false;
294 mesh_list.push_back( mesh );
300 if( mesh_list.size( ) < 10 )
306 std::sort( mesh_list.begin( ), mesh_list.end( ), __mesh_information__::sort_by_round );
310 mesh_iterator ite = mesh_list.begin( );
311 difference_type base_mesh_num = 1;
312 double oround = ite->round;
313 double maxround = ite->round;
318 for( ; ite != mesh_list.end( ) ; ++ite )
320 double round = ite->round;
325 if( round > oround * 0.9 && round > maxround * 0.5 )
336 for( ; ite != mesh_list.end( ) ; ++ite )
343 if( base_mesh_num < 2 )
345 for( ite = mesh_list.begin( ) ; ite != mesh_list.end( ) ; ++ite )
347 meshes[ ite->label ].mark = ite->mark;
350 for( i = 0 ; i < chart.
size( ) ; i++ )
352 if( meshes[ binary[ i ] ].mark >= 0 && meshes[ binary[ i ] ].enabled )
354 chart[ i ] =
static_cast< unsigned char >( meshes[ binary[ i ] ].mark );
366 double x1 = mesh_list[ 0 ].pos.x;
367 double y1 = mesh_list[ 0 ].pos.y;
368 double x2 = mesh_list[ 1 ].pos.x;
369 double y2 = mesh_list[ 1 ].pos.y;
372 double C = x2 * y1 - x1 * y2;
374 mesh_iterator site = mesh_list.
begin( );
375 mesh_iterator eite = site + base_mesh_num;
379 double __threshold__ = std::sqrt( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) ) * 0.2;
380 double D = 1.0 / std::sqrt( A * A + B * B );
381 for( ite = site ; ite != eite ; ++ite )
383 if( std::abs( A * ite->pos.x + B * ite->pos.y + C ) * D > __threshold__ )
392 for( ite = site ; ite != eite ; ++ite )
396 ite->length = - B * ite->pos.x + A * ite->pos.y;
400 ite->length = 1.0e10;
405 std::sort( site, eite, __mesh_information__::sort_by_length );
406 site = mesh_list.begin( );
407 eite = site + base_mesh_num;
412 mesh_iterator mite = mesh_list.begin( );
413 mesh_iterator oite = mesh_list.begin( );
414 mesh_iterator cite = oite;
415 for( ; cite != eite ; ++cite )
417 if( mite->round < cite->round )
423 for( cite = mite, oite = mite ; cite != eite ; ++cite )
425 double r1 = oite->round;
426 double r2 = cite->round;
430 if( ( r1 > r2 && r2 < r1 * 0.8 ) || ( r1 < r2 && r1 < r2 * 0.8 ) )
438 for( ; cite != eite ; ++cite )
441 cite->length = 1.0e10;
444 mesh_reverse_iterator rmite( mite + 1 );
445 mesh_reverse_iterator reite = mesh_list.rend( );
446 mesh_reverse_iterator rcite( rmite );
447 for( mesh_reverse_iterator roite = rmite ; rcite != reite ; ++rcite )
449 double r1 = roite->round;
450 double r2 = rcite->round;
454 if( ( r1 > r2 && r2 < r1 * 0.8 ) || ( r1 < r2 && r1 < r2 * 0.8 ) )
462 for( ; rcite != reite ; ++rcite )
465 rcite->length = 1.0e10;
468 for( cite = site, base_mesh_num = 0 ; cite != eite ; ++cite )
470 if( cite->mark == 1 )
477 std::sort( site, eite, __mesh_information__::sort_by_length );
478 site = mesh_list.begin( );
479 eite = site + base_mesh_num;
482 if( col + 1 < base_mesh_num )
484 for( ite = mesh_list.begin( ) ; ite != mesh_list.end( ) ; ++ite )
486 meshes[ ite->label ].mark = ite->mark;
489 for( i = 0 ; i < chart.
size( ) ; i++ )
491 if( meshes[ binary[ i ] ].mark >= 0 && meshes[ binary[ i ] ].enabled )
493 chart[ i ] =
static_cast< unsigned char >( meshes[ binary[ i ] ].mark );
508 mesh_iterator ite1 = mesh_list.
begin( );
509 mesh_iterator ite2 = ite1 + base_mesh_num - 1;
510 double lth = 2.0 * ( ite1->pos - ite2->pos ).length( ) /
static_cast< double >( base_mesh_num - 1 );
512 double ratio1 = 1.0e10;
513 double ratio2 = 1.0e10;
515 double len0 = __mesh_utility__::__compute_border_distance__( mesh_list[ 0 ].pos, chart.
width( ), chart.
height( ) );
516 double len1 = __mesh_utility__::__compute_border_distance__( mesh_list[ base_mesh_num - 1 ].pos, chart.
width( ), chart.
height( ) );
521 vector_type p1 = ite1->pos;
522 vector_type p2 = ( ite1 + 1 )->pos;
523 double length = ( p1 - p2 ).length( );
524 vector_type dir = ( p1 - p2 ).unit( );
525 vector_type p = p1 + dir * length * 0.8;
528 for( mesh_iterator cite = mesh_list.begin( ) ; cite != mesh_list.end( ) ; ++cite )
530 double l = ( cite->pos - p ).length( );
531 if( l < min && cite != ite1 && l < length )
534 ratio1 = cite->round / ite1->round;
542 vector_type p1 = ite2->pos;
543 vector_type p2 = ( ite2 - 1 )->pos;
544 double length = ( p1 - p2 ).length( );
545 vector_type dir = ( p1 - p2 ).unit( );
546 vector_type p = p1 + dir * length * 0.8;
549 for( mesh_iterator cite = mesh_list.begin( ) ; cite != mesh_list.end( ) ; ++cite )
551 double l = ( cite->pos - p ).length( );
552 if( l < min && cite != ite2 && l < length )
555 ratio2 = cite->round / ite2->round;
560 if( ratio1 > ratio2 )
563 std::reverse( mesh_list.begin( ), mesh_list.begin( ) + base_mesh_num );
564 site = mesh_list.begin( );
565 eite = site + base_mesh_num;
567 else if( ratio1 == ratio2 && len0 < len1 )
570 std::reverse( mesh_list.begin( ), mesh_list.begin( ) + base_mesh_num );
571 site = mesh_list.begin( );
572 eite = site + base_mesh_num;
577 difference_type mark = 1;
578 difference_type column = col;
579 for( ite = site ; ite != eite ; ++ite )
585 grid( ite->row, ite->col ) = ite->pos;
587 for( ; ite != mesh_list.end( ) ; ++ite )
593 for( ite = mesh_list.begin( ) ; ite != mesh_list.end( ) ; ++ite )
595 meshes[ ite->label ].mark = ite->mark;
599 if( base_mesh_num < 3 )
601 for( ite = mesh_list.begin( ) ; ite != mesh_list.end( ) ; ++ite )
603 meshes[ ite->label ].mark = ite->mark;
606 for( i = 0 ; i < chart.
size( ) ; i++ )
608 if( meshes[ binary[ i ] ].mark >= 0 && meshes[ binary[ i ] ].enabled )
610 chart[ i ] =
static_cast< unsigned char >( meshes[ binary[ i ] ].mark );
624 __mesh_information__ m1 = mesh_list[ 0 ];
625 __mesh_information__ m2 = mesh_list[ 2 ];
626 site = mesh_list.begin( );
629 vector_type p1 = m1.pos;
630 vector_type p2 = m2.pos;
631 vector_type dir = ( p1 - p2 ).unit( );
632 vector_type norm( -dir.y, dir.x );
633 double length = ( p1 - p2 ).length( ) /
static_cast< double >( 2 );
636 mesh_list.erase( site, eite );
639 difference_type rindex[] = { -1, 1 };
640 for( r = 0 ; r < 2 ; r++ )
642 for( c = m1.col ; c >= m2.col ; c-- )
644 vector_type &op = grid( m1.row + rindex[ r ], c );
645 vector_type p = grid( m1.row, c ) + rindex[ r ] * norm * length * 0.5;
648 mesh_iterator cur = mesh_list.begin( );
649 for( mesh_iterator cite = mesh_list.begin( ) ; cite != mesh_list.end( ) ; ++cite )
651 double l = ( cite->pos - p ).length( );
660 if( cur != mesh_list.end( ) && min < length && min < cur->length )
663 if( cur->row >= 0 || cur->col >= 0 )
665 grid( cur->row, cur->col ).x = -1;
666 grid( cur->row, cur->col ).y = -1;
680 for( mesh_iterator ite = mesh_list.begin( ) ; ite != mesh_list.end( ) ; )
682 if( ite->mark == -2 )
684 ite = mesh_list.erase( ite );
694 for( i = 0 ; i < chart.
size( ) ; i++ )
696 if( meshes[ binary[ i ] ].mark >= 0 && meshes[ binary[ i ] ].enabled )
698 chart[ i ] =
static_cast< unsigned char >( meshes[ binary[ i ] ].mark );
711 difference_type ncount = 0;
712 for( r = 0 ; r < rows && ncount < rows * cols ; r++ )
714 for( c = 0 ; c < cols && ncount < rows * cols ; c++ )
716 vector_type p = grid( r, c );
718 if( p.x != -1 || p.y != -1 )
724 double search_length = 0.0;
727 if( 0 < c && c < cols - 1 && grid( r, c - 1 ).x >= 0 && grid( r, c + 1 ).x >= 0 )
729 p = ( grid( r, c - 1 ) + grid( r, c + 1 ) ) / 2.0;
730 search_length = ( grid( r, c - 1 ) - grid( r, c + 1 ) ).length( ) / 2.0;
732 else if( 0 < r && r < rows - 1 && grid( r - 1, c ).x >= 0 && grid( r + 1, c ).x >= 0 )
734 p = ( grid( r - 1, c ) + grid( r + 1, c ) ) / 2.0;
735 search_length = ( grid( r - 1, c ) - grid( r + 1, c ) ).length( ) / 2.0;
737 else if( c < cols - 3 && grid( r, c + 1 ).x >= 0 && grid( r, c + 2 ).x >= 0 && grid( r, c + 3 ).x >= 0 )
739 double l1 = ( grid( r, c + 2 ) - grid( r, c + 3 ) ).length( );
740 double l2 = ( grid( r, c + 1 ) - grid( r, c + 2 ) ).length( );
741 p = grid( r, c + 1 ) + ( grid( r, c + 1 ) - grid( r, c + 2 ) ).unit( ) * ( 2.0 * l2 - l1 );
742 search_length = ( 2.0 * l2 - l1 ) / 2.0;
744 else if( c > 3 && grid( r, c - 1 ).x >= 0 && grid( r, c - 2 ).x >= 0 && grid( r, c - 3 ).x >= 0 )
746 double l1 = ( grid( r, c - 2 ) - grid( r, c - 3 ) ).length( );
747 double l2 = ( grid( r, c - 1 ) - grid( r, c - 2 ) ).length( );
748 p = grid( r, c - 1 ) + ( grid( r, c - 1 ) - grid( r, c - 2 ) ).unit( ) * ( 2.0 * l2 - l1 );
749 search_length = ( 2.0 * l2 - l1 ) / 2.0;
751 else if( r < rows - 3 && grid( r + 1, c ).x >= 0 && grid( r + 2, c ).x >= 0 && grid( r + 3, c ).x >= 0 )
753 double l1 = ( grid( r + 2, c ) - grid( r + 3, c ) ).length( );
754 double l2 = ( grid( r + 1, c ) - grid( r + 2, c ) ).length( );
755 p = grid( r + 1, c ) + ( grid( r + 1, c ) - grid( r + 2, c ) ).unit( ) * ( 2.0 * l2 - l1 );
756 search_length = ( 2.0 * l2 - l1 ) / 2.0;
758 else if( r > 3 && grid( r - 1, c ).x >= 0 && grid( r - 2, c ).x >= 0 && grid( r - 3, c ).x >= 0 )
760 double l1 = ( grid( r - 2, c ) - grid( r - 3, c ) ).length( );
761 double l2 = ( grid( r - 1, c ) - grid( r - 2, c ) ).length( );
762 p = grid( r - 1, c ) + ( grid( r - 1, c ) - grid( r - 2, c ) ).unit( ) * ( 2.0 * l2 - l1 );
763 search_length = ( 2.0 * l2 - l1 ) / 2.0;
765 else if( c > 1 && r < rows - 1 && grid( r + 1, c ).x >= 0 && grid( r, c - 1 ).x >= 0 && grid( r + 1, c - 1 ).x >= 0 )
767 vector_type &p0 = grid( r + 1, c - 1 );
768 vector_type &p1 = grid( r + 1, c );
769 vector_type &p2 = grid( r, c - 1 );
770 vector_type d = p1 + p2 - 2.0 * p0;
773 search_length = 0.5 * d.length( );
775 else if( c > 1 && r > 1 && grid( r - 1, c ).x >= 0 && grid( r, c - 1 ).x >= 0 && grid( r - 1, c - 1 ).x >= 0 )
777 vector_type &p0 = grid( r - 1, c - 1 );
778 vector_type &p1 = grid( r - 1, c );
779 vector_type &p2 = grid( r, c - 1 );
780 vector_type d = p1 + p2 - 2.0 * p0;
783 search_length = 0.5 * d.length( );
785 else if( c < cols - 1 && r > 1 && grid( r, c + 1 ).x >= 0 && grid( r - 1, c ).x >= 0 && grid( r - 1, c + 1 ).x >= 0 )
787 vector_type &p0 = grid( r - 1, c + 1 );
788 vector_type &p1 = grid( r - 1, c );
789 vector_type &p2 = grid( r, c + 1 );
790 vector_type d = p1 + p2 - 2.0 * p0;
793 search_length = 0.5 * d.length( );
795 else if( c < cols - 1 && r < rows - 1 && grid( r, c + 1 ).x >= 0 && grid( r + 1, c ).x >= 0 && grid( r + 1, c + 1 ).x >= 0 )
797 vector_type &p0 = grid( r + 1, c + 1 );
798 vector_type &p1 = grid( r + 1, c );
799 vector_type &p2 = grid( r, c + 1 );
800 vector_type d = p1 + p2 - 2.0 * p0;
803 search_length = 0.5 * d.length( );
814 mesh_iterator cur = mesh_list.begin( );
815 for( mesh_iterator cite = mesh_list.begin( ) ; cite != mesh_list.end( ) ; ++cite )
817 double l = ( cite->pos - p ).length( );
825 if( cur != mesh_list.end( ) && min < search_length && min < cur->length )
828 if( cur->row >= 0 || cur->col >= 0 )
830 grid( cur->row, cur->col ).x = -1;
831 grid( cur->row, cur->col ).y = -1;
839 grid( r, c ) = cur->pos;
851 for( mesh_iterator ite = mesh_list.begin( ) ; ite != mesh_list.end( ) ; )
853 if( ite->mark == -2 )
855 ite = mesh_list.erase( ite );
863 if( ncount == rows * cols )
871 for( r = 0 ; r < rows ; r++ )
873 for( c = 0 ; c < cols ; c++ )
875 if( grid( r, c ).x < 0 )
880 bool b1 = r > 0 ? grid( r - 1, c ).x >= 0 :
false;
881 bool b2 = r < rows ? grid( r + 1, c ).x >= 0 :
false;
882 bool b3 = c > 0 ? grid( r, c - 1 ).x >= 0 :
false;
883 bool b4 = c < cols ? grid( r, c + 1 ).x >= 0 :
false;
886 if( r > 0 && grid( r - 1, c ).x >= 0 )
890 if( r < rows && grid( r + 1, c ).x >= 0 )
894 if( c > 0 && grid( r, c - 1 ).x >= 0 )
898 if( c < cols && grid( r, c + 1 ).x >= 0 )
923 #endif // __INCLUDE_MIST_TIMER__