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