Changeset 3da643
- Timestamp:
- Aug 20, 2014, 1:04:08 PM (11 years ago)
- Children:
- 0710bf
- Parents:
- 6aa6b7
- git-author:
- Frederik Heber <heber@…> (06/12/14 07:23:12)
- git-committer:
- Frederik Heber <heber@…> (08/20/14 13:04:08)
- Files:
-
- 7 edited
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp (modified) (8 diffs)
-
src/Fragmentation/Exporters/SphericalPointDistribution.hpp (modified) (1 diff)
-
src/Fragmentation/Exporters/unittests/Makefile.am (modified) (1 diff)
-
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.cpp (modified) (21 diffs)
-
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.hpp (modified) (2 diffs)
-
tests/regression/Fragmentation/FragmentMolecule/testsuite-fragmentation-fragment-molecule.at (modified) (1 diff)
-
tests/regression/Fragmentation/StoreSaturatedFragment/testsuite-fragmentation-store-saturated-fragment.at (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
r6aa6b7 r3da643 53 53 54 54 #include "LinearAlgebra/Line.hpp" 55 #include "LinearAlgebra/Plane.hpp" 55 56 #include "LinearAlgebra/RealSpaceMatrix.hpp" 56 57 #include "LinearAlgebra/Vector.hpp" 57 58 58 typedef std::list<unsigned int> IndexList_t; 59 typedef std::vector<unsigned int> IndexArray_t;60 typedef std::vector<Vector> VectorArray_t; 59 // static entities 60 const double SphericalPointDistribution::warn_amplitude = 1e-2; 61 61 62 typedef std::vector<double> DistanceArray_t; 62 63 64 inline 63 65 DistanceArray_t calculatePairwiseDistances( 64 66 const std::vector<Vector> &_points, 65 const IndexList_t &_indices67 const SphericalPointDistribution::IndexList_t &_indices 66 68 ) 67 69 { 68 70 DistanceArray_t result; 69 for ( IndexList_t::const_iterator firstiter = _indices.begin();71 for (SphericalPointDistribution::IndexList_t::const_iterator firstiter = _indices.begin(); 70 72 firstiter != _indices.end(); ++firstiter) { 71 for ( IndexList_t::const_iterator seconditer = firstiter;73 for (SphericalPointDistribution::IndexList_t::const_iterator seconditer = firstiter; 72 74 seconditer != _indices.end(); ++seconditer) { 73 75 if (firstiter == seconditer) … … 98 100 * \return pair with L1 and squared L2 error 99 101 */ 100 std::pair<double, double> calculateErrorOfMatching(102 std::pair<double, double> SphericalPointDistribution::calculateErrorOfMatching( 101 103 const std::vector<Vector> &_old, 102 104 const std::vector<Vector> &_new, … … 135 137 } 136 138 137 SphericalPointDistribution::Polygon_t removeMatchingPoints(139 SphericalPointDistribution::Polygon_t SphericalPointDistribution::removeMatchingPoints( 138 140 const VectorArray_t &_points, 139 141 const IndexList_t &_matchingindices … … 160 162 } 161 163 162 struct MatchingControlStructure {163 bool foundflag;164 double bestL2;165 IndexList_t bestmatching;166 VectorArray_t oldpoints;167 VectorArray_t newpoints;168 };169 170 164 /** Recursive function to go through all possible matchings. 171 165 * … … 175 169 * \param _matchingsize 176 170 */ 177 void recurseMatchings(171 void SphericalPointDistribution::recurseMatchings( 178 172 MatchingControlStructure &_MCS, 179 173 IndexList_t &_matching, … … 224 218 } 225 219 226 /** Rotates a given polygon around x, y, and z axis by the given angles.227 * 228 * \param _polygon polygon whose points to rotate229 * \ param _q quaternion specifying the rotation of the coordinate system220 /** Decides by an orthonormal third vector whether the sign of the rotation 221 * angle should be negative or positive. 222 * 223 * \return -1 or 1 230 224 */ 231 SphericalPointDistribution::Polygon_t rotatePolygon( 225 inline 226 double determineSignOfRotation( 227 const Vector &_oldPosition, 228 const Vector &_newPosition, 229 const Vector &_RotationAxis 230 ) 231 { 232 Vector dreiBein(_oldPosition); 233 dreiBein.VectorProduct(_RotationAxis); 234 dreiBein.Normalize(); 235 const double sign = 236 (dreiBein.ScalarProduct(_newPosition) < 0.) ? -1. : +1.; 237 LOG(6, "DEBUG: oldCenter on plane is " << _oldPosition 238 << ", newCenter in plane is " << _newPosition 239 << ", and dreiBein is " << dreiBein); 240 return sign; 241 } 242 243 /** Finds combinatorially the best matching between points in \a _polygon 244 * and \a _newpolygon. 245 * 246 * We find the matching with the smallest L2 error, where we break when we stumble 247 * upon a matching with zero error. 248 * 249 * \sa recurseMatchings() for going through all matchings 250 * 251 * \param _polygon here, we have indices 0,1,2,... 252 * \param _newpolygon and here we need to find the correct indices 253 * \return list of indices: first in \a _polygon goes to first index for \a _newpolygon 254 */ 255 SphericalPointDistribution::IndexList_t SphericalPointDistribution::findBestMatching( 232 256 const SphericalPointDistribution::Polygon_t &_polygon, 233 const boost::math::quaternion<double> &_q) 234 { 235 SphericalPointDistribution::Polygon_t rotated_polygon = _polygon; 236 boost::math::quaternion<double> q_inverse = 237 boost::math::conj(_q)/(boost::math::norm(_q)); 238 239 // apply rotation angles 240 for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_polygon.begin(); 241 iter != rotated_polygon.end(); ++iter) { 242 Vector ¤t = *iter; 243 boost::math::quaternion<double> p(0, current[0], current[1], current[2]); 244 p = _q * p * q_inverse; 245 LOG(5, "DEBUG: Rotated point is " << p); 246 // i have no idea why but first component comes up with wrong sign 247 current[0] = -p.R_component_2(); 248 current[1] = p.R_component_3(); 249 current[2] = p.R_component_4(); 250 } 251 252 return rotated_polygon; 257 const SphericalPointDistribution::Polygon_t &_newpolygon 258 ) 259 { 260 MatchingControlStructure MCS; 261 MCS.foundflag = false; 262 MCS.bestL2 = std::numeric_limits<double>::max(); 263 MCS.oldpoints.insert(MCS.oldpoints.begin(), _polygon.begin(),_polygon.end() ); 264 MCS.newpoints.insert(MCS.newpoints.begin(), _newpolygon.begin(),_newpolygon.end() ); 265 266 // search for bestmatching combinatorially 267 { 268 // translate polygon into vector to enable index addressing 269 IndexList_t indices(_newpolygon.size()); 270 std::generate(indices.begin(), indices.end(), UniqueNumber); 271 IndexList_t matching; 272 273 // walk through all matchings 274 const unsigned int matchingsize = _polygon.size(); 275 ASSERT( matchingsize <= indices.size(), 276 "SphericalPointDistribution::matchSphericalPointDistributions() - not enough new points to choose for matching to old ones."); 277 recurseMatchings(MCS, matching, indices, matchingsize); 278 } 279 return MCS.bestmatching; 280 } 281 282 inline 283 Vector calculateCenter( 284 const SphericalPointDistribution::VectorArray_t &_positions, 285 const SphericalPointDistribution::IndexList_t &_indices) 286 { 287 Vector Center; 288 Center.Zero(); 289 for (SphericalPointDistribution::IndexList_t::const_iterator iter = _indices.begin(); 290 iter != _indices.end(); ++iter) 291 Center += _positions[*iter]; 292 if (!_indices.empty()) 293 Center *= 1./(double)_indices.size(); 294 295 return Center; 296 } 297 298 inline 299 void calculateOldAndNewCenters( 300 Vector &_oldCenter, 301 Vector &_newCenter, 302 const SphericalPointDistribution::VectorArray_t &_referencepositions, 303 const SphericalPointDistribution::VectorArray_t &_currentpositions, 304 const SphericalPointDistribution::IndexList_t &_bestmatching) 305 { 306 const size_t NumberIds = std::min(_bestmatching.size(), (size_t)3); 307 SphericalPointDistribution::IndexList_t continuousIds(NumberIds, -1); 308 std::generate(continuousIds.begin(), continuousIds.end(), UniqueNumber); 309 _oldCenter = calculateCenter(_referencepositions, continuousIds); 310 // C++11 defines a copy_n function ... 311 SphericalPointDistribution::IndexList_t::const_iterator enditer = _bestmatching.begin(); 312 std::advance(enditer, NumberIds); 313 SphericalPointDistribution::IndexList_t firstbestmatchingIds(NumberIds, -1); 314 std::copy(_bestmatching.begin(), enditer, firstbestmatchingIds.begin()); 315 _newCenter = calculateCenter( _currentpositions, firstbestmatchingIds); 316 } 317 318 SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPlaneAligningRotation( 319 const VectorArray_t &_referencepositions, 320 const VectorArray_t &_currentpositions, 321 const IndexList_t &_bestmatching 322 ) 323 { 324 bool dontcheck = false; 325 // initialize to no rotation 326 Rotation_t Rotation; 327 Rotation.first.Zero(); 328 Rotation.first[0] = 1.; 329 Rotation.second = 0.; 330 331 // calculate center of triangle/line/point consisting of first points of matching 332 Vector oldCenter; 333 Vector newCenter; 334 calculateOldAndNewCenters( 335 oldCenter, newCenter, 336 _referencepositions, _currentpositions, _bestmatching); 337 338 if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) { 339 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter); 340 oldCenter.Normalize(); 341 newCenter.Normalize(); 342 if (!oldCenter.IsEqualTo(newCenter)) { 343 // calculate rotation axis and angle 344 Rotation.first = oldCenter; 345 Rotation.first.VectorProduct(newCenter); 346 Rotation.second = oldCenter.Angle(newCenter); // /(M_PI/2.); 347 } else { 348 // no rotation required anymore 349 } 350 } else { 351 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter); 352 if ((oldCenter.IsZero()) && (newCenter.IsZero())) { 353 // either oldCenter or newCenter (or both) is directly at origin 354 if (_bestmatching.size() == 2) { 355 // line case 356 Vector oldPosition = _currentpositions[*_bestmatching.begin()]; 357 Vector newPosition = _referencepositions[0]; 358 // check whether we need to rotate at all 359 if (!oldPosition.IsEqualTo(newPosition)) { 360 Rotation.first = oldPosition; 361 Rotation.first.VectorProduct(newPosition); 362 // orientation will fix the sign here eventually 363 Rotation.second = oldPosition.Angle(newPosition); 364 } else { 365 // no rotation required anymore 366 } 367 } else { 368 // triangle case 369 // both triangles/planes have same center, hence get axis by 370 // VectorProduct of Normals 371 Plane newplane(_referencepositions[0], _referencepositions[1], _referencepositions[2]); 372 VectorArray_t vectors; 373 for (IndexList_t::const_iterator iter = _bestmatching.begin(); 374 iter != _bestmatching.end(); ++iter) 375 vectors.push_back(_currentpositions[*iter]); 376 Plane oldplane(vectors[0], vectors[1], vectors[2]); 377 Vector oldPosition = oldplane.getNormal(); 378 Vector newPosition = newplane.getNormal(); 379 // check whether we need to rotate at all 380 if (!oldPosition.IsEqualTo(newPosition)) { 381 Rotation.first = oldPosition; 382 Rotation.first.VectorProduct(newPosition); 383 Rotation.first.Normalize(); 384 385 // construct reference vector to determine direction of rotation 386 const double sign = determineSignOfRotation(oldPosition, newPosition, Rotation.first); 387 Rotation.second = sign * oldPosition.Angle(newPosition); 388 LOG(5, "DEBUG: Rotating plane normals by " << Rotation.second 389 << " around axis " << Rotation.first); 390 } else { 391 // else do nothing 392 } 393 } 394 } else { 395 // TODO: we can't do anything here, but this case needs to be dealt with when 396 // we have no ideal geometries anymore 397 if ((oldCenter-newCenter).Norm() > warn_amplitude) 398 ELOG(2, "oldCenter is " << oldCenter << ", yet newCenter is " << newCenter); 399 // else they are considered close enough 400 dontcheck = true; 401 } 402 } 403 404 #ifndef NDEBUG 405 // check: rotation brings newCenter onto oldCenter position 406 if (!dontcheck) { 407 Line Axis(zeroVec, Rotation.first); 408 Vector test = Axis.rotateVector(newCenter, Rotation.second); 409 LOG(4, "CHECK: rotated newCenter is " << test 410 << ", oldCenter is " << oldCenter); 411 ASSERT( (test - oldCenter).NormSquared() < std::numeric_limits<double>::epsilon()*1e4, 412 "matchSphericalPointDistributions() - rotation does not work as expected by " 413 +toString((test - oldCenter).NormSquared())+"."); 414 } 415 #endif 416 417 return Rotation; 418 } 419 420 SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPointAligningRotation( 421 const VectorArray_t &remainingold, 422 const VectorArray_t &remainingnew, 423 const IndexList_t &_bestmatching) 424 { 425 // initialize rotation to zero 426 Rotation_t Rotation; 427 Rotation.first.Zero(); 428 Rotation.first[0] = 1.; 429 Rotation.second = 0.; 430 431 // recalculate center 432 Vector oldCenter; 433 Vector newCenter; 434 calculateOldAndNewCenters( 435 oldCenter, newCenter, 436 remainingold, remainingnew, _bestmatching); 437 438 Vector oldPosition = remainingnew[*_bestmatching.begin()]; 439 Vector newPosition = remainingold[0]; 440 LOG(6, "DEBUG: oldPosition is " << oldPosition << " and newPosition is " << newPosition); 441 if (!oldPosition.IsEqualTo(newPosition)) { 442 if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) { 443 oldCenter.Normalize(); // note weighted sum of normalized weight is not normalized 444 Rotation.first = oldCenter; 445 LOG(6, "DEBUG: Picking normalized oldCenter as Rotation.first " << oldCenter); 446 oldPosition.ProjectOntoPlane(Rotation.first); 447 newPosition.ProjectOntoPlane(Rotation.first); 448 LOG(6, "DEBUG: Positions after projection are " << oldPosition << " and " << newPosition); 449 } else { 450 if (_bestmatching.size() == 2) { 451 // line situation 452 try { 453 Plane oldplane(oldPosition, oldCenter, newPosition); 454 Rotation.first = oldplane.getNormal(); 455 LOG(6, "DEBUG: Plane is " << oldplane << " and normal is " << Rotation.first); 456 } catch (LinearDependenceException &e) { 457 LOG(6, "DEBUG: Vectors defining plane are linearly dependent."); 458 // oldPosition and newPosition are on a line, just flip when not equal 459 if (!oldPosition.IsEqualTo(newPosition)) { 460 Rotation.first.Zero(); 461 Rotation.first.GetOneNormalVector(oldPosition); 462 LOG(6, "DEBUG: For flipping we use Rotation.first " << Rotation.first); 463 assert( Rotation.first.ScalarProduct(oldPosition) < std::numeric_limits<double>::epsilon()*1e4); 464 // Rotation.second = M_PI; 465 } else { 466 LOG(6, "DEBUG: oldPosition and newPosition are equivalent."); 467 } 468 } 469 } else { 470 // triangle situation 471 Plane oldplane(remainingold[0], remainingold[1], remainingold[2]); 472 Rotation.first = oldplane.getNormal(); 473 LOG(6, "DEBUG: oldPlane is " << oldplane << " and normal is " << Rotation.first); 474 oldPosition.ProjectOntoPlane(Rotation.first); 475 LOG(6, "DEBUG: Positions after projection are " << oldPosition << " and " << newPosition); 476 } 477 } 478 // construct reference vector to determine direction of rotation 479 const double sign = determineSignOfRotation(oldPosition, newPosition, Rotation.first); 480 Rotation.second = sign * oldPosition.Angle(newPosition); 481 } else { 482 LOG(6, "DEBUG: oldPosition and newPosition are equivalent, hence no orientating rotation."); 483 } 484 485 return Rotation; 253 486 } 254 487 … … 266 499 << " with new polygon " << _newpolygon); 267 500 501 if (_polygon.size() == _newpolygon.size()) { 502 // same number of points desired as are present? Do nothing 503 LOG(2, "INFO: There are no vacant points to return."); 504 return remainingpoints; 505 } 506 268 507 if (_polygon.size() > 0) { 269 MatchingControlStructure MCS; 270 MCS.foundflag = false; 271 MCS.bestL2 = std::numeric_limits<double>::max(); 272 MCS.oldpoints.insert(MCS.oldpoints.begin(), _polygon.begin(),_polygon.end() ); 273 MCS.newpoints.insert(MCS.newpoints.begin(), _newpolygon.begin(),_newpolygon.end() ); 274 275 // search for bestmatching combinatorially 508 IndexList_t bestmatching = findBestMatching(_polygon, _newpolygon); 509 LOG(2, "INFO: Best matching is " << bestmatching); 510 511 // determine rotation angles to align the two point distributions with 512 // respect to bestmatching: 513 // we use the center between the three first matching points 514 /// the first rotation brings these two centers to coincide 515 VectorArray_t rotated_newpolygon = remainingnew; 276 516 { 277 // translate polygon into vector to enable index addressing 278 IndexList_t indices(_newpolygon.size()); 279 std::generate(indices.begin(), indices.end(), UniqueNumber); 280 IndexList_t matching; 281 282 // walk through all matchings 283 const unsigned int matchingsize = _polygon.size(); 284 ASSERT( matchingsize <= indices.size(), 285 "SphericalPointDistribution::matchSphericalPointDistributions() - not enough new points to choose for matching to old ones."); 286 recurseMatchings(MCS, matching, indices, matchingsize); 287 } 288 LOG(2, "INFO: Best matching is " << MCS.bestmatching); 289 290 // determine rotation angles to align the two point distributions with 291 // respect to bestmatching 292 VectorArray_t rotated_newpolygon = remainingnew; 293 Vector oldCenter; 294 { 295 // calculate center of triangle/line/point consisting of first points of matching 296 Vector newCenter; 297 IndexList_t::const_iterator iter = MCS.bestmatching.begin(); 298 unsigned int i = 0; 299 for (; (i<3) && (i<MCS.bestmatching.size()); ++i, ++iter) { 300 oldCenter += remainingold[i]; 301 newCenter += remainingnew[*iter]; 302 } 303 oldCenter *= 1./(double)i; 304 newCenter *= 1./(double)i; 305 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter); 306 307 if ((oldCenter - newCenter).NormSquared() > std::numeric_limits<double>::epsilon()*1e4) { 308 // setup quaternion 309 Vector RotationAxis = oldCenter; 310 RotationAxis.VectorProduct(newCenter); 311 Line Axis(zeroVec, RotationAxis); 312 RotationAxis.Normalize(); 313 const double RotationAngle = oldCenter.Angle(newCenter); // /(M_PI/2.); 314 LOG(5, "DEBUG: Rotate coordinate system by " << RotationAngle 315 << " around axis " << RotationAxis); 316 317 // apply rotation angles 318 for (VectorArray_t::iterator iter = rotated_newpolygon.begin(); 319 iter != rotated_newpolygon.end(); ++iter) { 320 Vector ¤t = *iter; 321 LOG(5, "DEBUG: Original point is " << current); 322 current = Axis.rotateVector(current, RotationAngle); 323 LOG(5, "DEBUG: Rotated point is " << current); 517 Rotation_t Rotation = findPlaneAligningRotation( 518 remainingold, 519 remainingnew, 520 bestmatching); 521 LOG(5, "DEBUG: Rotating coordinate system by " << Rotation.second 522 << " around axis " << Rotation.first); 523 Line Axis(zeroVec, Rotation.first); 524 525 // apply rotation angle to bring newCenter to oldCenter 526 for (VectorArray_t::iterator iter = rotated_newpolygon.begin(); 527 iter != rotated_newpolygon.end(); ++iter) { 528 Vector ¤t = *iter; 529 LOG(6, "DEBUG: Original point is " << current); 530 current = Axis.rotateVector(current, Rotation.second); 531 LOG(6, "DEBUG: Rotated point is " << current); 532 } 533 534 #ifndef NDEBUG 535 // check: rotated "newCenter" should now equal oldCenter 536 { 537 Vector oldCenter; 538 Vector rotatednewCenter; 539 calculateOldAndNewCenters( 540 oldCenter, rotatednewCenter, 541 remainingold, rotated_newpolygon, bestmatching); 542 // NOTE: Center must not necessarily lie on the sphere with norm 1, hence, we 543 // have to normalize it just as before, as oldCenter and newCenter lengths may differ. 544 if ((!oldCenter.IsZero()) && (!rotatednewCenter.IsZero())) { 545 oldCenter.Normalize(); 546 rotatednewCenter.Normalize(); 547 LOG(4, "CHECK: rotatednewCenter is " << rotatednewCenter 548 << ", oldCenter is " << oldCenter); 549 ASSERT( (rotatednewCenter - oldCenter).NormSquared() < std::numeric_limits<double>::epsilon()*1e4, 550 "matchSphericalPointDistributions() - rotation does not work as expected by " 551 +toString((rotatednewCenter - oldCenter).NormSquared())+"."); 324 552 } 325 553 } 326 } 327 // rotate triangle/line/point around itself to match orientation 328 if (MCS.bestmatching.size() > 1) { 329 if (oldCenter.NormSquared() > std::numeric_limits<double>::epsilon()*1e4) { 330 // construct RotationAxis and two points on its plane, defining the angle 331 const Line RotationAxis(zeroVec, oldCenter); 332 Vector oldPosition(rotated_newpolygon[*MCS.bestmatching.begin()]); 333 oldPosition.ProjectOntoPlane(RotationAxis.getDirection()); 334 Vector newPosition(remainingold[*MCS.bestmatching.begin()]); 335 newPosition.ProjectOntoPlane(RotationAxis.getDirection()); 336 337 // construct reference vector to determine direction of rotation 338 Vector dreiBein(oldPosition); 339 dreiBein.VectorProduct(oldCenter); 340 dreiBein.Normalize(); 341 const double sign = 342 (dreiBein.ScalarProduct(newPosition) < 0.) ? -1. : +1.; 343 LOG(6, "DEBUG: oldCenter on plane is " << oldPosition 344 << ", newCenter in plane is " << newPosition 345 << ", and dreiBein is " << dreiBein); 346 const double RotationAngle = sign * oldPosition.Angle(newPosition); 347 LOG(5, "DEBUG: Rotating around self is " << RotationAngle 348 << " around axis " << RotationAxis); 554 #endif 555 } 556 /// the second (orientation) rotation aligns the planes such that the 557 /// points themselves coincide 558 if (bestmatching.size() > 1) { 559 Rotation_t Rotation = findPointAligningRotation( 560 remainingold, 561 rotated_newpolygon, 562 bestmatching); 563 564 // construct RotationAxis and two points on its plane, defining the angle 565 Rotation.first.Normalize(); 566 const Line RotationAxis(zeroVec, Rotation.first); 567 568 LOG(5, "DEBUG: Rotating around self is " << Rotation.second 569 << " around axis " << RotationAxis); 349 570 350 571 #ifndef NDEBUG 351 // check: first bestmatching in rotated_newpolygon and remainingnew352 // should now equal353 {354 const IndexList_t::const_iterator iter = MCS.bestmatching.begin();355 Vector rotatednew = RotationAxis.rotateVector(356 rotated_newpolygon[*iter],357 RotationAngle);358 LOG(4, "CHECK: rotated first new bestmatching is " << rotatednew359 << " while old was " << remainingold[*iter]);360 ASSERT( (rotatednew - remainingold[*iter]).Norm()361 < std::numeric_limits<double>::epsilon()*1e4,362 "matchSphericalPointDistributions() - orientation rotation does not work as expected.");363 }572 // check: first bestmatching in rotated_newpolygon and remainingnew 573 // should now equal 574 { 575 const IndexList_t::const_iterator iter = bestmatching.begin(); 576 Vector rotatednew = RotationAxis.rotateVector( 577 rotated_newpolygon[*iter], 578 Rotation.second); 579 LOG(4, "CHECK: rotated first new bestmatching is " << rotatednew 580 << " while old was " << remainingold[0]); 581 ASSERT( (rotatednew - remainingold[0]).Norm() < warn_amplitude, 582 "matchSphericalPointDistributions() - orientation rotation ends up off by more than " 583 +toString(warn_amplitude)+"."); 584 } 364 585 #endif 365 586 366 for (VectorArray_t::iterator iter = rotated_newpolygon.begin(); 367 iter != rotated_newpolygon.end(); ++iter) { 368 Vector ¤t = *iter; 369 LOG(6, "DEBUG: Original point is " << current); 370 current = RotationAxis.rotateVector(current, RotationAngle); 371 LOG(6, "DEBUG: Rotated point is " << current); 372 } 587 for (VectorArray_t::iterator iter = rotated_newpolygon.begin(); 588 iter != rotated_newpolygon.end(); ++iter) { 589 Vector ¤t = *iter; 590 LOG(6, "DEBUG: Original point is " << current); 591 current = RotationAxis.rotateVector(current, Rotation.second); 592 LOG(6, "DEBUG: Rotated point is " << current); 373 593 } 374 594 } … … 376 596 // remove all points in matching and return remaining ones 377 597 SphericalPointDistribution::Polygon_t remainingpoints = 378 removeMatchingPoints(rotated_newpolygon, MCS.bestmatching);598 removeMatchingPoints(rotated_newpolygon, bestmatching); 379 599 LOG(2, "INFO: Remaining points are " << remainingpoints); 380 600 return remainingpoints; -
src/Fragmentation/Exporters/SphericalPointDistribution.hpp
r6aa6b7 r3da643 85 85 //!> precalculated value for root of 3 86 86 const double SQRT_3; 87 88 typedef std::pair<Vector, double> Rotation_t; 89 90 typedef std::list<unsigned int> IndexList_t; 91 typedef std::vector<unsigned int> IndexArray_t; 92 typedef std::vector<Vector> VectorArray_t; 93 94 //!> amplitude up to which deviations in checks of rotations are tolerated 95 static const double warn_amplitude; 96 97 private: 98 static std::pair<double, double> calculateErrorOfMatching( 99 const std::vector<Vector> &_old, 100 const std::vector<Vector> &_new, 101 const IndexList_t &_Matching); 102 103 static Polygon_t removeMatchingPoints( 104 const VectorArray_t &_points, 105 const IndexList_t &_matchingindices 106 ); 107 108 struct MatchingControlStructure { 109 bool foundflag; 110 double bestL2; 111 IndexList_t bestmatching; 112 VectorArray_t oldpoints; 113 VectorArray_t newpoints; 114 }; 115 116 static void recurseMatchings( 117 MatchingControlStructure &_MCS, 118 IndexList_t &_matching, 119 IndexList_t _indices, 120 unsigned int _matchingsize); 121 122 static IndexList_t findBestMatching( 123 const Polygon_t &_polygon, 124 const Polygon_t &_newpolygon 125 ); 126 127 static Rotation_t findPlaneAligningRotation( 128 const VectorArray_t &_referencepositions, 129 const VectorArray_t &_currentpositions, 130 const IndexList_t &_bestmatching 131 ); 132 133 static Rotation_t findPointAligningRotation( 134 const VectorArray_t &remainingold, 135 const VectorArray_t &remainingnew, 136 const IndexList_t &_bestmatching); 137 87 138 }; 88 139 -
src/Fragmentation/Exporters/unittests/Makefile.am
r6aa6b7 r3da643 17 17 SphericalPointDistributionUnitTest 18 18 19 XFAIL_TESTS += SphericalPointDistributionUnitTest20 19 TESTS += $(FRAGMENTATIONEXPORTERSTESTS) 21 20 check_PROGRAMS += $(FRAGMENTATIONEXPORTERSTESTS) -
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.cpp
r6aa6b7 r3da643 150 150 } 151 151 152 void perturbPolygon( 153 SphericalPointDistribution::Polygon_t &_polygon, 154 double _amplitude 155 ) 156 { 157 for (SphericalPointDistribution::Polygon_t::iterator iter = _polygon.begin(); 158 iter != _polygon.end(); ++iter) { 159 Vector perturber; 160 perturber.GetOneNormalVector((*iter)); 161 perturber.Scale(_amplitude); 162 *iter = *iter + perturber; 163 (*iter).Normalize(); 164 } 165 } 166 167 static 168 bool areEqualToWithinBounds( 169 const SphericalPointDistribution::Polygon_t &_polygon, 170 const SphericalPointDistribution::Polygon_t &_otherpolygon, 171 double _amplitude 172 ) 173 { 174 // same size? 175 if (_polygon.size() != _otherpolygon.size()) 176 return false; 177 // same points ? We just check witrh trivial mapping, nothing fancy ... 178 bool status = true; 179 SphericalPointDistribution::Polygon_t::const_iterator iter = _polygon.begin(); 180 SphericalPointDistribution::Polygon_t::const_iterator otheriter = _otherpolygon.begin(); 181 for (; iter != _polygon.end(); ++iter, ++otheriter) { 182 status &= (*iter - *otheriter).Norm() < _amplitude; 183 } 184 return status; 185 } 186 187 /** UnitTest for areEqualToWithinBounds() 188 */ 189 void SphericalPointDistributionTest::areEqualToWithinBoundsTest() 190 { 191 // test with no points 192 { 193 SphericalPointDistribution::Polygon_t polygon; 194 SphericalPointDistribution::Polygon_t expected = polygon; 195 CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, std::numeric_limits<double>::epsilon()*1e2) ); 196 } 197 // test with one point 198 { 199 SphericalPointDistribution::Polygon_t polygon; 200 polygon += Vector(1.,0.,0.); 201 SphericalPointDistribution::Polygon_t expected = polygon; 202 CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, std::numeric_limits<double>::epsilon()*1e2) ); 203 } 204 // test with two points 205 { 206 SphericalPointDistribution::Polygon_t polygon; 207 polygon += Vector(1.,0.,0.); 208 polygon += Vector(0.,1.,0.); 209 SphericalPointDistribution::Polygon_t expected = polygon; 210 CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, std::numeric_limits<double>::epsilon()*1e2) ); 211 } 212 213 // test with two points in different order: THIS GOES WRONG: We only check trivially 214 { 215 SphericalPointDistribution::Polygon_t polygon; 216 polygon += Vector(1.,0.,0.); 217 polygon += Vector(0.,1.,0.); 218 SphericalPointDistribution::Polygon_t expected; 219 expected += Vector(0.,1.,0.); 220 expected += Vector(1.,0.,0.); 221 CPPUNIT_ASSERT( !areEqualToWithinBounds(polygon, expected, std::numeric_limits<double>::epsilon()*1e2) ); 222 } 223 224 // test with two different points 225 { 226 SphericalPointDistribution::Polygon_t polygon; 227 polygon += Vector(1.,0.,0.); 228 polygon += Vector(0.,1.,0.); 229 SphericalPointDistribution::Polygon_t expected; 230 expected += Vector(1.01,0.,0.); 231 expected += Vector(0.,1.,0.); 232 CPPUNIT_ASSERT( areEqualToWithinBounds(polygon, expected, 0.05) ); 233 CPPUNIT_ASSERT( !areEqualToWithinBounds(polygon, expected, 0.005) ); 234 } 235 236 // test with different number of points 237 { 238 SphericalPointDistribution::Polygon_t polygon; 239 polygon += Vector(1.,0.,0.); 240 polygon += Vector(0.,1.,0.); 241 SphericalPointDistribution::Polygon_t expected; 242 expected += Vector(0.,1.,0.); 243 CPPUNIT_ASSERT( !areEqualToWithinBounds(polygon, expected, 0.05) ); 244 } 245 } 246 247 152 248 /** UnitTest for matchSphericalPointDistributions() with three points 153 249 */ … … 205 301 newpolygon); 206 302 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 303 // also slightly perturbed 304 const double amplitude = 0.05; 305 perturbPolygon(polygon, amplitude); 306 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 207 307 } 208 308 … … 227 327 newpolygon); 228 328 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 329 // also slightly perturbed 330 const double amplitude = 0.05; 331 perturbPolygon(polygon, amplitude); 332 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 229 333 } 230 334 … … 241 345 newpolygon); 242 346 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 347 // also slightly perturbed 348 const double amplitude = 0.05; 349 perturbPolygon(polygon, amplitude); 350 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 243 351 } 244 352 … … 260 368 newpolygon); 261 369 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 370 // also slightly perturbed 371 const double amplitude = 0.05; 372 perturbPolygon(polygon, amplitude); 373 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 262 374 } 263 375 } … … 318 430 newpolygon); 319 431 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 432 // also slightly perturbed 433 const double amplitude = 0.05; 434 perturbPolygon(polygon, amplitude); 435 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 436 } 437 438 // test with two points, matching trivially, also with slightly perturbed 439 { 440 SphericalPointDistribution::Polygon_t polygon; 441 polygon += Vector(1.,0.,0.), Vector(-1./3.0, 2.0*M_SQRT2/3.0,0.); 442 SphericalPointDistribution::Polygon_t newpolygon = 443 SPD.get<4>(); 444 SphericalPointDistribution::Polygon_t expected = newpolygon; 445 expected.pop_front(); // remove first point 446 expected.pop_front(); // remove second point 447 SphericalPointDistribution::Polygon_t remaining = 448 SphericalPointDistribution::matchSphericalPointDistributions( 449 polygon, 450 newpolygon); 451 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 452 // also slightly perturbed 453 const double amplitude = 0.05; 454 perturbPolygon(polygon, amplitude); 455 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 320 456 } 321 457 … … 340 476 newpolygon); 341 477 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 478 // also slightly perturbed 479 const double amplitude = 0.05; 480 perturbPolygon(polygon, amplitude); 481 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 342 482 } 343 483 … … 360 500 newpolygon); 361 501 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 502 // also slightly perturbed 503 const double amplitude = 0.05; 504 perturbPolygon(polygon, amplitude); 505 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 362 506 } 363 507 … … 384 528 newpolygon); 385 529 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 530 // also slightly perturbed 531 const double amplitude = 0.05; 532 perturbPolygon(polygon, amplitude); 533 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 386 534 } 387 535 } … … 442 590 newpolygon); 443 591 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 592 // also slightly perturbed 593 const double amplitude = 0.05; 594 perturbPolygon(polygon, amplitude); 595 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 444 596 } 445 597 … … 494 646 newpolygon); 495 647 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 648 // also slightly perturbed 649 const double amplitude = 0.05; 650 perturbPolygon(polygon, amplitude); 651 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 496 652 } 497 653 … … 518 674 newpolygon); 519 675 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 676 // also slightly perturbed 677 const double amplitude = 0.05; 678 perturbPolygon(polygon, amplitude); 679 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 520 680 } 521 681 } … … 576 736 newpolygon); 577 737 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 738 // also slightly perturbed 739 const double amplitude = 0.05; 740 perturbPolygon(polygon, amplitude); 741 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 578 742 } 579 743 … … 628 792 newpolygon); 629 793 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 794 // also slightly perturbed 795 const double amplitude = 0.05; 796 perturbPolygon(polygon, amplitude); 797 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 630 798 } 631 799 … … 652 820 newpolygon); 653 821 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 822 // also slightly perturbed 823 const double amplitude = 0.05; 824 perturbPolygon(polygon, amplitude); 825 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 654 826 } 655 827 } … … 710 882 newpolygon); 711 883 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 884 // also slightly perturbed 885 const double amplitude = 0.05; 886 perturbPolygon(polygon, amplitude); 887 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 712 888 } 713 889 … … 762 938 newpolygon); 763 939 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 940 // also slightly perturbed 941 const double amplitude = 0.05; 942 perturbPolygon(polygon, amplitude); 943 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 764 944 } 765 945 … … 786 966 newpolygon); 787 967 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 968 // also slightly perturbed 969 const double amplitude = 0.05; 970 perturbPolygon(polygon, amplitude); 971 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 788 972 } 789 973 } … … 844 1028 newpolygon); 845 1029 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 1030 // also slightly perturbed 1031 const double amplitude = 0.05; 1032 perturbPolygon(polygon, amplitude); 1033 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 846 1034 } 847 1035 … … 900 1088 newpolygon); 901 1089 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 1090 // also slightly perturbed 1091 const double amplitude = 0.05; 1092 perturbPolygon(polygon, amplitude); 1093 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 902 1094 } 903 1095 … … 924 1116 newpolygon); 925 1117 CPPUNIT_ASSERT_EQUAL( expected, remaining ); 1118 // also slightly perturbed 1119 const double amplitude = 0.05; 1120 perturbPolygon(polygon, amplitude); 1121 CPPUNIT_ASSERT( areEqualToWithinBounds(expected, remaining, amplitude) ); 926 1122 } 927 1123 } -
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.hpp
r6aa6b7 r3da643 22 22 { 23 23 CPPUNIT_TEST_SUITE( SphericalPointDistributionTest) ; 24 CPPUNIT_TEST ( areEqualToWithinBoundsTest ); 24 25 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_2 ); 25 26 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_3 ); … … 34 35 void setUp(); 35 36 void tearDown(); 37 void areEqualToWithinBoundsTest(); 36 38 void matchSphericalPointDistributionsTest_2(); 37 39 void matchSphericalPointDistributionsTest_3(); -
tests/regression/Fragmentation/FragmentMolecule/testsuite-fragmentation-fragment-molecule.at
r6aa6b7 r3da643 37 37 AT_SETUP([Fragmentation - Fragmentation with cycles]) 38 38 AT_KEYWORDS([fragmentation fragment-molecule cycle]) 39 AT_XFAIL_IF([/bin/true])40 39 41 40 file=benzene.pdb -
tests/regression/Fragmentation/StoreSaturatedFragment/testsuite-fragmentation-store-saturated-fragment.at
r6aa6b7 r3da643 21 21 AT_SETUP([Fragmentation - Store saturated fragment]) 22 22 AT_KEYWORDS([fragmentation store-saturated-fragment]) 23 AT_XFAIL_IF([/bin/true])24 23 25 24 file=BondFragment0.xyz
Note:
See TracChangeset
for help on using the changeset viewer.
