Changeset 1ae9aa
- Timestamp:
- Aug 20, 2014, 1:04:08 PM (11 years ago)
- Children:
- 23c605
- Parents:
- 260540
- git-author:
- Frederik Heber <heber@…> (06/29/14 21:20:49)
- git-committer:
- Frederik Heber <heber@…> (08/20/14 13:04:08)
- Location:
- src/Fragmentation/Exporters
- Files:
-
- 4 edited
-
SphericalPointDistribution.cpp (modified) (7 diffs)
-
SphericalPointDistribution.hpp (modified) (5 diffs)
-
unittests/SphericalPointDistributionUnitTest.cpp (modified) (1 diff)
-
unittests/SphericalPointDistributionUnitTest.hpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
r260540 r1ae9aa 62 62 typedef std::vector<double> DistanceArray_t; 63 63 64 // class generator: taken from www.cplusplus.com example std::generate 65 struct c_unique { 66 int current; 67 c_unique() {current=0;} 68 int operator()() {return current++;} 69 } UniqueNumber; 70 64 71 inline 65 72 DistanceArray_t calculatePairwiseDistances( … … 82 89 } 83 90 84 // class generator: taken from www.cplusplus.com example std::generate 85 struct c_unique { 86 int current; 87 c_unique() {current=0;} 88 int operator()() {return current++;} 89 } UniqueNumber; 90 91 /** Calculate the center of a given set of points in \a _positions but only 92 * for those indicated by \a _indices. 93 * 94 */ 95 inline 96 Vector calculateCenter( 97 const SphericalPointDistribution::VectorArray_t &_positions, 98 const SphericalPointDistribution::IndexList_t &_indices) 99 { 100 Vector Center; 101 Center.Zero(); 102 for (SphericalPointDistribution::IndexList_t::const_iterator iter = _indices.begin(); 103 iter != _indices.end(); ++iter) 104 Center += _positions[*iter]; 105 if (!_indices.empty()) 106 Center *= 1./(double)_indices.size(); 107 108 return Center; 109 } 110 111 /** Decides by an orthonormal third vector whether the sign of the rotation 112 * angle should be negative or positive. 113 * 114 * \return -1 or 1 115 */ 116 inline 117 double determineSignOfRotation( 118 const Vector &_oldPosition, 119 const Vector &_newPosition, 120 const Vector &_RotationAxis 121 ) 122 { 123 Vector dreiBein(_oldPosition); 124 dreiBein.VectorProduct(_RotationAxis); 125 dreiBein.Normalize(); 126 const double sign = 127 (dreiBein.ScalarProduct(_newPosition) < 0.) ? -1. : +1.; 128 LOG(6, "DEBUG: oldCenter on plane is " << _oldPosition 129 << ", newCenter in plane is " << _newPosition 130 << ", and dreiBein is " << dreiBein); 131 return sign; 132 } 133 134 /** Convenience function to recalculate old and new center for determining plane 135 * rotation. 136 */ 137 inline 138 void calculateOldAndNewCenters( 139 Vector &_oldCenter, 140 Vector &_newCenter, 141 const SphericalPointDistribution::VectorArray_t &_referencepositions, 142 const SphericalPointDistribution::VectorArray_t &_currentpositions, 143 const SphericalPointDistribution::IndexList_t &_bestmatching) 144 { 145 const size_t NumberIds = std::min(_bestmatching.size(), (size_t)3); 146 SphericalPointDistribution::IndexList_t continuousIds(NumberIds, -1); 147 std::generate(continuousIds.begin(), continuousIds.end(), UniqueNumber); 148 _oldCenter = calculateCenter(_referencepositions, continuousIds); 149 // C++11 defines a copy_n function ... 150 SphericalPointDistribution::IndexList_t::const_iterator enditer = _bestmatching.begin(); 151 std::advance(enditer, NumberIds); 152 SphericalPointDistribution::IndexList_t firstbestmatchingIds(NumberIds, -1); 153 std::copy(_bestmatching.begin(), enditer, firstbestmatchingIds.begin()); 154 _newCenter = calculateCenter( _currentpositions, firstbestmatchingIds); 155 } 91 156 /** Returns squared L2 error of the given \a _Matching. 92 157 * … … 218 283 } 219 284 220 /** Decides by an orthonormal third vector whether the sign of the rotation221 * angle should be negative or positive.222 *223 * \return -1 or 1224 */225 inline226 double determineSignOfRotation(227 const Vector &_oldPosition,228 const Vector &_newPosition,229 const Vector &_RotationAxis230 )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 " << _oldPosition238 << ", newCenter in plane is " << _newPosition239 << ", and dreiBein is " << dreiBein);240 return sign;241 }242 243 285 /** Finds combinatorially the best matching between points in \a _polygon 244 286 * and \a _newpolygon. … … 246 288 * We find the matching with the smallest L2 error, where we break when we stumble 247 289 * upon a matching with zero error. 290 * 291 * As points in \a _polygon may be have a weight greater 1 we have to match it to 292 * multiple points in \a _newpolygon. Eventually, these multiple points are combined 293 * for their center of weight, which is the only thing follow-up function see of 294 * these multiple points. Hence, we actually modify \a _newpolygon in the process 295 * such that the returned IndexList_t indicates a bijective mapping in the end. 248 296 * 249 297 * \sa recurseMatchings() for going through all matchings … … 254 302 */ 255 303 SphericalPointDistribution::IndexList_t SphericalPointDistribution::findBestMatching( 256 const SphericalPointDistribution::WeightedPolygon_t &_polygon,257 const SphericalPointDistribution::Polygon_t &_newpolygon304 const WeightedPolygon_t &_polygon, 305 Polygon_t &_newpolygon 258 306 ) 259 307 { … … 279 327 recurseMatchings(MCS, matching, indices, matchingsize); 280 328 } 281 return MCS.bestmatching; 282 } 283 284 inline 285 Vector calculateCenter( 286 const SphericalPointDistribution::VectorArray_t &_positions, 287 const SphericalPointDistribution::IndexList_t &_indices) 288 { 289 Vector Center; 290 Center.Zero(); 291 for (SphericalPointDistribution::IndexList_t::const_iterator iter = _indices.begin(); 292 iter != _indices.end(); ++iter) 293 Center += _positions[*iter]; 294 if (!_indices.empty()) 295 Center *= 1./(double)_indices.size(); 296 297 return Center; 298 } 299 300 inline 301 void calculateOldAndNewCenters( 302 Vector &_oldCenter, 303 Vector &_newCenter, 304 const SphericalPointDistribution::VectorArray_t &_referencepositions, 305 const SphericalPointDistribution::VectorArray_t &_currentpositions, 306 const SphericalPointDistribution::IndexList_t &_bestmatching) 307 { 308 const size_t NumberIds = std::min(_bestmatching.size(), (size_t)3); 309 SphericalPointDistribution::IndexList_t continuousIds(NumberIds, -1); 310 std::generate(continuousIds.begin(), continuousIds.end(), UniqueNumber); 311 _oldCenter = calculateCenter(_referencepositions, continuousIds); 312 // C++11 defines a copy_n function ... 313 SphericalPointDistribution::IndexList_t::const_iterator enditer = _bestmatching.begin(); 314 std::advance(enditer, NumberIds); 315 SphericalPointDistribution::IndexList_t firstbestmatchingIds(NumberIds, -1); 316 std::copy(_bestmatching.begin(), enditer, firstbestmatchingIds.begin()); 317 _newCenter = calculateCenter( _currentpositions, firstbestmatchingIds); 329 330 // 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 const SphericalPointDistribution::IndexList_t IndexList = 336 joinPoints(_newpolygon, MCS.newpoints, bestmatching); 337 338 return IndexList; 339 } 340 341 SphericalPointDistribution::IndexList_t SphericalPointDistribution::joinPoints( 342 Polygon_t &_newpolygon, 343 const VectorArray_t &_newpoints, 344 const IndexTupleList_t &_bestmatching 345 ) 346 { 347 // combine all multiple points 348 IndexList_t IndexList; 349 IndexArray_t removalpoints; 350 unsigned int UniqueIndex = _newpolygon.size(); // all indices up to size are used right now 351 VectorArray_t newCenters; 352 newCenters.reserve(_bestmatching.size()); 353 for (IndexTupleList_t::const_iterator tupleiter = _bestmatching.begin(); 354 tupleiter != _bestmatching.end(); ++tupleiter) { 355 ASSERT (tupleiter->size() > 0, 356 "findBestMatching() - encountered tuple in bestmatching with size 0."); 357 if (tupleiter->size() == 1) { 358 // add point and index 359 IndexList.push_back(*tupleiter->begin()); 360 } else { 361 // combine into weighted and normalized center 362 Vector Center = calculateCenter(_newpoints, *tupleiter); 363 Center.Normalize(); 364 _newpolygon.push_back(Center); 365 LOG(5, "DEBUG: Combining " << tupleiter->size() << "points to weighted center " 366 << Center << " with new index " << UniqueIndex); 367 // mark for removal 368 removalpoints.insert(removalpoints.end(), tupleiter->begin(), tupleiter->end()); 369 // add new index 370 IndexList.push_back(UniqueIndex++); 371 } 372 } 373 // IndexList is now our new bestmatching (that is bijective) 374 LOG(4, "DEBUG: Our new bijective IndexList reads as " << IndexList); 375 376 // modifying _newpolygon: remove all points in removalpoints, add those in newCenters 377 Polygon_t allnewpoints = _newpolygon; 378 { 379 _newpolygon.clear(); 380 std::sort(removalpoints.begin(), removalpoints.end()); 381 size_t i = 0; 382 IndexArray_t::const_iterator removeiter = removalpoints.begin(); 383 for (Polygon_t::iterator iter = allnewpoints.begin(); 384 iter != allnewpoints.end(); ++iter, ++i) { 385 if ((removeiter != removalpoints.end()) && (i == *removeiter)) { 386 // don't add, go to next remove index 387 ++removeiter; 388 } else { 389 // otherwise add points 390 _newpolygon.push_back(*iter); 391 } 392 } 393 } 394 LOG(4, "DEBUG: The polygon with recentered points removed is " << _newpolygon); 395 396 // map IndexList to new shrinked _newpolygon 397 typedef std::set<unsigned int> IndexSet_t; 398 IndexSet_t SortedIndexList(IndexList.begin(), IndexList.end()); 399 IndexList.clear(); 400 { 401 size_t offset = 0; 402 IndexSet_t::const_iterator listiter = SortedIndexList.begin(); 403 IndexArray_t::const_iterator removeiter = removalpoints.begin(); 404 for (size_t i = 0; i < allnewpoints.size(); ++i) { 405 if ((removeiter != removalpoints.end()) && (i == *removeiter)) { 406 ++offset; 407 ++removeiter; 408 } else if ((listiter != SortedIndexList.end()) && (i == *listiter)) { 409 IndexList.push_back(*listiter - offset); 410 ++listiter; 411 } 412 } 413 } 414 LOG(4, "DEBUG: Our new bijective IndexList corrected for removed points reads as " 415 << IndexList); 416 417 return IndexList; 318 418 } 319 419 … … 492 592 SphericalPointDistribution::matchSphericalPointDistributions( 493 593 const SphericalPointDistribution::WeightedPolygon_t &_polygon, 494 constSphericalPointDistribution::Polygon_t &_newpolygon594 SphericalPointDistribution::Polygon_t &_newpolygon 495 595 ) 496 596 { -
src/Fragmentation/Exporters/SphericalPointDistribution.hpp
r260540 r1ae9aa 21 21 22 22 #include "LinearAlgebra/Vector.hpp" 23 24 class SphericalPointDistributionTest; 23 25 24 26 /** contains getters for the VSEPR model for specific number of electrons. … … 80 82 static Polygon_t matchSphericalPointDistributions( 81 83 const WeightedPolygon_t &_polygon, 82 constPolygon_t &_newpolygon84 Polygon_t &_newpolygon 83 85 ); 84 86 … … 88 90 const double SQRT_3; 89 91 92 //!> typedef for a full rotation specification consisting of axis and angle. 90 93 typedef std::pair<Vector, double> Rotation_t; 91 94 95 //!> typedef for a list of indices (of points in a polygon) 92 96 typedef std::list<unsigned int> IndexList_t; 97 //!> typedef enumerating possibly multiple points accumulated as one point 98 typedef std::list< IndexList_t > IndexTupleList_t; 99 //!> typedef for a vector of indices 93 100 typedef std::vector<unsigned int> IndexArray_t; 101 //!> typedef for a Vector of positions 94 102 typedef std::vector<Vector> VectorArray_t; 103 //!> typedef for a Vector of positions with weights 104 typedef std::vector< std::pair<Vector, int> > WeightedVectorArray_t; 95 105 96 106 //!> amplitude up to which deviations in checks of rotations are tolerated … … 98 108 99 109 private: 110 //!> grant unit tests access to private parts 111 friend class SphericalPointDistributionTest; 112 100 113 static std::pair<double, double> calculateErrorOfMatching( 101 114 const std::vector<Vector> &_old, … … 124 137 static IndexList_t findBestMatching( 125 138 const WeightedPolygon_t &_polygon, 126 const Polygon_t &_newpolygon 139 Polygon_t &_newpolygon 140 ); 141 142 static IndexList_t joinPoints( 143 Polygon_t &_newpolygon, 144 const VectorArray_t &_newpoints, 145 const IndexTupleList_t &_bestmatching 127 146 ); 128 147 -
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.cpp
r260540 r1ae9aa 245 245 } 246 246 247 /** UnitTest for joinPoints() 248 */ 249 void SphericalPointDistributionTest::joinPointsTest() 250 { 251 // test with simple configuration of three points 252 { 253 SphericalPointDistribution::Polygon_t newpolygon; 254 newpolygon += Vector(1.,0.,0.); 255 newpolygon += Vector(0.,1.,0.); 256 newpolygon += Vector(0.,0.,1.); 257 SphericalPointDistribution::Polygon_t expectedpolygon = newpolygon; 258 SphericalPointDistribution::IndexTupleList_t matching; 259 matching += SphericalPointDistribution::IndexList_t(1,0); 260 matching += SphericalPointDistribution::IndexList_t(1,1); 261 matching += SphericalPointDistribution::IndexList_t(1,2); 262 SphericalPointDistribution::IndexList_t IndexList = 263 SphericalPointDistribution::joinPoints( 264 newpolygon, 265 SphericalPointDistribution::VectorArray_t(newpolygon.begin(), newpolygon.end()), 266 matching); 267 SphericalPointDistribution::IndexList_t expected; 268 expected += 0,1,2; 269 CPPUNIT_ASSERT_EQUAL( expected, IndexList ); 270 CPPUNIT_ASSERT_EQUAL( expectedpolygon, newpolygon ); 271 } 272 273 // test with simple configuration of three points, only two are picked 274 { 275 SphericalPointDistribution::Polygon_t newpolygon; 276 newpolygon += Vector(1.,0.,0.); 277 newpolygon += Vector(0.,1.,0.); 278 newpolygon += Vector(0.,0.,1.); 279 SphericalPointDistribution::Polygon_t expectedpolygon = newpolygon; 280 SphericalPointDistribution::IndexTupleList_t matching; 281 matching += SphericalPointDistribution::IndexList_t(1,1); 282 matching += SphericalPointDistribution::IndexList_t(1,2); 283 SphericalPointDistribution::IndexList_t IndexList = 284 SphericalPointDistribution::joinPoints( 285 newpolygon, 286 SphericalPointDistribution::VectorArray_t(newpolygon.begin(), newpolygon.end()), 287 matching); 288 SphericalPointDistribution::IndexList_t expected; 289 expected += 1,2; 290 CPPUNIT_ASSERT_EQUAL( expected, IndexList ); 291 CPPUNIT_ASSERT_EQUAL( expectedpolygon, newpolygon ); 292 } 293 294 // test with simple configuration of three points, two are joined 295 { 296 SphericalPointDistribution::Polygon_t newpolygon; 297 newpolygon += Vector(1.,0.,0.); 298 newpolygon += Vector(0.,1.,0.); 299 newpolygon += Vector(0.,0.,1.); 300 SphericalPointDistribution::Polygon_t expectedpolygon; 301 expectedpolygon += Vector(1.,0.,0.); 302 expectedpolygon += Vector(0.,M_SQRT1_2,M_SQRT1_2); 303 SphericalPointDistribution::IndexTupleList_t matching; 304 SphericalPointDistribution::IndexList_t joined; 305 joined += 1,2; 306 matching += SphericalPointDistribution::IndexList_t(1,0); 307 matching += joined; 308 SphericalPointDistribution::IndexList_t IndexList = 309 SphericalPointDistribution::joinPoints( 310 newpolygon, 311 SphericalPointDistribution::VectorArray_t(newpolygon.begin(), newpolygon.end()), 312 matching); 313 SphericalPointDistribution::IndexList_t expected; 314 expected += 0,1; 315 CPPUNIT_ASSERT_EQUAL( expected, IndexList ); 316 CPPUNIT_ASSERT_EQUAL( expectedpolygon, newpolygon ); 317 } 318 319 // test with simple configuration of six points, two are joined, jumbled indices 320 { 321 SphericalPointDistribution::Polygon_t newpolygon; 322 newpolygon += Vector(1.,0.,1.); 323 newpolygon += Vector(1.,0.,0.); 324 newpolygon += Vector(1.,1.,0.); 325 newpolygon += Vector(0.,1.,0.); 326 newpolygon += Vector(0.,0.,1.); 327 newpolygon += Vector(1.,0.,1.); 328 SphericalPointDistribution::Polygon_t expectedpolygon; 329 expectedpolygon += Vector(1.,0.,1.); 330 expectedpolygon += Vector(1.,0.,0.); 331 expectedpolygon += Vector(1.,1.,0.); 332 expectedpolygon += Vector(1.,0.,1.); 333 expectedpolygon += Vector(0.,M_SQRT1_2,M_SQRT1_2); // new centers go last 334 SphericalPointDistribution::IndexTupleList_t matching; 335 SphericalPointDistribution::IndexList_t joined; 336 joined += 3,4; 337 matching += SphericalPointDistribution::IndexList_t(1,1); 338 matching += joined; 339 SphericalPointDistribution::IndexList_t IndexList = 340 SphericalPointDistribution::joinPoints( 341 newpolygon, 342 SphericalPointDistribution::VectorArray_t(newpolygon.begin(), newpolygon.end()), 343 matching); 344 SphericalPointDistribution::IndexList_t expected; 345 expected += 1,4; 346 CPPUNIT_ASSERT_EQUAL( expected, IndexList ); 347 CPPUNIT_ASSERT_EQUAL( expectedpolygon, newpolygon ); 348 } 349 } 247 350 248 351 /** UnitTest for matchSphericalPointDistributions() with three points -
src/Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.hpp
r260540 r1ae9aa 23 23 CPPUNIT_TEST_SUITE( SphericalPointDistributionTest) ; 24 24 CPPUNIT_TEST ( areEqualToWithinBoundsTest ); 25 CPPUNIT_TEST ( joinPointsTest ); 25 26 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_2 ); 26 27 CPPUNIT_TEST ( matchSphericalPointDistributionsTest_3 ); … … 36 37 void tearDown(); 37 38 void areEqualToWithinBoundsTest(); 39 void joinPointsTest(); 38 40 void matchSphericalPointDistributionsTest_2(); 39 41 void matchSphericalPointDistributionsTest_3();
Note:
See TracChangeset
for help on using the changeset viewer.
