- Timestamp:
- Aug 20, 2014, 1:04:08 PM (11 years ago)
- Children:
- 0ae114
- Parents:
- d734ff
- git-author:
- Frederik Heber <heber@…> (06/05/14 17:16:26)
- git-committer:
- Frederik Heber <heber@…> (08/20/14 13:04:08)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
rd734ff r2d50a2 43 43 44 44 #include <algorithm> 45 #include <boost/math/quaternion.hpp> 45 46 #include <cmath> 46 47 #include <functional> … … 222 223 } 223 224 224 /** Convert cartesian to polar coordinates.225 *226 * \param _cartesian vector in cartesian coordinates227 * \return vector containing \f$ (r,\theta, \varphi \f$ tuple for polar coordinates228 */229 std::vector<double> getPolarCoordinates(const Vector &_cartesian)230 {231 std::vector<double> polar(3,0.);232 const double xsqr = _cartesian[0] * _cartesian[0];233 const double ysqr = _cartesian[1] * _cartesian[1];234 polar[0] = sqrt(xsqr + ysqr + _cartesian[2]*_cartesian[2]);235 if (fabs(_cartesian[2]) < std::numeric_limits<double>::epsilon()*1e4) {236 if (fabs(xsqr + ysqr) < std::numeric_limits<double>::epsilon()*1e4) {237 polar[1] = 0.;238 } else {239 // xsqr + ysqr is always non-negative240 polar[1] = M_PI/2.;241 }242 } else {243 polar[1] = atan( sqrt(xsqr + ysqr)/_cartesian[2]);244 if (_cartesian[2] <= -std::numeric_limits<double>::epsilon()*1e4)245 polar[1] += M_PI;246 }247 248 if (fabs(_cartesian[0]) < std::numeric_limits<double>::epsilon()*1e4) {249 if (fabs(_cartesian[1]) < std::numeric_limits<double>::epsilon()*1e4) {250 polar[2] = 0.;251 } else if (_cartesian[1] > std::numeric_limits<double>::epsilon()*1e4) {252 polar[2] = M_PI/2.;253 } else {254 polar[2] = -M_PI/2.;255 }256 } else {257 polar[2] = atan ( _cartesian[1]/_cartesian[0] );258 if (_cartesian[0] <= -std::numeric_limits<double>::epsilon()*1e4)259 polar[2] += M_PI;260 }261 return polar;262 }263 264 /** Calculate cartesian coordinates from given polar ones.265 *266 * \param _polar vector with polar coordinates267 * \return cartesian coordinates268 */269 Vector getCartesianCoordinates(const std::vector<double> &_polar)270 {271 Vector cartesian;272 ASSERT( _polar.size() == 3,273 "convertToCartesianCoordinates() - tuples has insufficient components.");274 cartesian[0] = _polar[0] * sin(_polar[1]) * cos(_polar[2]);275 cartesian[1] = _polar[0] * sin(_polar[1]) * sin(_polar[2]);276 cartesian[2] = _polar[0] * cos(_polar[1]);277 return cartesian;278 }279 280 225 /** Rotates a given polygon around x, y, and z axis by the given angles. 281 226 * 282 227 * \param _polygon polygon whose points to rotate 283 * \param _ angles vector with rotation angles for x,y,z axis228 * \param _q quaternion specifying the rotation of the coordinate system 284 229 */ 285 230 SphericalPointDistribution::Polygon_t rotatePolygon( 286 231 const SphericalPointDistribution::Polygon_t &_polygon, 287 const std::vector<double> &_angles)232 const boost::math::quaternion<double> &_q) 288 233 { 289 234 SphericalPointDistribution::Polygon_t rotated_polygon = _polygon; 290 RealSpaceMatrix rotation; 291 ASSERT( _angles.size() == 3, 292 "rotatePolygon() - not exactly "+toString(3)+" components given."); 235 boost::math::quaternion<double> q_inverse = 236 boost::math::conj(_q)/(boost::math::norm(_q)); 293 237 294 238 // apply rotation angles 295 239 for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_polygon.begin(); 296 240 iter != rotated_polygon.end(); ++iter) { 297 // transform to polar 298 std::vector<double> polar = getPolarCoordinates(*iter); 299 LOG(5, "DEBUG: Converting " << *iter << " to " << polar); 300 // sum up difference 301 std::transform( 302 _angles.begin(), _angles.end(), 303 polar.begin(), 304 polar.begin(), 305 std::plus<double>()); 306 // convert back 307 *iter = getCartesianCoordinates(polar); 308 LOG(5, "DEBUG: Converting modified " << polar << " to " << *iter); 241 Vector ¤t = *iter; 242 boost::math::quaternion<double> p(0, current[0], current[1], current[2]); 243 p = _q * p * q_inverse; 244 LOG(5, "DEBUG: Rotated point is " << p); 245 // i have no idea why but first component comes up with wrong sign 246 current[0] = -p.R_component_2(); 247 current[1] = p.R_component_3(); 248 current[2] = p.R_component_4(); 309 249 } 310 250 … … 349 289 // determine rotation angles to align the two point distributions with 350 290 // respect to bestmatching 351 std::vector<double> angles(NDIM); 352 Vector newCenter; 291 SphericalPointDistribution::Polygon_t rotated_newpolygon; 353 292 Vector oldCenter; 354 293 { 355 294 // calculate center of triangle/line/point consisting of first points of matching 295 Vector newCenter; 356 296 IndexList_t::const_iterator iter = MCS.bestmatching.begin(); 357 297 unsigned int i = 0; … … 364 304 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter); 365 305 366 // transform to polar coordinates and note difference in angular parts 367 std::vector<double> oldpolar = getPolarCoordinates(oldCenter); 368 std::vector<double> newpolar = getPolarCoordinates(newCenter); 369 std::vector<double> differencepolar; 370 std::transform( 371 oldpolar.begin(), oldpolar.end(), 372 newpolar.begin(), 373 std::back_inserter(differencepolar), 374 std::minus<double>()); 375 LOG(3, "INFO: (r,theta,phi) angles are" << differencepolar); 376 } 377 // rotate _newpolygon 378 SphericalPointDistribution::Polygon_t rotated_newpolygon = 379 rotatePolygon(_newpolygon, angles); 380 LOG(5, "DEBUG: Rotated new polygon is " << rotated_newpolygon); 381 306 if ((oldCenter - newCenter).NormSquared() > std::numeric_limits<double>::epsilon()*1e4) { 307 // setup quaternion 308 Vector RotationAxis = newCenter; 309 RotationAxis.VectorProduct(oldCenter); 310 RotationAxis.Normalize(); 311 const double RotationAngle = oldCenter.Angle(newCenter)/(M_PI/2.); 312 // RotationAxis.Angle(oldCenter) - RotationAxis.Angle(newCenter); 313 boost::math::quaternion<double> q 314 (RotationAngle, RotationAxis[0], RotationAxis[1], RotationAxis[2]); 315 LOG(5, "DEBUG: RotationAxis is " << RotationAxis 316 << ", RotationAngle is " << RotationAngle); 317 LOG(5, "DEBUG: Quaternion describing rotation is " << q); 318 #ifndef NDEBUG 319 { 320 // check that rotation works in DEBUG mode 321 boost::math::quaternion<double> p(0., newCenter[0], newCenter[1], newCenter[2]); 322 boost::math::quaternion<double> q_inverse = 323 boost::math::conj(q)/(boost::math::norm(q)); 324 p = q * p * q_inverse; 325 boost::math::quaternion<double> identity(1,0,0,0); 326 ASSERT( boost::math::norm(q*q_inverse - identity) < std::numeric_limits<double>::epsilon()*1e4, 327 "matchSphericalPointDistributions() - quaternion does not rotate newCenter " 328 +toString(q*q_inverse)+" into oldCenter "+toString(identity)+"."); 329 boost::math::quaternion<double> comparison(0., -oldCenter[0], oldCenter[1], oldCenter[2]); 330 ASSERT( boost::math::norm(p - comparison) < std::numeric_limits<double>::epsilon()*1e4, 331 "matchSphericalPointDistributions() - quaternion does not rotate newCenter " 332 +toString(p)+" into oldCenter "+toString(comparison)+"."); 333 } 334 #endif 335 336 // rotate spherical distribution 337 rotated_newpolygon = rotatePolygon(_newpolygon, q); 338 LOG(5, "DEBUG: Rotated new polygon is " << rotated_newpolygon); 339 } else { 340 rotated_newpolygon = _newpolygon; 341 } 342 } 343 // rotate triangle/line/point around itself to match orientation 382 344 const Line RotationAxis(zeroVec, oldCenter); 383 345 const double RotationAngle =
Note:
See TracChangeset
for help on using the changeset viewer.
