23 #include <utility/LexicographicalIterator.hh>
24 #include <utility/FixedSizeLexicographicalIterator.hh>
25 #include <utility/FixedSizeLexicographicalIterator.tmpl.hh>
28 #include <utility/vector1.hh>
40 numeric::geometry::hashing::SixDCoordinateBinner
const & binner,
41 numeric::geometry::hashing::Bin6D & next_bin
61 assert( bin_width > 0 );
69 assert( bin_width_degrees > 0 );
77 for (
Size ii = 1; ii <= 3; ++ii ) {
78 assert( bin_widths( ii ) > 0 );
88 for (
Size ii = 1; ii <= 3; ++ii ) {
89 assert( euler_bin_widths( ii ) > 0 );
113 for (
Size ii = 1; ii <= 3; ++ii ) { half_xyzbin_widths[ ii ] *= 0.5; }
118 utility::LexicographicalIterator lex( six_twos );
129 while ( ! lex.at_end() ) {
131 for (
Size ii = 1; ii <= 3; ++ii ) {
132 xyz_lower( ii ) =
bb_.lower()( ii ) + ( lex[ ii ] - 1 ) * ( half_xyzbin_widths[ ii ] );
134 for (
Size ii = 1, iip3 = 4; ii <= 3; ++ii, ++iip3 ) {
135 euler_offsets[ ii ] = ( lex[ iip3 ] - 1 );
146 hit_hashes_[ count ].first =
new numeric::geometry::hashing::SixDCoordinateBinner( bb, euler_offsets, bin_widths );
156 runtime_assert( hit );
158 Vector point(
Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
159 if ( !
bb_.contains( point ) ) {
160 utility_exit_with_message(
"ERROR: Attempted to insert hit into HitHasher outside of the HitHasher bounding box!" );
165 boost::uint64_t bin_index =
hit_hashes_[ ii ].first->bin_index( geom );
166 HitHash::iterator iter =
hit_hashes_[ ii ].second.find( bin_index );
177 ms[ geometric_constraint_id ].push_back( hit );
178 hit_hashes_[ ii ].second.insert( std::make_pair( bin_index, ms ));
180 iter->second[ geometric_constraint_id ].push_back( hit );
192 runtime_assert( hit );
194 Vector point(
Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
195 if ( !
bb_.contains( point ) ) {
196 std::cerr <<
"Weird: Attempted to insert hit into HitHasher outside of the HitHasher bounding box!" << std::endl;
197 std::cerr <<
"point: " << point.x() <<
" " << point.y() <<
" " << point.z() << std::endl;
198 std::cerr <<
"bb: lower "<<
bb_.lower().x() <<
" " <<
bb_.lower().y() <<
" " <<
bb_.lower().z() << std::endl;
199 std::cerr <<
"bb: upper "<<
bb_.upper().x() <<
" " <<
bb_.upper().y() <<
" " <<
bb_.upper().z() << std::endl;
204 if (
hit_hashes_[ which_hash_map ].first->contains( geom ) ) {
205 boost::uint64_t bin_index =
hit_hashes_[ which_hash_map ].first->bin_index( geom );
206 HitHash::iterator iter =
hit_hashes_[ which_hash_map ].second.find( bin_index );
207 if ( iter ==
hit_hashes_[ which_hash_map ].second.end() ) {
217 ms[ geometric_constraint_id ].push_back( hit );
218 hit_hashes_[ which_hash_map ].second.insert( std::make_pair( bin_index, ms ));
220 iter->second[ geometric_constraint_id ].push_back( hit );
231 HitHasher::HitHash::const_iterator
234 return hit_hashes_[ which_hash_map ].second.begin();
237 HitHasher::HitHash::const_iterator
260 assert( bin_width > 0 );
268 assert( bin_width_degrees > 0 );
276 for (
Size ii = 1; ii <= 3; ++ii ) {
277 assert( bin_widths( ii ) > 0 );
287 for (
Size ii = 1; ii <= 3; ++ii ) {
288 assert( euler_bin_widths( ii ) > 0 );
299 for ( std::list< Hit >::const_iterator iter = hitlist.begin(), iter_end = hitlist.end(); iter != iter_end; ++iter ) {
301 all_hits_.push_back( std::make_pair( count_hits, & ( *iter ) ));
318 Size3 euler_offsets( 0 );
324 binner_ =
new numeric::geometry::hashing::SixDCoordinateBinner(
bb_, euler_offsets, bin_widths );
337 utility::FixedSizeLexicographicalIterator< 6 > halfbin_lex( twos );
339 for (
Size ii = 5; ii >= 1; --ii ) twopows[ ii ] = twopows[ ii + 1 ] * 2;
346 for ( HitHash::const_iterator iter =
hash_.begin(), iter_end =
hash_.end(); iter != iter_end; ++iter ) {
348 if ( hitlist.empty() )
continue;
349 std::fill( visited_halfbins.begin(), visited_halfbins.end(), false );
350 Size first_hit_index = hitlist.begin()->first;
356 for ( HitIndexList::const_iterator
357 hitlist_iter = hitlist.begin(), hitlist_iter_end = hitlist.end();
358 hitlist_iter != hitlist_iter_end; ++hitlist_iter ) {
359 if ( ds.ds_find( first_hit_index ) == ds.ds_find( hitlist_iter->first ))
continue;
360 ds.ds_union( first_hit_index, hitlist_iter->first );
365 for ( HitIndexList::const_iterator
366 hitlist_iter = hitlist.begin(), hitlist_iter_end = hitlist.end();
367 hitlist_iter != hitlist_iter_end; ++hitlist_iter ) {
368 Size query_id = hitlist_iter->first;
369 Hit const * query_hit = hitlist_iter->
second;
371 Size query_halfbin_index = 1;
372 for (
Size ii = 1; ii <= 6; ++ii )
if ( query_halfbin[ ii ] == 1 ) query_halfbin_index += twopows[ ii ];
375 if ( visited_halfbins[ query_halfbin_index ] )
continue;
376 visited_halfbins[ query_halfbin_index ] =
true;
379 for (
Size ii = 1; ii <= 6; ++ii ) {
380 if ( query_halfbin[ ii ] == 0 ) halfsteps[ ii ] *= -1;
384 while ( !halfbin_lex.at_end() ) {
387 if ( skip_pos != 0 ) {
388 halfbin_lex.continue_at_dimension( skip_pos );
393 boost::uint64_t nbindex =
binner_->bin_index( nbbin );
394 HitHash::const_iterator nbr_hits =
hash_.find( nbindex );
396 if ( nbr_hits !=
hash_.end() ) {
398 for ( HitIndexList::const_iterator nbr_hits_iter = nbr_hits->second.begin(),
399 nbr_hits_iter_end = nbr_hits->second.end();
400 nbr_hits_iter != nbr_hits_iter_end; ++nbr_hits_iter ) {
401 Size nbr_id = nbr_hits_iter->first;
402 if ( ds.ds_find( query_id ) == ds.ds_find( nbr_id ) )
continue;
403 Bin6D nb_halfbin =
binner_->halfbin6( nbr_hits_iter->second->second() );
404 if (
within_reach( query_halfbin, nb_halfbin, nbbin, halfbin_lex )) {
405 ds.ds_union( query_id, nbr_id );
440 boost::uint64_t nbindex = binner_->bin_index( nbbin );
441 HitHash::const_iterator nbr_hits = hash_.find( nbindex );
443 if ( nbr_hits != hash_.end() ) {
444 // we have hits in the neighbor bin
445 for ( HitIndexList::const_iterator nbr_hits_iter = nbr_hits->second.begin(),
446 nbr_hits_iter_end = nbr_hits->second.end();
447 nbr_hits_iter != nbr_hits_iter_end; ++nbr_hits_iter ) {
448 Size nbr_id = nbr_hits_iter->first;
449 if ( ds.ds_find( query_id ) == ds.ds_find( nbr_id ) ) continue; // already neighbors
450 Bin6D nb_halfbin = binner_->halfbin6( nbr_hits_iter->second->second() );
451 if ( within_reach( query_halfbin, nb_halfbin, nbbin, halfbin_lex )) {
452 ds.ds_union( query_id, nbr_id ); // mark these hits as neighbors
458 } // end while ( !halfbin_lex.at_end() )
464 Size const nccs = ds.n_disjoint_sets();
467 for (
Size ii = 1; ii <= ds.n_nodes(); ++ii ) {
468 if ( ds.ds_find( ii ) == ii ) {
470 ds_representatives_to_setnos[ ii ] = count_set;
475 for (HitIndexList::const_iterator iter =
all_hits_.begin(), iter_end =
all_hits_.end();
476 iter != iter_end; ++iter ) {
477 Size iterrep = ds.ds_find( iter->first );
478 Size setid = ds_representatives_to_setnos[ iterrep ];
479 assert( setid != 0 );
480 hit_ccs[ setid ].push_back( iter->second );
492 std::set< Size > neighbor_set;
493 std::set< boost::uint64_t > exhausted_bins;
497 utility::FixedSizeLexicographicalIterator< 6 > halfbin_lex( twos );
499 for ( HitPtrList::const_iterator iter = queryhits.begin(), iter_end = queryhits.end();
500 iter != iter_end; ++iter ) {
502 Hit const * query_hit = *iter;
506 for (
Size ii = 1; ii <= 6; ++ii ) {
507 if ( query_halfbin[ ii ] == 0 ) halfsteps[ ii ] *= -1;
511 while ( !halfbin_lex.at_end() ) {
514 if ( skip_pos != 0 ) {
515 halfbin_lex.continue_at_dimension( skip_pos );
520 boost::uint64_t nbindex =
binner_->bin_index( nbbin );
521 HitHash::const_iterator nbr_hits =
hash_.find( nbindex );
523 if ( exhausted_bins.find( nbindex ) != exhausted_bins.end() ) { ++halfbin_lex;
continue; }
525 if ( nbr_hits !=
hash_.end() ) {
527 bool all_inserted =
true;
528 for ( HitIndexList::const_iterator nbr_hits_iter = nbr_hits->second.begin(),
529 nbr_hits_iter_end = nbr_hits->second.end();
530 nbr_hits_iter != nbr_hits_iter_end; ++nbr_hits_iter ) {
531 Size nbr_id = nbr_hits_iter->first;
532 if ( neighbor_set.find( nbr_id ) != neighbor_set.end() ) {
538 Bin6D nb_halfbin =
binner_->halfbin6( nbr_hits_iter->second->second() );
539 if (
within_reach( query_halfbin, nb_halfbin, nbbin, halfbin_lex )) {
540 neighbor_set.insert( nbr_id );
541 neighbors.push_back( nbr_hits_iter->second );
543 all_inserted =
false;
546 if ( all_inserted ) {
548 exhausted_bins.insert( nbindex );
552 exhausted_bins.insert( nbindex );
565 for ( HitIndexList::const_iterator iter =
all_hits_.begin(), iter_end =
all_hits_.end();
566 iter != iter_end; ++iter ) {
567 boost::uint64_t bin_index =
binner_->bin_index( iter->second->second() );
568 HitHash::iterator hash_iter =
hash_.find( bin_index );
569 if ( hash_iter ==
hash_.end() ) {
571 hitlist.push_back( *iter );
572 hash_[ bin_index ] = hitlist;
574 hash_iter->second.push_back( *iter );
588 utility::FixedSizeLexicographicalIterator< 6 >
const & halfbin_lex,
593 for (
Size ii = 1; ii <= 6; ++ii ) {
594 if ( halfbin_lex[ ii ] == 2 ) steps[ ii ] = offsets[ ii ];
603 Bin6D const & query_halfbin,
604 Bin6D const & nb_halfbin,
606 utility::FixedSizeLexicographicalIterator< 6 >
const & halfbin_lex
609 Size const NEIGHBOR_BIN = 2;
612 for (
Size ii = 1; ii <= 5; ++ii ) {
613 if ( halfbin_lex[ ii ] == NEIGHBOR_BIN && query_halfbin[ ii ] == nb_halfbin[ ii ] )
624 if ( halfbin_lex[ 6 ] == NEIGHBOR_BIN ) {
625 if ( nbbin[ 6 ] == 0 || nbbin[ 6 ] + 1 ==
binner_->dimsizes()[ 6 ] ) {
627 if ( query_halfbin[ 6 ] != nb_halfbin[ 6 ] ) {
632 if ( query_halfbin[ 6 ] == nb_halfbin[ 6 ] ) {
666 assert( bin_width > 0 );
674 assert( bin_width_degrees > 0 );
682 for (
Size ii = 1; ii <= 3; ++ii ) {
683 assert( bin_widths( ii ) > 0 );
693 for (
Size ii = 1; ii <= 3; ++ii ) {
694 assert( euler_bin_widths( ii ) > 0 );
703 for ( std::list< Hit >::const_iterator iter = hitlist.begin(), iter_end = hitlist.end(); iter != iter_end; ++iter ) {
704 boost::uint64_t bin_index =
binner_->bin_index( iter->second() );
705 HitHash::iterator hash_iter =
hash_.find( bin_index );
706 if ( hash_iter ==
hash_.end() ) {
709 std::fill( hitcount_v.begin(), hitcount_v.end(), 0 );
710 hitcount_v[ geomcst_id ] = 1;
712 hash_iter->second[ geomcst_id ] += 1;
721 for ( std::list< Hit const * >::const_iterator iter = hitlist.begin(), iter_end = hitlist.end(); iter != iter_end; ++iter ) {
722 boost::uint64_t bin_index =
binner_->bin_index( (*iter)->second() );
723 HitHash::iterator hash_iter =
hash_.find( bin_index );
724 if ( hash_iter ==
hash_.end() ) {
727 std::fill( hitcount_v.begin(), hitcount_v.end(), 0 );
728 hitcount_v[ geomcst_id ] = 1;
730 hash_iter->second[ geomcst_id ] += 1;
744 Size3 euler_offsets( 0 );
750 for (
Size ii = 1; ii <=6; ++ii ) bin_widths[ ii ] *= 0.5;
752 binner_ =
new numeric::geometry::hashing::SixDCoordinateBinner(
bb_, euler_offsets, bin_widths );
761 Size const two_billion = 2000000000;
762 Real const ln2e9 = 21.4;
764 Size const three_to_the_sixth = 729;
768 for (
Size ii = 1; ii <= three_to_the_sixth; ++ii ) {
769 neighbor_bin_hit_counts[ ii ].resize(
n_geom_csts_, 0 );
770 log_neighbor_bin_hit_counts[ ii ].resize(
n_geom_csts_, 0 );
774 utility::LexicographicalIterator lex( seventwentynines );
777 utility::FixedSizeLexicographicalIterator< 6 > neighbor_halfbin_lex( threes ), geomcst2_lex( threes ), comp_lex( threes );
788 Size grand_total = 0;
789 Size last_grand_total = 0;
790 for ( HitHash::const_iterator iter =
hash_.begin(), iter_end =
hash_.end(); iter != iter_end; ++iter ) {
791 for (
Size ii = 1; ii <= three_to_the_sixth; ++ii ) std::fill( neighbor_bin_hit_counts[ ii ].begin(), neighbor_bin_hit_counts[ ii ].end(), 0 );
793 HitCounts const & center_hits = iter->second;
794 Size const halfbin_center_first_geom_cst_nhits = center_hits[ 1 ];
796 if ( halfbin_center_first_geom_cst_nhits == 0 )
continue;
798 Real const log_halfbin_center_first_geom_cst_nhits = std::log( (
double) halfbin_center_first_geom_cst_nhits );
799 boost::uint64_t bin_index = iter->first;
804 neighbor_halfbin_lex.begin();
805 while ( ! neighbor_halfbin_lex.at_end() ) {
808 for (
Size ii = 1; ii <= 6; ++ii ) {
809 if ( neighbor_halfbin_lex[ ii ] == 1 ) steps[ ii ] = -1 *
binner_->bin_widths()[ ii ];
810 else if ( neighbor_halfbin_lex[ ii ] == 3 ) steps[ ii ] =
binner_->bin_widths()[ ii ];
813 if ( oo_bounds_dim != 0 ) {
815 neighbor_halfbin_lex.continue_at_dimension( oo_bounds_dim );
818 boost::uint64_t neighbor_bin_index =
binner_->bin_index( neighbor_bin );
819 HitHash::const_iterator nbr_hits =
hash_.find( neighbor_bin_index );
820 if ( nbr_hits !=
hash_.end() ) {
821 Size const neighbor_halfbin_lex_index = neighbor_halfbin_lex.index();
822 neighbor_bin_hit_counts[ neighbor_halfbin_lex_index ] = nbr_hits->second;
824 if ( neighbor_bin_hit_counts[ neighbor_halfbin_lex_index ][ ii ] > 1 ) {
826 log_neighbor_bin_hit_counts[ neighbor_halfbin_lex_index ][ ii ] =
827 std::log( (
double) (neighbor_bin_hit_counts[ neighbor_halfbin_lex_index ][ ii ]) );
831 ++neighbor_halfbin_lex;
841 while ( ! lex.at_end() ) {
842 Size this_combo_n_hits = halfbin_center_first_geom_cst_nhits;
843 Real this_combo_log_n_hits = log_halfbin_center_first_geom_cst_nhits;
847 if ( geomcst2_lex.index() != lex[ 1 ] ) geomcst2_lex.set_position_from_index( lex[ 1 ] );
849 for (
Size ii = 1; ii <= 6; ++ii ) outer_corner[ ii ] = geomcst2_lex[ ii ];
850 bool out_of_range =
false;
852 comp_lex.set_position_from_index( lex[ ii-1 ] );
853 for (
Size jj = 1; jj <= 6; ++jj ) {
855 if ( comp_lex[ jj ] == 2 )
continue;
856 if ( outer_corner[ jj ] == 2 ) { outer_corner[ jj ] = comp_lex[ jj ];
continue; }
857 if ( comp_lex[ jj ] == outer_corner[ jj ] )
continue;
860 lex.continue_at_dimension( ii-1 );
863 if ( out_of_range )
break;
865 if ( out_of_range )
continue;
869 this_combo_n_hits *= neighbor_bin_hit_counts[ lex[ ii-1 ] ][ ii ];
870 this_combo_log_n_hits += log_neighbor_bin_hit_counts[ lex[ ii-1 ] ][ ii ];
871 if ( this_combo_n_hits == 0 ) {
872 lex.continue_at_dimension( ii-1 );
876 if ( this_combo_n_hits == 0 )
continue;
878 if ( this_combo_log_n_hits > ln2e9 ) {
return two_billion; }
879 total += this_combo_n_hits;
880 if ( total < last_total ) {
return two_billion; }
886 grand_total += total;
887 if ( grand_total < last_grand_total ) {
return two_billion; }
888 last_grand_total = grand_total;
902 numeric::geometry::hashing::SixDCoordinateBinner
const & binner,
903 numeric::geometry::hashing::Bin6D & next_bin
906 using namespace core;
911 for (
Size ii = 1; ii <= 3; ++ii ) {
912 alt_point[ ii ] += steps[ ii ];
913 euler_offsets[ ii ] = steps[ ii + 3 ];
914 orig_euler[ ii ] = orig_point[ ii + 3 ];
918 for (
Size ii = 1; ii <= 3; ++ii ) {
919 if ( binner.bounding_box().lower()( ii ) > alt_point[ ii ] ||
920 binner.bounding_box().upper()( ii ) < alt_point[ ii ] ) {
928 for (
Size ii = 1; ii <= 3; ++ii ) {
929 alt_point[ ii + 3 ] = new_euler[ ii ];
932 next_bin = binner.bin6( alt_point );
951 for (
Size ii = 1; ii <= 3; ++ii ) new_euler_angles[ ii ] += offsets[ ii ];
953 if ( new_euler_angles[ 3 ] < 0 || new_euler_angles[ 3 ] > 180 ) {
955 if ( new_euler_angles[ 3 ] < 0 ) {
956 new_euler_angles[ 3 ] *= -1.0;
958 assert( new_euler_angles[ 3 ] < 360 );
959 new_euler_angles[ 3 ] = 360 - new_euler_angles[ 3 ];
962 for (
Size ii = 1; ii <=2; ++ii ) {
963 if ( new_euler_angles[ ii ] < 180 ) {
964 new_euler_angles[ ii ] += 180;
966 new_euler_angles[ ii ] -= 180;
971 for (
Size ii = 1; ii <= 2; ++ii ) {
972 if ( new_euler_angles[ ii ] > 360 ) {
973 new_euler_angles[ ii ] -= 360;
974 }
else if ( new_euler_angles[ ii ] < 0 ) {
975 new_euler_angles[ ii ] += 360;
983 return new_euler_angles;
994 MatchHash::const_iterator iter =
hash_.find( m );
995 if ( iter ==
hash_.end() ) {
996 hash_.insert( std::make_pair( m,
true ) );