- 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)
- File:
-
- 1 edited
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
Note:
See TracChangeset
for help on using the changeset viewer.
