Ignore:
Timestamp:
Aug 20, 2014, 1:04:08 PM (11 years ago)
Author:
Frederik Heber <heber@…>
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)
Message:

Using the idea of three points giving a triangle to find rotation axis.

  • we calculate the center of either triangle and rotate the center of the ideal point distribution to match the one from the given points.
  • next we have the triangles normals as axis, take the first matching point and rotate align it.
  • we have to deal with a lot of special cases: What if only zero, one, or two points are given ...
  • in general we assume that the triangle lies relatively flat on the sphere's surface but what if the origin is in the triangle plane or even the calculated center is at the origin ...
  • TESTS: SphericalPointDistributionUnitTest working again, regression tests FragmentMolecule-cylces and StoreSaturatedFragment working.
File:
1 edited

Legend:

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

    r6aa6b7 r3da643  
    5353
    5454#include "LinearAlgebra/Line.hpp"
     55#include "LinearAlgebra/Plane.hpp"
    5556#include "LinearAlgebra/RealSpaceMatrix.hpp"
    5657#include "LinearAlgebra/Vector.hpp"
    5758
    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
     60const double SphericalPointDistribution::warn_amplitude = 1e-2;
     61
    6162typedef std::vector<double> DistanceArray_t;
    6263
     64inline
    6365DistanceArray_t calculatePairwiseDistances(
    6466    const std::vector<Vector> &_points,
    65     const IndexList_t &_indices
     67    const SphericalPointDistribution::IndexList_t &_indices
    6668    )
    6769{
    6870  DistanceArray_t result;
    69   for (IndexList_t::const_iterator firstiter = _indices.begin();
     71  for (SphericalPointDistribution::IndexList_t::const_iterator firstiter = _indices.begin();
    7072      firstiter != _indices.end(); ++firstiter) {
    71     for (IndexList_t::const_iterator seconditer = firstiter;
     73    for (SphericalPointDistribution::IndexList_t::const_iterator seconditer = firstiter;
    7274        seconditer != _indices.end(); ++seconditer) {
    7375      if (firstiter == seconditer)
     
    98100 * \return pair with L1 and squared L2 error
    99101 */
    100 std::pair<double, double> calculateErrorOfMatching(
     102std::pair<double, double> SphericalPointDistribution::calculateErrorOfMatching(
    101103    const std::vector<Vector> &_old,
    102104    const std::vector<Vector> &_new,
     
    135137}
    136138
    137 SphericalPointDistribution::Polygon_t removeMatchingPoints(
     139SphericalPointDistribution::Polygon_t SphericalPointDistribution::removeMatchingPoints(
    138140    const VectorArray_t &_points,
    139141    const IndexList_t &_matchingindices
     
    160162}
    161163
    162 struct MatchingControlStructure {
    163   bool foundflag;
    164   double bestL2;
    165   IndexList_t bestmatching;
    166   VectorArray_t oldpoints;
    167   VectorArray_t newpoints;
    168 };
    169 
    170164/** Recursive function to go through all possible matchings.
    171165 *
     
    175169 * \param _matchingsize
    176170 */
    177 void recurseMatchings(
     171void SphericalPointDistribution::recurseMatchings(
    178172    MatchingControlStructure &_MCS,
    179173    IndexList_t &_matching,
     
    224218}
    225219
    226 /** Rotates a given polygon around x, y, and z axis by the given angles.
    227  *
    228  * \param _polygon polygon whose points to rotate
    229  * \param _q quaternion specifying the rotation of the coordinate system
     220/** 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
    230224 */
    231 SphericalPointDistribution::Polygon_t rotatePolygon(
     225inline
     226double 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 */
     255SphericalPointDistribution::IndexList_t SphericalPointDistribution::findBestMatching(
    232256    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 &current = *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
     282inline
     283Vector 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
     298inline
     299void 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
     318SphericalPointDistribution::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
     420SphericalPointDistribution::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;
    253486}
    254487
     
    266499      << " with new polygon " << _newpolygon);
    267500
     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
    268507  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;
    276516    {
    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 &current = *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 &current = *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())+".");
    324552        }
    325553      }
    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);
    349570
    350571#ifndef NDEBUG
    351         // check: first bestmatching in rotated_newpolygon and remainingnew
    352         // should now equal
    353         {
    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 " << rotatednew
    359               << " 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      }
    364585#endif
    365586
    366         for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
    367             iter != rotated_newpolygon.end(); ++iter) {
    368           Vector &current = *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 &current = *iter;
     590        LOG(6, "DEBUG: Original point is " << current);
     591        current = RotationAxis.rotateVector(current, Rotation.second);
     592        LOG(6, "DEBUG: Rotated point is " << current);
    373593      }
    374594    }
     
    376596    // remove all points in matching and return remaining ones
    377597    SphericalPointDistribution::Polygon_t remainingpoints =
    378         removeMatchingPoints(rotated_newpolygon, MCS.bestmatching);
     598        removeMatchingPoints(rotated_newpolygon, bestmatching);
    379599    LOG(2, "INFO: Remaining points are " << remainingpoints);
    380600    return remainingpoints;
Note: See TracChangeset for help on using the changeset viewer.