00001 #ifndef vtol_extract_topology_txx_
00002 #define vtol_extract_topology_txx_
00003
00004 #include "vtol_extract_topology.h"
00005
00006
00007
00008 #include <vcl_iosfwd.h>
00009 #include <vcl_cassert.h>
00010
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vgl/vgl_vector_2d.h>
00013 #include <vgl/algo/vgl_line_2d_regression.h>
00014
00015 #include <vtol/vtol_vertex_2d.h>
00016 #include <vtol/vtol_edge_2d.h>
00017 #include <vtol/vtol_edge_2d_sptr.h>
00018 #include <vtol/vtol_intensity_face.h>
00019
00020 #include <vsol/vsol_curve_2d_sptr.h>
00021
00022 #include <vdgl/vdgl_edgel.h>
00023 #include <vdgl/vdgl_edgel_chain.h>
00024 #include <vdgl/vdgl_interpolator_linear.h>
00025 #include <vdgl/vdgl_digital_curve.h>
00026
00027 #ifndef NDEBUG
00028 # include <vcl_iostream.h>
00029 # define DBG( x ) x;
00030 #else
00031 # define DBG( x ) do {} while (false)
00032 #endif
00033
00034
00035
00036
00037
00038 typedef vtol_extract_topology_vertex_node vertex_node;
00039
00040
00041
00042
00043
00044 #if !VCL_STATIC_CONST_INIT_INT_NO_DEFN
00045 const unsigned
00046 vtol_extract_topology_vertex_node::null_index VCL_STATIC_CONST_INIT_INT_DEFN( unsigned(-2) );
00047
00048 const unsigned
00049 vtol_extract_topology_vertex_node::done_index VCL_STATIC_CONST_INIT_INT_DEFN( unsigned(-1) );
00050 #endif
00051
00052
00053
00054
00055
00056
00057 template< typename T >
00058 vtol_extract_topology<T>::
00059 vtol_extract_topology( label_image_type const& in_image,
00060 vtol_extract_topology_params const& in_params )
00061 : label_img_( in_image ),
00062 params_( in_params )
00063 {
00064 compute_label_range();
00065 construct_topology();
00066 }
00067
00068
00069
00070
00071
00072 template< typename T >
00073 vcl_vector< vtol_vertex_2d_sptr >
00074 vtol_extract_topology<T>::
00075 vertices() const
00076 {
00077 typedef vcl_vector< vertex_node >::const_iterator vertex_iterator_t;
00078
00079 vcl_vector< vtol_vertex_2d_sptr > verts;
00080
00081 for ( vertex_iterator_t i = node_list_.begin();
00082 i != node_list_.end(); ++i ) {
00083 verts.push_back( i->vertex );
00084 }
00085
00086 return verts;
00087 }
00088
00089
00090
00091
00092
00093 template< typename T >
00094 vcl_vector< vtol_intensity_face_sptr >
00095 vtol_extract_topology<T>::
00096 faces( data_image_type const& data_img ) const
00097 {
00098 region_collection region_list;
00099 collect_regions( region_list );
00100
00101
00102
00103
00104 vcl_vector< vtol_intensity_face_sptr > faces;
00105 for ( unsigned i = 0; i < region_list.size(); ++i ) {
00106 if ( ! region_list[i].empty() ) {
00107 compute_faces( region_list[i], faces, &data_img );
00108 }
00109 }
00110
00111 return faces;
00112 }
00113
00114
00115 template< typename T >
00116 vcl_vector< vtol_intensity_face_sptr >
00117 vtol_extract_topology<T>::
00118 faces( ) const
00119 {
00120 region_collection region_list;
00121 collect_regions( region_list );
00122
00123
00124
00125
00126 vcl_vector< vtol_intensity_face_sptr > faces;
00127 for ( unsigned i = 0; i < region_list.size(); ++i ) {
00128 if ( ! region_list[i].empty() ) {
00129 compute_faces( region_list[i], faces, 0 );
00130 }
00131 }
00132
00133 return faces;
00134 }
00135
00136
00137
00138
00139
00140 template< typename T >
00141 void
00142 vtol_extract_topology<T>::
00143 compute_label_range()
00144 {
00145 assert( label_img_.ni() >= 1 && label_img_.nj() >= 1 );
00146
00147
00148
00149 min_label_ = label_img_(0,0);
00150 max_label_ = min_label_;
00151 for ( unsigned j = 0; j < label_img_.nj(); ++j ) {
00152 for ( unsigned i = 0; i < label_img_.ni(); ++i ) {
00153 if ( min_label_ > label_img_(i,j) )
00154 min_label_ = label_img_(i,j);
00155 if ( max_label_ < label_img_(i,j) )
00156 max_label_ = label_img_(i,j);
00157 }
00158 }
00159 }
00160
00161
00162
00163
00164 template< typename LABEL_TYPE >
00165 typename vtol_extract_topology< LABEL_TYPE >::LabelPoint
00166 vtol_extract_topology< LABEL_TYPE >::
00167 label( unsigned i, unsigned j ) const
00168 {
00169 if ( i < label_img_.ni() && j < label_img_.nj() ) {
00170 return LabelPoint(label_img_( i, j ), true);
00171 }
00172 else {
00173 return LabelPoint(0, false);
00174 }
00175 }
00176
00177
00178
00179
00180
00181 template< typename T >
00182 bool
00183 vtol_extract_topology<T>::
00184 is_junction_vertex( unsigned i, unsigned j ) const
00185 {
00186
00187
00188 unsigned edge_count = 0;
00189 for ( unsigned dir = 0; dir < 4; ++dir ) {
00190 if ( is_edge( i, j, dir ) ) {
00191 ++edge_count;
00192 }
00193 }
00194
00195 return edge_count >= 3;
00196 }
00197
00198
00199
00200
00201
00202 template< typename LABEL_TYPE >
00203 bool
00204 vtol_extract_topology< LABEL_TYPE >::
00205 is_boundary_vertex( unsigned i, unsigned j ) const
00206 {
00207
00208
00209
00210 LabelPoint pixel1( label( i , j ) );
00211 LabelPoint pixel2( label( i , j-1 ) );
00212 LabelPoint pixel3( label( i-1, j ) );
00213 LabelPoint pixel4( label( i-1, j-1 ) );
00214
00215 return pixel1 != pixel2 || pixel2 != pixel3 || pixel3 != pixel4;
00216 }
00217
00218
00219
00220
00221
00222 template< typename LABEL_TYPE >
00223 bool
00224 vtol_extract_topology< LABEL_TYPE >::
00225 is_edge( unsigned i, unsigned j, unsigned dir ) const
00226 {
00227 LabelPoint left, right;
00228
00229 edge_labels( i, j, dir, left, right );
00230
00231 return left != right;
00232 }
00233
00234
00235
00236
00237
00238 template< typename LABEL_TYPE >
00239 void
00240 vtol_extract_topology< LABEL_TYPE >::
00241 edge_labels( unsigned i, unsigned j, unsigned dir,
00242 LabelPoint& left, LabelPoint& right ) const
00243 {
00244 assert( dir <= 3 );
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 static const int offsets[4][2] =
00255 { { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, -1 } };
00256
00257 unsigned dir2 = (dir+1) % 4;
00258
00259 left = label( i+offsets[dir ][0], j+offsets[dir ][1] );
00260 right = label( i+offsets[dir2][0], j+offsets[dir2][1] );
00261 }
00262
00263
00264
00265
00266
00267 template< typename T >
00268 unsigned
00269 vtol_extract_topology<T>::
00270 vertex_index( unsigned i, unsigned j ) const
00271 {
00272 assert( i < index_img_.ni() &&
00273 j < index_img_.nj() );
00274
00275 return index_img_( i, j );
00276 }
00277
00278
00279
00280
00281
00282 template< typename T >
00283 void
00284 vtol_extract_topology<T>::
00285 set_vertex_index( unsigned i, unsigned j, unsigned index )
00286 {
00287 assert( i < index_img_.ni() &&
00288 j < index_img_.nj() );
00289
00290 index_img_( i, j ) = index;
00291 }
00292
00293
00294
00295
00296
00297 template< typename T >
00298 vtol_extract_topology_vertex_node&
00299 vtol_extract_topology<T>::
00300 node( unsigned index )
00301 {
00302 assert( index < node_list_.size() );
00303
00304 return node_list_[index];
00305 }
00306
00307
00308 template< typename T >
00309 vtol_extract_topology_vertex_node const&
00310 vtol_extract_topology<T>::
00311 node( unsigned index ) const
00312 {
00313 assert( index < node_list_.size() );
00314
00315 return node_list_[index];
00316 }
00317
00318
00319
00320
00321
00322 template< typename T >
00323 void
00324 vtol_extract_topology<T>::
00325 move( unsigned dir, unsigned& i, unsigned& j )
00326 {
00327 assert( dir < 4 );
00328
00329 switch ( dir )
00330 {
00331 case 0:
00332 ++i;
00333 break;
00334 case 1:
00335 ++j;
00336 break;
00337 case 2:
00338 --i;
00339 break;
00340 case 3:
00341 --j;
00342 break;
00343 default: break;
00344 }
00345 }
00346
00347
00348
00349
00350
00351 template< typename T >
00352 void
00353 vtol_extract_topology<T>::
00354 set_mark( unsigned& marker, unsigned dir ) const
00355 {
00356 marker |= ( 1 << dir );
00357 }
00358
00359
00360
00361
00362
00363 template< typename T >
00364 bool
00365 vtol_extract_topology<T>::
00366 is_marked( unsigned marker, unsigned dir ) const
00367 {
00368 return ( marker & ( 1 << dir ) ) != 0;
00369 }
00370
00371
00372
00373
00374
00375 template< typename T >
00376 void
00377 vtol_extract_topology<T>::
00378 trace_edge_chain( unsigned i, unsigned j, unsigned dir )
00379 {
00380
00381
00382 if ( ! is_edge( i, j, dir ) )
00383 return;
00384
00385
00386
00387
00388
00389
00390 unsigned start_index = vertex_index( i, j );
00391 unsigned start_dir = dir;
00392
00393
00394
00395 vdgl_edgel_chain_sptr chain = new vdgl_edgel_chain();
00396
00397
00398 chain->add_edgel( vdgl_edgel( i-0.5, j-0.5, -1, dir*90 ) );
00399 move( dir, i, j );
00400
00401
00402
00403
00404
00405
00406
00407
00408 unsigned int prev_dir = (unsigned int)(-1);
00409
00410 while ( vertex_index( i, j ) == vertex_node::null_index )
00411 {
00412 set_vertex_index( i, j, vertex_node::done_index );
00413
00414 chain->add_edgel( vdgl_edgel( i-0.5, j-0.5, -1, dir*90 ) );
00415
00416
00417
00418
00419 DBG( unsigned count = 0 );
00420 prev_dir = dir;
00421 dir = (dir+3) % 4;
00422 while ( ! is_edge( i, j, dir ) ) {
00423 dir = (dir+1) % 4;
00424 DBG( ++count );
00425 DBG( assert( count < 3 ) );
00426 }
00427
00428 move( dir, i, j );
00429
00430
00431
00432
00433
00434 assert( vertex_index( i, j ) != vertex_node::done_index );
00435 }
00436
00437 unsigned end_index = vertex_index( i, j );
00438
00439 if ( end_index == start_index ) {
00440
00441
00442
00443 move( (dir+2)%4, i, j );
00444 set_vertex_index( i, j, node_list_.size() );
00445 node_list_.push_back( vertex_node( i, j ) );
00446 end_index = vertex_index( i, j );
00447 dir = prev_dir;
00448
00449 }
00450 else {
00451
00452 chain->add_edgel( vdgl_edgel( i-0.5, j-0.5 ) );
00453 }
00454
00455 chain = smooth_chain( chain, params_.num_for_smooth );
00456
00457 vertex_node& start_node = node( start_index );
00458 vertex_node& end_node = node( end_index );
00459
00460 vdgl_interpolator_sptr interp = new vdgl_interpolator_linear( chain );
00461 vsol_curve_2d_sptr curve = new vdgl_digital_curve( interp );
00462 vtol_edge_2d_sptr edge = new vtol_edge_2d( start_node.vertex,
00463 end_node.vertex,
00464 curve );
00465
00466 edgel_chain_sptr chain2 = new edgel_chain;
00467 chain2->chain = chain;
00468 chain2->edge = edge;
00469
00470
00471
00472
00473 dir = (dir+2) % 4;
00474
00475 start_node.link[ start_dir ] = end_index;
00476 start_node.back_dir[ start_dir ] = dir;
00477 start_node.edgel_chain[ start_dir ] = chain2;
00478
00479 end_node.link[ dir ] = start_index;
00480 end_node.back_dir[ dir ] = start_dir;
00481 end_node.edgel_chain[ dir ] = chain2;
00482 }
00483
00484
00485
00486
00487
00488 template< typename T >
00489 void
00490 vtol_extract_topology<T>::
00491 construct_topology( )
00492 {
00493
00494
00495
00496 index_img_.set_size( label_img_.ni()+1, label_img_.nj()+1 );
00497
00498 node_list_.clear();
00499 index_img_.fill( vertex_node::null_index );
00500
00501 for ( unsigned j = 0; j <= label_img_.nj(); ++j ) {
00502 for ( unsigned i = 0; i <= label_img_.ni(); ++i ) {
00503 if ( is_junction_vertex( i, j ) ) {
00504 set_vertex_index( i, j, node_list_.size() );
00505 node_list_.push_back( vertex_node( i, j ) );
00506 }
00507 }
00508 }
00509
00510
00511
00512
00513 for ( unsigned index = 0; index < node_list_.size(); ++index ) {
00514 for ( unsigned dir = 0; dir < 4; ++dir ) {
00515 if ( node(index).link[dir] == vertex_node::null_index ) {
00516 trace_edge_chain( node(index).i,
00517 node(index).j,
00518 dir );
00519 }
00520 }
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 for ( unsigned j = 0; j <= label_img_.nj(); ++j ) {
00533 for ( unsigned i = 0; i <= label_img_.ni(); ++i ) {
00534 if ( vertex_index( i, j ) == vertex_node::null_index &&
00535 is_boundary_vertex( i, j ) )
00536 {
00537
00538
00539 unsigned dir = 0;
00540 while ( dir < 4 && ! is_edge( i, j, dir ) ) {
00541 ++dir;
00542 }
00543 assert( dir < 4 );
00544 unsigned dir2 = dir+1;
00545 while ( dir2 < 4 && ! is_edge( i, j, dir2 ) ) {
00546 ++dir2;
00547 }
00548 assert( dir2 < 4 );
00549
00550
00551
00552 set_vertex_index( i, j, node_list_.size() );
00553 node_list_.push_back( vertex_node( i, j ) );
00554
00555
00556
00557 unsigned i2 = i, j2 = j;
00558 move( dir, i2, j2 );
00559 assert( vertex_index( i2, j2 ) == vertex_node::null_index &&
00560 is_boundary_vertex( i2, j2 ) );
00561 set_vertex_index( i2, j2, node_list_.size() );
00562 node_list_.push_back( vertex_node( i2, j2 ) );
00563
00564
00565
00566 trace_edge_chain( i, j, dir );
00567 trace_edge_chain( i, j, dir2 );
00568 }
00569 }
00570 }
00571
00572 #ifndef NDEBUG
00573
00574 bool good = true;
00575 for ( unsigned index = 0; index < node_list_.size(); ++index ) {
00576 for ( unsigned dir = 0; dir < 4; ++dir ) {
00577 if ( node(index).link[dir] != vertex_node::null_index ) {
00578 unsigned nbr = node(index).link[dir];
00579 unsigned back_dir = node(index).back_dir[dir];
00580 if ( node(nbr).link[back_dir] != index ) {
00581 vcl_cerr << "Bad back link on vertex " << index << " ("<<node(index).i
00582 << ',' << node(index).j << " in dir " << dir << '\n'
00583 << " link " << dir << " = " << node(index).link[dir] << ";\n"
00584 << " back_dir " << dir << " = " << node(index).back_dir[dir] << '\n';
00585 }
00586 }
00587 }
00588 assert( good );
00589 }
00590 #endif
00591 }
00592
00593
00594
00595
00596
00597 template< typename LABEL_TYPE >
00598 bool
00599 vtol_extract_topology< LABEL_TYPE >::
00600 trace_face_boundary( vcl_vector<unsigned>& markers,
00601 unsigned index,
00602 unsigned dir,
00603 region_type& chain_list,
00604 LabelPoint& region_label ) const
00605 {
00606 unsigned start_index = index;
00607 LabelPoint start_left;
00608 edge_labels( node(index).i, node(index).j, dir,
00609 start_left, region_label );
00610
00611 #ifdef DEBUG
00612 vcl_cout << "start left, region label: " << (int) start_left << ' '
00613 << (int)region_label << " ; i,j: " << node(index).i << ' '
00614 << node(index).j << " ; index,dir " << index << ' '
00615 << dir << " ; label(i,j) = "
00616 << (int)label_img_(node(index).i, node(index).j) << vcl_endl;
00617 if ( region_label + 1 == min_label_ ) {
00618 vcl_cout << "exiting" << vcl_endl;
00619 return false;
00620 }
00621 #endif
00622 if (!region_label.valid) {
00623 return false;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 static const int delta_i[4] = { 0, -1, -1, 0 };
00633 static const int delta_j[4] = { 0, 0, -1, -1 };
00634 chain_list.i = node(index).i + delta_i[dir];
00635 chain_list.j = node(index).j + delta_j[dir];
00636
00637 #ifdef DEBUG
00638 vcl_cout << "index " << index << " dir " << dir << " node " << node(index).i
00639 << " delta " << delta_i[dir] << vcl_endl;
00640 #endif
00641 assert( chain_list.i < label_img_.ni() );
00642 assert( chain_list.j < label_img_.nj() );
00643
00644 do {
00645
00646
00647
00648 assert( ! is_marked( markers[index], dir ) );
00649 set_mark( markers[index], dir );
00650 chain_list.push_back( node(index).edgel_chain[dir] );
00651
00652 unsigned back_dir = node(index).back_dir[ dir ];
00653 index = node(index).link[ dir ];
00654 assert( index != vertex_node::null_index );
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 unsigned i = node(index).i;
00672 unsigned j = node(index).j;
00673 LabelPoint left, right;
00674 dir = back_dir;
00675 DBG( unsigned old_dir = dir % 4 );
00676 do {
00677 dir = (dir+3) % 4;
00678
00679
00680 DBG( assert( dir != old_dir ) );
00681
00682 edge_labels( i, j, dir, left, right );
00683 } while ( left == right || right != region_label );
00684
00685 } while ( index != start_index );
00686
00687 return true;
00688 }
00689
00690
00691
00692
00693
00694 template< typename LABEL_TYPE >
00695 void
00696 vtol_extract_topology< LABEL_TYPE >::
00697 collect_regions( region_collection& region_list ) const
00698 {
00699
00700
00701
00702 vcl_vector< unsigned > markers( node_list_.size(), 0 );
00703
00704 region_list.resize( max_label_ - min_label_ + 1 );
00705
00706
00707
00708 for ( unsigned i = 0; i < node_list_.size(); ++i ) {
00709 for ( unsigned dir = 0; dir < 4; ++dir ) {
00710 if ( ! is_marked( markers[i], dir ) &&
00711 node(i).link[dir] != vertex_node::null_index ) {
00712 region_type_sptr chain = new region_type;
00713 LabelPoint label;
00714 if ( trace_face_boundary( markers, i, dir, *chain, label ) ) {
00715 assert( (label.valid) && (label.label >= min_label_) );
00716 region_list[ label.label - min_label_ ].push_back( chain );
00717 }
00718 }
00719 }
00720 }
00721
00722 #ifndef NDEBUG
00723
00724
00725
00726
00727
00728 for ( unsigned i = 0; i < node_list_.size(); ++i ) {
00729 for ( unsigned dir = 0; dir < 4; ++dir ) {
00730 assert( node(i).link[dir] == vertex_node::null_index ||
00731 ( dir==0 && node(i).j==label_img_.nj() ) ||
00732 ( dir==1 && node(i).i==0 ) ||
00733 ( dir==2 && node(i).j==0 ) ||
00734 ( dir==3 && node(i).i==label_img_.ni() ) ||
00735 is_marked( markers[i], dir ) );
00736 }
00737 }
00738 #endif
00739 }
00740
00741
00742
00743
00744
00745 template< typename T >
00746 void
00747 vtol_extract_topology<T>::
00748 compute_faces( vcl_vector< region_type_sptr > const& chains,
00749 vcl_vector< vtol_intensity_face_sptr >& faces,
00750 data_image_type const* data_img ) const
00751 {
00752 assert( chains.size() > 0 );
00753
00754
00755
00756
00757
00758 chain_tree_node universe( 0 );
00759 for ( unsigned i = 0; i < chains.size(); ++i ) {
00760 universe.add( chains[i] );
00761 }
00762
00763
00764
00765
00766 if ( data_img ) {
00767 finder_type* finder = new finder_type( label_img_, vil_region_finder_4_conn );
00768 add_faces( faces, finder, data_img, &universe );
00769 delete finder;
00770 }
00771 else {
00772 add_faces( faces, 0, 0, &universe );
00773 }
00774 }
00775
00776
00777
00778
00779 template <typename T>
00780 void
00781 vtol_extract_topology<T>::
00782 add_faces( vcl_vector<vtol_intensity_face_sptr>& faces,
00783 typename vtol_extract_topology<T>::finder_type* find,
00784 data_image_type const* img,
00785 typename vtol_extract_topology<T>::chain_tree_node* node,
00786 bool even_level ) const
00787 {
00788 if ( even_level ) {
00789 faces.push_back( node->make_face( find, img ) );
00790 }
00791 for ( unsigned i = 0; i < node->children.size(); ++i ) {
00792 add_faces( faces, find, img, node->children[i], !even_level );
00793 }
00794 }
00795
00796
00797
00798
00799
00800 template <typename T>
00801 bool
00802 vtol_extract_topology<T>::
00803 contains( region_type_sptr a, region_type_sptr b )
00804 {
00805 assert( b );
00806 if ( !a ) {
00807 return true;
00808 }
00809 else {
00810
00811
00812 unsigned num_crossings = 0;
00813 for ( unsigned i = 0; i < a->size(); ++i ) {
00814 num_crossings += num_crosses_x_pos_ray( b->i, b->j, *(*a)[i] );
00815 }
00816 return ( num_crossings % 2 ) == 1;
00817 }
00818 }
00819
00820
00821
00822
00823
00824 template <typename T>
00825 unsigned
00826 vtol_extract_topology<T>::
00827 num_crosses_x_pos_ray( double x, double y, vdgl_edgel_chain const& chain )
00828 {
00829 if ( chain.size() < 2 )
00830 return 0;
00831
00832
00833
00834
00835
00836 unsigned count = 0;
00837 for ( unsigned int i = 0; i+1 < chain.size(); ++i ) {
00838 vdgl_edgel const* e0 = &chain[i];
00839 vdgl_edgel const* e1 = &chain[i+1];
00840 assert( e0->y() != y && e1->y() != y );
00841 if ( ( e0->y() < y && y < e1->y() ) ||
00842 ( e1->y() < y && y < e0->y() ) ) {
00843 assert( e0->x() == e1->x() );
00844 assert( e0->x() != x );
00845 if ( e0->x() > x ) {
00846 ++count;
00847 }
00848 }
00849 }
00850
00851 return count;
00852 }
00853
00854
00855
00856
00857
00858 template <typename T>
00859 vdgl_edgel_chain_sptr
00860 vtol_extract_topology<T>::
00861 smooth_chain( vdgl_edgel_chain_sptr chain,
00862 unsigned int num_pts ) const
00863 {
00864
00865 if ( num_pts > chain->size() ) {
00866 num_pts = chain->size();
00867 }
00868
00869
00870 if ( num_pts < 2)
00871 return chain;
00872
00873 vdgl_edgel_chain_sptr new_chain = new vdgl_edgel_chain;
00874
00875 vgl_line_2d_regression<double> reg;
00876
00877
00878
00879
00880 unsigned fit_start;
00881 unsigned fit_end;
00882
00883
00884
00885 unsigned curr_ind = 0;
00886
00887 vgl_point_2d<double> pt1, pt2;
00888 vgl_vector_2d<double> dir;
00889 double slope;
00890
00891
00892
00893
00894
00895
00896
00897 for ( fit_end = 1; fit_end < num_pts; ++fit_end ) {
00898 reg.increment_partial_sums( chain->edgel(fit_end).x(),
00899 chain->edgel(fit_end).y() );
00900 }
00901 assert( reg.get_n_pts() + 1 == num_pts );
00902 if ( !reg.fit_constrained( chain->edgel(0).x(), chain->edgel(0).y() ) ) {
00903 vcl_cerr << "line fit failed at start\n";
00904 }
00905
00906
00907
00908
00909 reg.get_line().get_two_points( pt1, pt2 );
00910 dir = reg.get_line().direction();
00911 slope = reg.get_line().slope_degrees();
00912 for ( ; curr_ind < (fit_end+1)/2; ++curr_ind ) {
00913 pt2.set( chain->edgel(curr_ind).x(), chain->edgel(curr_ind).y() );
00914 pt2 = pt1 + dot_product( pt2-pt1, dir ) * dir;
00915 new_chain->add_edgel( vdgl_edgel( pt2.x(), pt2.y(), -1, slope ) );
00916 }
00917
00918
00919
00920 fit_start = 1;
00921
00922 while ( fit_end + 1 < chain->size() ) {
00923
00924
00925 reg.increment_partial_sums( chain->edgel(fit_end).x(),
00926 chain->edgel(fit_end).y() );
00927 ++fit_end;
00928
00929 assert( reg.get_n_pts() == num_pts );
00930
00931
00932
00933 if ( !reg.fit() ) {
00934 vcl_cerr << "line fit failed at " << fit_start << '-' << fit_end << '\n';
00935 }
00936
00937
00938
00939 reg.get_line().get_two_points( pt1, pt2 );
00940 dir = reg.get_line().direction();
00941 slope = reg.get_line().slope_degrees();
00942 pt2.set( chain->edgel(curr_ind).x(), chain->edgel(curr_ind).y() );
00943 pt2 = pt1 + dot_product( pt2-pt1, dir ) * dir;
00944 new_chain->add_edgel( vdgl_edgel( pt2.x(), pt2.y(), -1, slope ) );
00945 ++curr_ind;
00946
00947
00948
00949 reg.decrement_partial_sums( chain->edgel(fit_start).x(),
00950 chain->edgel(fit_start).y() );
00951 ++fit_start;
00952 }
00953
00954 assert( reg.get_n_pts() + 1 == num_pts );
00955
00956
00957
00958
00959
00960
00961
00962 if ( num_pts == chain->size() ) {
00963 assert( fit_end == chain->size() );
00964 assert( fit_start == 1 );
00965 --fit_end;
00966 reg.decrement_partial_sums( chain->edgel(fit_end).x(),
00967 chain->edgel(fit_end).y() );
00968 reg.increment_partial_sums( chain->edgel(0).x(),
00969 chain->edgel(0).y() );
00970 }
00971
00972
00973
00974
00975
00976 if ( !reg.fit_constrained( chain->edgel(fit_end).x(),
00977 chain->edgel(fit_end).y() ) ) {
00978 vcl_cerr << "line fit failed at end\n";
00979 }
00980
00981 dir = reg.get_line().direction();
00982 reg.get_line().get_two_points( pt1, pt2 );
00983 slope = reg.get_line().slope_degrees();
00984 for ( ; curr_ind <= fit_end; ++curr_ind ) {
00985 pt2.set( chain->edgel(curr_ind).x(), chain->edgel(curr_ind).y() );
00986 pt2 = pt1 + dot_product( pt2-pt1, dir )*dir;
00987 new_chain->add_edgel( vdgl_edgel( pt2.x(), pt2.y(), -1, slope ) );
00988 }
00989
00990 return new_chain;
00991 }
00992
00993 #endif // vtol_extract_topology_txx_