Changeset 23c605 for src/Fragmentation
- Timestamp:
- Aug 20, 2014, 1:06:16 PM (11 years ago)
- Children:
- 1cde4e8
- Parents:
- 1ae9aa
- git-author:
- Frederik Heber <heber@…> (06/30/14 09:35:42)
- git-committer:
- Frederik Heber <heber@…> (08/20/14 13:06:16)
- Location:
- src/Fragmentation/Exporters
- Files:
-
- 4 edited
-
SphericalPointDistribution.cpp (modified) (15 diffs)
-
SphericalPointDistribution.hpp (modified) (4 diffs)
-
unittests/SphericalPointDistributionUnitTest.cpp (modified) (1 diff)
-
unittests/SphericalPointDistributionUnitTest.hpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
r1ae9aa r23c605 49 49 #include <limits> 50 50 #include <list> 51 #include <numeric> 51 52 #include <vector> 52 53 #include <map> … … 59 60 // static entities 60 61 const double SphericalPointDistribution::warn_amplitude = 1e-2; 62 const double SphericalPointDistribution::L1THRESHOLD = 1e-2; 63 const double SphericalPointDistribution::L2THRESHOLD = 2e-1; 61 64 62 65 typedef std::vector<double> DistanceArray_t; … … 64 67 // class generator: taken from www.cplusplus.com example std::generate 65 68 struct c_unique { 66 int current;69 unsigned int current; 67 70 c_unique() {current=0;} 68 int operator()() {return current++;}71 unsigned int operator()() {return current++;} 69 72 } UniqueNumber; 70 73 71 inline 72 DistanceArray_t calculatePairwiseDistances( 73 const std::vector<Vector> &_points, 74 const SphericalPointDistribution::IndexList_t &_indices 75 ) 76 { 77 DistanceArray_t result; 78 for (SphericalPointDistribution::IndexList_t::const_iterator firstiter = _indices.begin(); 79 firstiter != _indices.end(); ++firstiter) { 80 for (SphericalPointDistribution::IndexList_t::const_iterator seconditer = firstiter; 81 seconditer != _indices.end(); ++seconditer) { 82 if (firstiter == seconditer) 83 continue; 84 const double distance = (_points[*firstiter] - _points[*seconditer]).NormSquared(); 85 result.push_back(distance); 86 } 87 } 88 return result; 89 } 74 struct c_unique_list { 75 unsigned int current; 76 c_unique_list() {current=0;} 77 std::list<unsigned int> operator()() {return std::list<unsigned int>(1, current++);} 78 } UniqueNumberList; 90 79 91 80 /** Calculate the center of a given set of points in \a _positions but only … … 107 96 108 97 return Center; 98 } 99 100 inline 101 DistanceArray_t calculatePairwiseDistances( 102 const SphericalPointDistribution::VectorArray_t &_points, 103 const SphericalPointDistribution::IndexTupleList_t &_indices 104 ) 105 { 106 DistanceArray_t result; 107 for (SphericalPointDistribution::IndexTupleList_t::const_iterator firstiter = _indices.begin(); 108 firstiter != _indices.end(); ++firstiter) { 109 110 // calculate first center from possible tuple of indices 111 Vector FirstCenter; 112 ASSERT(!firstiter->empty(), "calculatePairwiseDistances() - there is an empty tuple."); 113 if (firstiter->size() == 1) { 114 FirstCenter = _points[*firstiter->begin()]; 115 } else { 116 FirstCenter = calculateCenter( _points, *firstiter); 117 if (!FirstCenter.IsZero()) 118 FirstCenter.Normalize(); 119 } 120 121 for (SphericalPointDistribution::IndexTupleList_t::const_iterator seconditer = firstiter; 122 seconditer != _indices.end(); ++seconditer) { 123 if (firstiter == seconditer) 124 continue; 125 126 // calculate second center from possible tuple of indices 127 Vector SecondCenter; 128 ASSERT(!seconditer->empty(), "calculatePairwiseDistances() - there is an empty tuple."); 129 if (seconditer->size() == 1) { 130 SecondCenter = _points[*seconditer->begin()]; 131 } else { 132 SecondCenter = calculateCenter( _points, *seconditer); 133 if (!SecondCenter.IsZero()) 134 SecondCenter.Normalize(); 135 } 136 137 // calculate distance between both centers 138 double distance = 2.; // greatest distance on surface of sphere with radius 1. 139 if ((!FirstCenter.IsZero()) && (!SecondCenter.IsZero())) 140 distance = (FirstCenter - SecondCenter).NormSquared(); 141 result.push_back(distance); 142 } 143 } 144 return result; 109 145 } 110 146 … … 123 159 Vector dreiBein(_oldPosition); 124 160 dreiBein.VectorProduct(_RotationAxis); 161 ASSERT( !dreiBein.IsZero(), "determineSignOfRotation() - dreiBein is zero."); 125 162 dreiBein.Normalize(); 126 163 const double sign = 127 164 (dreiBein.ScalarProduct(_newPosition) < 0.) ? -1. : +1.; 128 165 LOG(6, "DEBUG: oldCenter on plane is " << _oldPosition 129 << ", newCenter in plane is " << _newPosition166 << ", newCenter on plane is " << _newPosition 130 167 << ", and dreiBein is " << dreiBein); 131 168 return sign; … … 166 203 */ 167 204 std::pair<double, double> SphericalPointDistribution::calculateErrorOfMatching( 168 const std::vector<Vector>&_old,169 const std::vector<Vector>&_new,170 const Index List_t &_Matching)205 const VectorArray_t &_old, 206 const VectorArray_t &_new, 207 const IndexTupleList_t &_Matching) 171 208 { 172 209 std::pair<double, double> errors( std::make_pair( 0., 0. ) ); 173 210 174 211 if (_Matching.size() > 1) { 175 LOG( 3, "INFO: Matching is " << _Matching);212 LOG(5, "INFO: Matching is " << _Matching); 176 213 177 214 // calculate all pair-wise distances 178 IndexList_t keys(_Matching.size()); 179 std::generate (keys.begin(), keys.end(), UniqueNumber); 215 IndexTupleList_t keys(_old.size(), IndexList_t() ); 216 std::generate (keys.begin(), keys.end(), UniqueNumberList); 217 180 218 const DistanceArray_t firstdistances = calculatePairwiseDistances(_old, keys); 181 219 const DistanceArray_t seconddistances = calculatePairwiseDistances(_new, _Matching); … … 187 225 for (;(firstiter != firstdistances.end()) && (seconditer != seconddistances.end()); 188 226 ++firstiter, ++seconditer) { 189 const double gap = *firstiter - *seconditer;227 const double gap = fabs(*firstiter - *seconditer); 190 228 // L1 error 191 229 if (errors.first < gap) … … 194 232 errors.second += gap*gap; 195 233 } 196 } else 197 ELOG(3, "calculateErrorOfMatching() - Given matching's size is less than 2."); 198 LOG(3, "INFO: Resulting errors for matching (L1, L2): " 234 } else { 235 // check whether we have any zero centers: Combining points on new sphere may result 236 // in zero centers 237 for (SphericalPointDistribution::IndexTupleList_t::const_iterator iter = _Matching.begin(); 238 iter != _Matching.end(); ++iter) { 239 if ((iter->size() != 1) && (calculateCenter( _new, *iter).IsZero())) { 240 errors.first = 2.; 241 errors.second = 2.; 242 } 243 } 244 } 245 LOG(4, "INFO: Resulting errors for matching (L1, L2): " 199 246 << errors.first << "," << errors.second << "."); 200 247 … … 232 279 * \param _matching current matching being build up 233 280 * \param _indices contains still available indices 281 * \param _remainingweights current weights to fill (each weight a place) 282 * \param _remainiter iterator over the weights, indicating the current position we match 234 283 * \param _matchingsize 235 284 */ 236 285 void SphericalPointDistribution::recurseMatchings( 237 286 MatchingControlStructure &_MCS, 238 Index List_t &_matching,287 IndexTupleList_t &_matching, 239 288 IndexList_t _indices, 240 unsigned int _matchingsize) 241 { 242 LOG(4, "DEBUG: Recursing with current matching " << _matching 289 WeightsArray_t &_remainingweights, 290 WeightsArray_t::iterator _remainiter, 291 const unsigned int _matchingsize 292 ) 293 { 294 LOG(5, "DEBUG: Recursing with current matching " << _matching 243 295 << ", remaining indices " << _indices 244 << ", and sought size " << _matching.size()+_matchingsize); 245 //!> threshold for L1 error below which matching is immediately acceptable 246 const double L1THRESHOLD = 1e-2; 296 << ", and remaining weights " << _matchingsize); 247 297 if (!_MCS.foundflag) { 248 LOG( 4, "DEBUG: Current matching has size " << _matching.size() << ", places left " << _matchingsize);298 LOG(5, "DEBUG: Current matching has size " << _matching.size() << ", places left " << _matchingsize); 249 299 if (_matchingsize > 0) { 250 300 // go through all indices 251 301 for (IndexList_t::iterator iter = _indices.begin(); 252 302 (iter != _indices.end()) && (!_MCS.foundflag);) { 303 // check whether we can stay in the current bin or have to move on to next one 304 if (*_remainiter == 0) { 305 // we need to move on 306 if (_remainiter != _remainingweights.end()) { 307 ++_remainiter; 308 } else { 309 // as we check _matchingsize > 0 this should be impossible 310 ASSERT( 0, "recurseMatchings() - we must not come to this position."); 311 } 312 } 313 // advance in matching to same position 314 const size_t OldIndex = std::distance(_remainingweights.begin(), _remainiter); 315 while (_matching.size() <= OldIndex) { // add empty lists of new bin is opened 316 LOG(6, "DEBUG: Extending _matching."); 317 _matching.push_back( IndexList_t() ); 318 } 319 IndexTupleList_t::iterator filliniter = _matching.begin(); 320 std::advance(filliniter, OldIndex); 253 321 // add index to matching 254 _matching.push_back(*iter); 255 LOG(5, "DEBUG: Adding " << *iter << " to matching."); 322 filliniter->push_back(*iter); 323 --(*_remainiter); 324 LOG(6, "DEBUG: Adding " << *iter << " to matching at " << OldIndex << "."); 256 325 // remove index but keep iterator to position (is the next to erase element) 257 326 IndexList_t::iterator backupiter = _indices.erase(iter); 258 327 // recurse with decreased _matchingsize 259 recurseMatchings(_MCS, _matching, _indices, _ matchingsize-1);328 recurseMatchings(_MCS, _matching, _indices, _remainingweights, _remainiter, _matchingsize-1); 260 329 // re-add chosen index and reset index to new position 261 _indices.insert(backupiter, _matching.back());330 _indices.insert(backupiter, filliniter->back()); 262 331 iter = backupiter; 263 332 // remove index from _matching to make space for the next one 264 _matching.pop_back(); 333 filliniter->pop_back(); 334 ++(*_remainiter); 265 335 } 266 336 // gone through all indices then exit recursion … … 268 338 _MCS.foundflag = true; 269 339 } else { 270 LOG( 3, "INFO: Found matching " << _matching);340 LOG(4, "INFO: Found matching " << _matching); 271 341 // calculate errors 272 342 std::pair<double, double> errors = calculateErrorOfMatching( … … 309 379 MCS.foundflag = false; 310 380 MCS.bestL2 = std::numeric_limits<double>::max(); 381 // transform lists into arrays 311 382 for (WeightedPolygon_t::const_iterator iter = _polygon.begin(); 312 iter != _polygon.end(); ++iter) 383 iter != _polygon.end(); ++iter) { 313 384 MCS.oldpoints.push_back(iter->first); 385 MCS.weights.push_back(iter->second); 386 } 314 387 MCS.newpoints.insert(MCS.newpoints.begin(), _newpolygon.begin(),_newpolygon.end() ); 315 388 … … 319 392 IndexList_t indices(_newpolygon.size()); 320 393 std::generate(indices.begin(), indices.end(), UniqueNumber); 321 Index List_t matching;394 IndexTupleList_t matching; 322 395 323 396 // walk through all matchings 324 const unsigned int matchingsize = _polygon.size(); 325 ASSERT( matchingsize <= indices.size(), 326 "SphericalPointDistribution::matchSphericalPointDistributions() - not enough new points to choose for matching to old ones."); 327 recurseMatchings(MCS, matching, indices, matchingsize); 397 WeightsArray_t remainingweights = MCS.weights; 398 unsigned int placesleft = std::accumulate(remainingweights.begin(), remainingweights.end(), 0); 399 recurseMatchings(MCS, matching, indices, remainingweights, remainingweights.begin(), placesleft); 400 } 401 if (MCS.foundflag) 402 LOG(3, "Found a best matching beneath L1 threshold of " << L1THRESHOLD); 403 else { 404 if (MCS.bestL2 < warn_amplitude) 405 LOG(3, "Picking matching is " << MCS.bestmatching << " with best L2 error of " 406 << MCS.bestL2); 407 else if (MCS.bestL2 < L2THRESHOLD) 408 ELOG(2, "Picking matching is " << MCS.bestmatching 409 << " with rather large L2 error of " << MCS.bestL2); 410 else 411 ASSERT(0, "findBestMatching() - matching "+toString(MCS.bestmatching) 412 +" has L2 error of "+toString(MCS.bestL2)+" that is too large."); 328 413 } 329 414 330 415 // combine multiple points and create simple IndexList from IndexTupleList 331 IndexTupleList_t bestmatching;332 for (IndexList_t::const_iterator iter = MCS.bestmatching.begin();333 iter != MCS.bestmatching.end(); ++iter)334 bestmatching.push_back(IndexList_t(1, *iter));335 416 const SphericalPointDistribution::IndexList_t IndexList = 336 joinPoints(_newpolygon, MCS.newpoints, bestmatching);417 joinPoints(_newpolygon, MCS.newpoints, MCS.bestmatching); 337 418 338 419 return IndexList; … … 363 444 Center.Normalize(); 364 445 _newpolygon.push_back(Center); 365 LOG(5, "DEBUG: Combining " << tupleiter->size() << " points to weighted center "446 LOG(5, "DEBUG: Combining " << tupleiter->size() << " points to weighted center " 366 447 << Center << " with new index " << UniqueIndex); 367 448 // mark for removal … … 600 681 iter != _polygon.end(); ++iter) 601 682 remainingold.push_back(iter->first); 602 VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end());603 683 LOG(2, "INFO: Matching old polygon " << _polygon 604 684 << " with new polygon " << _newpolygon); … … 613 693 IndexList_t bestmatching = findBestMatching(_polygon, _newpolygon); 614 694 LOG(2, "INFO: Best matching is " << bestmatching); 695 696 // _newpolygon has changed, so now convert to array 697 VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end()); 615 698 616 699 // determine rotation angles to align the two point distributions with -
src/Fragmentation/Exporters/SphericalPointDistribution.hpp
r1ae9aa r23c605 89 89 //!> precalculated value for root of 3 90 90 const double SQRT_3; 91 //!> threshold for L1 error below which matching is immediately acceptable 92 static const double L1THRESHOLD; 93 //!> threshold for L2 error below which matching is acceptable 94 static const double L2THRESHOLD; 91 95 92 96 //!> typedef for a full rotation specification consisting of axis and angle. … … 103 107 //!> typedef for a Vector of positions with weights 104 108 typedef std::vector< std::pair<Vector, int> > WeightedVectorArray_t; 109 //!> typedef for a vector of degrees (or integral weights) 110 typedef std::vector<unsigned int> WeightsArray_t; 105 111 106 112 //!> amplitude up to which deviations in checks of rotations are tolerated … … 112 118 113 119 static std::pair<double, double> calculateErrorOfMatching( 114 const std::vector<Vector>&_old,115 const std::vector<Vector>&_new,116 const Index List_t &_Matching);120 const VectorArray_t &_old, 121 const VectorArray_t &_new, 122 const IndexTupleList_t &_Matching); 117 123 118 124 static Polygon_t removeMatchingPoints( … … 124 130 bool foundflag; 125 131 double bestL2; 126 Index List_t bestmatching;132 IndexTupleList_t bestmatching; 127 133 VectorArray_t oldpoints; 128 134 VectorArray_t newpoints; 135 WeightsArray_t weights; 129 136 }; 130 137 131 138 static void recurseMatchings( 132 139 MatchingControlStructure &_MCS, 133 Index List_t &_matching,140 IndexTupleList_t &_matching, 134 141 IndexList_t _indices, 135 unsigned int _matchingsize); 142 WeightsArray_t &_remainingweights, 143 WeightsArray_t::iterator _remainiter, 144 const unsigned int _matchingsize 145 ); 136 146 137 147 static IndexList_t findBestMatching( -
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.cpp
r1ae9aa r23c605 638 638 } 639 639 640 /** UnitTest for matchSphericalPointDistributions() with four points and weights 641 * not all equal to one. 642 */ 643 void SphericalPointDistributionTest::matchSphericalPointDistributionsTest_multiple() 644 { 645 SphericalPointDistribution SPD(1.); 646 647 // test with four points: one point having weight of two 648 { 649 SphericalPointDistribution::WeightedPolygon_t polygon; 650 polygon += std::make_pair( Vector(1.,0.,0.), 2); 651 SphericalPointDistribution::Polygon_t newpolygon = 652 SPD.get<4>(); 653 SphericalPointDistribution::Polygon_t expected; 654 expected += Vector(-0.5773502691896,-5.551115123126e-17,0.8164965809277); 655 expected += Vector(-0.5773502691896,-5.551115123126e-17,-0.8164965809277); 656 SphericalPointDistribution::Polygon_t remaining = 657 SphericalPointDistribution::matchSphericalPointDistributions( 658 polygon, 659 newpolygon); 660 // std::cout << std::setprecision(13) << "Matched polygon is " << remaining << std::endl; 661 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 662 } 663 664 // test with five points: one point having weight of two 665 { 666 SphericalPointDistribution::WeightedPolygon_t polygon; 667 polygon += std::make_pair( Vector(1.,0.,0.), 2); 668 SphericalPointDistribution::Polygon_t newpolygon = 669 SPD.get<5>(); 670 SphericalPointDistribution::Polygon_t expected; 671 expected += Vector(-0.7071067811865,0.7071067811865,0); 672 expected += Vector(-0.3535533905933,-0.3535533905933,0.8660254037844); 673 expected += Vector(-0.3535533905933,-0.3535533905933,-0.8660254037844); 674 SphericalPointDistribution::Polygon_t remaining = 675 SphericalPointDistribution::matchSphericalPointDistributions( 676 polygon, 677 newpolygon); 678 // std::cout << std::setprecision(13) << "Matched polygon is " << remaining << std::endl; 679 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 680 } 681 682 683 // test with five points: one point having weight of two, one weight of one 684 { 685 SphericalPointDistribution::WeightedPolygon_t polygon; 686 polygon += std::make_pair( Vector(M_SQRT1_2,M_SQRT1_2,0.), 2); 687 polygon += std::make_pair( Vector(-1.,0.,0.), 1); 688 SphericalPointDistribution::Polygon_t newpolygon = 689 SPD.get<5>(); 690 SphericalPointDistribution::Polygon_t expected; 691 expected += Vector(0.3535533786708,-0.3535533955317,-0.8660254066357); 692 expected += Vector(0.3535534025157,-0.3535533856548,0.8660254009332); 693 SphericalPointDistribution::Polygon_t remaining = 694 SphericalPointDistribution::matchSphericalPointDistributions( 695 polygon, 696 newpolygon); 697 // std::cout << std::setprecision(13) << "Matched polygon is " << remaining << std::endl; 698 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 699 } 700 701 // test with six points: two points each having weight of two 702 { 703 SphericalPointDistribution::WeightedPolygon_t polygon; 704 polygon += std::make_pair( Vector(M_SQRT1_2,-M_SQRT1_2,0.), 2); 705 polygon += std::make_pair( Vector(-M_SQRT1_2,M_SQRT1_2,0.), 2); 706 SphericalPointDistribution::Polygon_t newpolygon = 707 SPD.get<6>(); 708 SphericalPointDistribution::Polygon_t expected; 709 expected += Vector(0.,0.,-1.); 710 expected += Vector(0.,0.,1.); 711 SphericalPointDistribution::Polygon_t remaining = 712 SphericalPointDistribution::matchSphericalPointDistributions( 713 polygon, 714 newpolygon); 715 // std::cout << std::setprecision(13) << "Matched polygon is " << remaining << std::endl; 716 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 717 } 718 } 719 640 720 /** UnitTest for matchSphericalPointDistributions() with five points 641 721 */ -
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.hpp
r1ae9aa r23c605 31 31 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_7 ); 32 32 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_8 ); 33 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_multiple ); 33 34 CPPUNIT_TEST_SUITE_END(); 34 35 … … 45 46 void matchSphericalPointDistributionsTest_7(); 46 47 void matchSphericalPointDistributionsTest_8(); 48 void matchSphericalPointDistributionsTest_multiple(); 47 49 48 50 private:
Note:
See TracChangeset
for help on using the changeset viewer.
