Ignore:
Timestamp:
Aug 20, 2014, 1:04:08 PM (11 years ago)
Author:
Frederik Heber <heber@…>
Children:
e139180
Parents:
90426a
git-author:
Frederik Heber <heber@…> (06/02/14 14:51:33)
git-committer:
Frederik Heber <heber@…> (08/20/14 13:04:08)
Message:

FIX: SphericalPointDistribution succeeds with unit test.

Location:
src/Fragmentation/Exporters
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/Fragmentation/Exporters/SphericalPointDistribution.cpp

    r90426a r0d5ca7  
    4444#include <algorithm>
    4545#include <cmath>
     46#include <functional>
     47#include <iterator>
    4648#include <limits>
    4749#include <list>
     
    8183  int current;
    8284  c_unique() {current=0;}
    83   int operator()() {return ++current;}
     85  int operator()() {return current++;}
    8486} UniqueNumber;
    8587
     
    125127    }
    126128  } else
    127     ELOG(2, "calculateErrorOfMatching() - Given matching is empty.");
     129    ELOG(3, "calculateErrorOfMatching() - Given matching's size is less than 2.");
    128130  LOG(3, "INFO: Resulting errors for matching (L1, L2): "
    129131      << errors.first << "," << errors.second << ".");
     
    156158}
    157159
    158 /** Rotates a given polygon around x, y, and z axis by the given angles.
    159  *
    160  * Essentially, we concentrate on the three points of the polygon to rotate
    161  * to the correct position. First, we rotate its center via \a angles,
    162  * then we rotate the "triangle" around itself/\a _RotationAxis by
    163  * \a _RotationAngle.
    164  *
    165  * \param _polygon polygon whose points to rotate
    166  * \param _angles vector with rotation angles for x,y,z axis
    167  * \param _RotationAxis
    168  * \param _RotationAngle
    169  */
    170 SphericalPointDistribution::Polygon_t rotatePolygon(
    171     const SphericalPointDistribution::Polygon_t &_polygon,
    172     const std::vector<double> &_angles,
    173     const Line &_RotationAxis,
    174     const double _RotationAngle)
    175 {
    176   SphericalPointDistribution::Polygon_t rotated_polygon = _polygon;
    177   RealSpaceMatrix rotation;
    178   ASSERT( _angles.size() == 3,
    179       "rotatePolygon() - not exactly "+toString(3)+" angles given.");
    180   rotation.setRotation(_angles[0] * M_PI/180., _angles[1] * M_PI/180., _angles[2] * M_PI/180.);
    181   LOG(4, "DEBUG: Rotation matrix is " << rotation);
    182 
    183   // apply rotation angles
    184   for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_polygon.begin();
    185       iter != rotated_polygon.end(); ++iter) {
    186     *iter = rotation * (*iter);
    187     _RotationAxis.rotateVector(*iter, _RotationAngle);
    188   }
    189 
    190   return rotated_polygon;
    191 }
    192 
    193160struct MatchingControlStructure {
    194161  bool foundflag;
     
    214181  LOG(4, "DEBUG: Recursing with current matching " << _matching
    215182      << ", remaining indices " << _indices
    216       << ", and sought size " << _matchingsize);
     183      << ", and sought size " << _matching.size()+_matchingsize);
    217184  //!> threshold for L1 error below which matching is immediately acceptable
    218185  const double L1THRESHOLD = 1e-2;
    219186  if (!_MCS.foundflag) {
    220     LOG(3, "INFO: Current matching has size " << _matching.size() << " of " << _matchingsize);
    221     if (_matching.size() < _matchingsize) {
     187    LOG(4, "DEBUG: Current matching has size " << _matching.size() << ", places left " << _matchingsize);
     188    if (_matchingsize > 0) {
    222189      // go through all indices
    223190      for (IndexList_t::iterator iter = _indices.begin();
    224           iter != _indices.end();) {
     191          (iter != _indices.end()) && (!_MCS.foundflag);) {
    225192        // add index to matching
    226193        _matching.push_back(*iter);
    227         LOG(4, "DEBUG: Adding " << *iter << " to matching.");
     194        LOG(5, "DEBUG: Adding " << *iter << " to matching.");
    228195        // remove index but keep iterator to position (is the next to erase element)
    229196        IndexList_t::iterator backupiter = _indices.erase(iter);
     
    237204      }
    238205      // gone through all indices then exit recursion
    239       _MCS.foundflag = true;
     206      if (_matching.empty())
     207        _MCS.foundflag = true;
    240208    } else {
    241209      LOG(3, "INFO: Found matching " << _matching);
     
    246214        _MCS.bestmatching = _matching;
    247215        _MCS.foundflag = true;
    248       }
    249       if (_MCS.bestL2 > errors.second) {
     216      } else if (_MCS.bestL2 > errors.second) {
    250217        _MCS.bestmatching = _matching;
    251218        _MCS.bestL2 = errors.second;
     
    254221  }
    255222}
     223
     224/** Convert cartesian to polar coordinates.
     225 *
     226 * \param _cartesian vector in cartesian coordinates
     227 * \return vector containing \f$ (r,\theta, \varphi \f$ tuple for polar coordinates
     228 */
     229std::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-negative
     240      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 coordinates
     267 * \return cartesian coordinates
     268 */
     269Vector 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/** Rotates a given polygon around x, y, and z axis by the given angles.
     281 *
     282 * \param _polygon polygon whose points to rotate
     283 * \param _angles vector with rotation angles for x,y,z axis
     284 */
     285SphericalPointDistribution::Polygon_t rotatePolygon(
     286    const SphericalPointDistribution::Polygon_t &_polygon,
     287    const std::vector<double> &_angles)
     288{
     289  SphericalPointDistribution::Polygon_t rotated_polygon = _polygon;
     290  RealSpaceMatrix rotation;
     291  ASSERT( _angles.size() == 3,
     292      "rotatePolygon() - not exactly "+toString(3)+" components given.");
     293
     294  // apply rotation angles
     295  for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_polygon.begin();
     296      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);
     309  }
     310
     311  return rotated_polygon;
     312}
     313
    256314
    257315SphericalPointDistribution::Polygon_t
     
    264322  VectorArray_t remainingold(_polygon.begin(), _polygon.end());
    265323  VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end());
    266   LOG(3, "INFO: Matching old polygon " << _polygon
     324  LOG(2, "INFO: Matching old polygon " << _polygon
    267325      << " with new polygon " << _newpolygon);
    268326
     
    287345      recurseMatchings(MCS, matching, indices, matchingsize);
    288346    }
    289     LOG(3, "INFO: Best matching is " << MCS.bestmatching);
     347    LOG(2, "INFO: Best matching is " << MCS.bestmatching);
    290348
    291349    // determine rotation angles to align the two point distributions with
    292350    // respect to bestmatching
    293     std::vector<double> angles(3);
     351    std::vector<double> angles(NDIM);
    294352    Vector newCenter;
     353    Vector oldCenter;
    295354    {
    296355      // calculate center of triangle/line/point consisting of first points of matching
    297       Vector oldCenter;
    298356      IndexList_t::const_iterator iter = MCS.bestmatching.begin();
    299357      unsigned int i = 0;
     
    304362      oldCenter *= 1./(double)i;
    305363      newCenter *= 1./(double)i;
    306       LOG(3, "INFO: oldCenter is " << oldCenter << ", newCenter is " << newCenter);
    307 
    308       Vector direction(0.,0.,0.);
    309       for(size_t i=0;i<NDIM;++i) {
    310         // create new rotation axis
    311         direction[i] = 1.;
    312         const Line axis (zeroVec, direction);
    313         // calculate rotation angle for this axis
    314         const double alpha = direction.Angle(oldCenter) - direction.Angle(newCenter);
    315         // perform rotation
    316         axis.rotateVector(newCenter, alpha);
    317         // store angle
    318         angles[i] = alpha;
    319         // reset direction component for next iteration
    320         direction[i] = 0.;
    321       }
    322     }
    323     LOG(3, "INFO: (x,y,z) angles are" << angles);
    324     const Line RotationAxis(zeroVec, newCenter);
    325     const double RotationAngle =
    326         newCenter.Angle(remainingold[0])
    327         - newCenter.Angle(remainingnew[*MCS.bestmatching.begin()]);
    328     LOG(3, "INFO: Rotate around self is " << RotationAngle
    329         << " around axis " << RotationAxis);
    330 
     364      LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter);
     365
     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    }
    331377    // rotate _newpolygon
    332378    SphericalPointDistribution::Polygon_t rotated_newpolygon =
    333         rotatePolygon(_newpolygon, angles, RotationAxis, RotationAngle);
    334     LOG(3, "INFO: Rotated new polygon is " << rotated_newpolygon);
     379        rotatePolygon(_newpolygon, angles);
     380    LOG(5, "DEBUG: Rotated new polygon is " << rotated_newpolygon);
     381
     382    const Line RotationAxis(zeroVec, oldCenter);
     383    const double RotationAngle =
     384        oldCenter.Angle(remainingold[0])
     385        - oldCenter.Angle(remainingnew[*MCS.bestmatching.begin()]);
     386    LOG(5, "DEBUG: Rotate around self is " << RotationAngle
     387        << " around axis " << RotationAxis);
     388
     389    for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_newpolygon.begin();
     390        iter != rotated_newpolygon.end(); ++iter) {
     391      RotationAxis.rotateVector(*iter, RotationAngle);
     392    }
    335393
    336394    // remove all points in matching and return remaining ones
    337     return removeMatchingPoints(rotated_newpolygon, MCS.bestmatching);
     395    SphericalPointDistribution::Polygon_t remainingpoints =
     396        removeMatchingPoints(rotated_newpolygon, MCS.bestmatching);
     397    LOG(2, "INFO: Remaining points are " << remainingpoints);
     398    return remainingpoints;
    338399  } else
    339400    return _newpolygon;
  • src/Fragmentation/Exporters/unittests/Makefile.am

    r90426a r0d5ca7  
    1818
    1919TESTS += $(FRAGMENTATIONEXPORTERSTESTS)
    20 XFAIL_TESTS += SphericalPointDistributionUnitTest
    2120check_PROGRAMS += $(FRAGMENTATIONEXPORTERSTESTS)
    2221noinst_PROGRAMS += $(FRAGMENTATIONEXPORTERSTESTS)
Note: See TracChangeset for help on using the changeset viewer.