Ignore:
Timestamp:
May 25, 2016, 7:13:59 AM (9 years ago)
Author:
Frederik Heber <heber@…>
Children:
66700f2
Parents:
4d611d
git-author:
Frederik Heber <heber@…> (07/09/14 21:14:53)
git-committer:
Frederik Heber <heber@…> (05/25/16 07:13:59)
Message:

Refactoring SphericalPointDistribution to combine point list and subset of indices.

File:
1 edited

Legend:

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

    r4d611d r4b96da  
    9999}
    100100
     101/** Calculate the center of a given set of points in \a _positions but only
     102 * for those indicated by \a _indices.
     103 *
     104 */
     105inline
     106Vector calculateCenter(
     107    const SphericalPointDistribution::PolygonWithIndices &_polygon)
     108{
     109  return calculateCenter(_polygon.polygon, _polygon.indices);
     110}
     111
    101112inline
    102113DistanceArray_t calculatePairwiseDistances(
     
    177188    Vector &_oldCenter,
    178189    Vector &_newCenter,
    179     const SphericalPointDistribution::VectorArray_t &_referencepositions,
    180     const SphericalPointDistribution::VectorArray_t &_currentpositions,
    181     const SphericalPointDistribution::IndexList_t &_bestmatching)
    182 {
    183   const size_t NumberIds = std::min(_bestmatching.size(), (size_t)3);
    184   SphericalPointDistribution::IndexList_t continuousIds(NumberIds, -1);
    185   std::generate(continuousIds.begin(), continuousIds.end(), UniqueNumber);
    186   _oldCenter = calculateCenter(_referencepositions, continuousIds);
     190    const SphericalPointDistribution::PolygonWithIndices &_referencepositions,
     191    const SphericalPointDistribution::PolygonWithIndices &_currentpositions)
     192{
     193  _oldCenter = calculateCenter(_referencepositions.polygon, _referencepositions.indices);
    187194  // C++11 defines a copy_n function ...
    188   SphericalPointDistribution::IndexList_t::const_iterator enditer = _bestmatching.begin();
    189   std::advance(enditer, NumberIds);
    190   SphericalPointDistribution::IndexList_t firstbestmatchingIds(NumberIds, -1);
    191   std::copy(_bestmatching.begin(), enditer, firstbestmatchingIds.begin());
    192   _newCenter = calculateCenter( _currentpositions, firstbestmatchingIds);
     195  _newCenter = calculateCenter( _currentpositions.polygon, _currentpositions.indices);
    193196}
    194197/** Returns squared L2 error of the given \a _Matching.
     
    251254
    252255SphericalPointDistribution::Polygon_t SphericalPointDistribution::removeMatchingPoints(
    253     const VectorArray_t &_points,
    254     const IndexList_t &_matchingindices
     256    const PolygonWithIndices &_points
    255257    )
    256258{
    257   SphericalPointDistribution::Polygon_t remainingreturnpolygon;
    258   IndexArray_t indices(_matchingindices.begin(), _matchingindices.end());
     259  SphericalPointDistribution::Polygon_t remainingpoints;
     260  IndexArray_t indices(_points.indices.begin(), _points.indices.end());
    259261  std::sort(indices.begin(), indices.end());
    260262  LOG(4, "DEBUG: sorted matching is " << indices);
    261   IndexArray_t remainingindices(_points.size(), -1);
     263  IndexArray_t remainingindices(_points.polygon.size(), -1);
    262264  std::generate(remainingindices.begin(), remainingindices.end(), UniqueNumber);
    263265  IndexArray_t::iterator remainiter = std::set_difference(
     
    269271  for (IndexArray_t::const_iterator iter = remainingindices.begin();
    270272      iter != remainingindices.end(); ++iter) {
    271           remainingreturnpolygon.push_back(_points[*iter]);
    272   }
    273 
    274   return remainingreturnpolygon;
     273    remainingpoints.push_back(_points.polygon[*iter]);
     274  }
     275
     276  return remainingpoints;
    275277}
    276278
     
    501503
    502504SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPlaneAligningRotation(
    503     const VectorArray_t &_referencepositions,
    504     const VectorArray_t &_currentpositions,
    505     const IndexList_t &_bestmatching
     505    const PolygonWithIndices &_referencepositions,
     506    const PolygonWithIndices &_currentpositions
    506507    )
    507508{
     
    518519  calculateOldAndNewCenters(
    519520      oldCenter, newCenter,
    520       _referencepositions, _currentpositions, _bestmatching);
     521      _referencepositions, _currentpositions);
    521522
    522523  if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) {
     
    536537    if ((oldCenter.IsZero()) && (newCenter.IsZero())) {
    537538      // either oldCenter or newCenter (or both) is directly at origin
    538       if (_bestmatching.size() == 2) {
     539      if (_currentpositions.indices.size() == 2) {
    539540        // line case
    540         Vector oldPosition = _currentpositions[*_bestmatching.begin()];
    541         Vector newPosition = _referencepositions[0];
     541        Vector oldPosition = _currentpositions.polygon[*_currentpositions.indices.begin()];
     542        Vector newPosition = _referencepositions.polygon[0];
    542543        // check whether we need to rotate at all
    543544        if (!oldPosition.IsEqualTo(newPosition)) {
     
    553554        // both triangles/planes have same center, hence get axis by
    554555        // VectorProduct of Normals
    555         Plane newplane(_referencepositions[0], _referencepositions[1], _referencepositions[2]);
     556        Plane newplane(_referencepositions.polygon[0], _referencepositions.polygon[1], _referencepositions.polygon[2]);
    556557        VectorArray_t vectors;
    557         for (IndexList_t::const_iterator iter = _bestmatching.begin();
    558             iter != _bestmatching.end(); ++iter)
    559           vectors.push_back(_currentpositions[*iter]);
     558        for (IndexList_t::const_iterator iter = _currentpositions.indices.begin();
     559            iter != _currentpositions.indices.end(); ++iter)
     560          vectors.push_back(_currentpositions.polygon[*iter]);
    560561        Plane oldplane(vectors[0], vectors[1], vectors[2]);
    561562        Vector oldPosition = oldplane.getNormal();
     
    603604
    604605SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPointAligningRotation(
    605     const VectorArray_t &remainingold,
    606     const VectorArray_t &remainingnew,
    607     const IndexList_t &_bestmatching)
     606    const PolygonWithIndices &remainingold,
     607    const PolygonWithIndices &remainingnew)
    608608{
    609609  // initialize rotation to zero
     
    618618  calculateOldAndNewCenters(
    619619      oldCenter, newCenter,
    620       remainingold, remainingnew, _bestmatching);
    621 
    622   Vector oldPosition = remainingnew[*_bestmatching.begin()];
    623   Vector newPosition = remainingold[0];
    624   LOG(6, "DEBUG: oldPosition is " << oldPosition << " and newPosition is " << newPosition);
     620      remainingold, remainingnew);
     621
     622  Vector oldPosition = remainingnew.polygon[*remainingnew.indices.begin()];
     623  Vector newPosition = remainingold.polygon[0];
     624  LOG(6, "DEBUG: oldPosition is " << oldPosition << " (length: "
     625      << oldPosition.Norm() << ") and newPosition is " << newPosition << " length(: "
     626      << newPosition.Norm() << ")");
    625627  if (!oldPosition.IsEqualTo(newPosition)) {
    626628    if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) {
    627       oldCenter.Normalize();  // note weighted sum of normalized weight is not normalized
     629      // we rotate at oldCenter and around the radial direction, which is again given
     630      // by oldCenter.
    628631      Rotation.first = oldCenter;
    629       LOG(6, "DEBUG: Picking normalized oldCenter as Rotation.first " << oldCenter);
    630       oldPosition.ProjectOntoPlane(Rotation.first);
    631       newPosition.ProjectOntoPlane(Rotation.first);
     632      Rotation.first.Normalize();  // note weighted sum of normalized weight is not normalized
     633      LOG(6, "DEBUG: Using oldCenter " << oldCenter << " as rotation center and "
     634          << Rotation.first << " as axis.");
     635      oldPosition -= oldCenter;
     636      newPosition -= oldCenter;
     637      oldPosition = (oldPosition - oldPosition.Projection(Rotation.first));
     638      newPosition = (newPosition - newPosition.Projection(Rotation.first));
    632639      LOG(6, "DEBUG: Positions after projection are " << oldPosition << " and " << newPosition);
    633640    } else {
    634       if (_bestmatching.size() == 2) {
     641      if (remainingnew.indices.size() == 2) {
    635642        // line situation
    636643        try {
     
    653660      } else {
    654661        // triangle situation
    655         Plane oldplane(remainingold[0], remainingold[1], remainingold[2]);
     662        Plane oldplane(remainingold.polygon[0], remainingold.polygon[1], remainingold.polygon[2]);
    656663        Rotation.first = oldplane.getNormal();
    657664        LOG(6, "DEBUG: oldPlane is " << oldplane << " and normal is " << Rotation.first);
     
    678685{
    679686  SphericalPointDistribution::Polygon_t remainingpoints;
    680   VectorArray_t remainingold;
    681   for (WeightedPolygon_t::const_iterator iter = _polygon.begin();
    682       iter != _polygon.end(); ++iter)
    683     remainingold.push_back(iter->first);
     687
    684688  LOG(2, "INFO: Matching old polygon " << _polygon
    685689      << " with new polygon " << _newpolygon);
     
    695699    LOG(2, "INFO: Best matching is " << bestmatching);
    696700
    697     // _newpolygon has changed, so now convert to array
    698     VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end());
     701    const size_t NumberIds = std::min(bestmatching.size(), (size_t)3);
     702    // create old set
     703    PolygonWithIndices oldSet;
     704    oldSet.indices.resize(NumberIds, -1);
     705    std::generate(oldSet.indices.begin(), oldSet.indices.end(), UniqueNumber);
     706    for (WeightedPolygon_t::const_iterator iter = _polygon.begin();
     707        iter != _polygon.end(); ++iter)
     708      oldSet.polygon.push_back(iter->first);
     709
     710    // _newpolygon has changed, so now convert to array with matched indices
     711    PolygonWithIndices newSet;
     712    SphericalPointDistribution::IndexList_t::const_iterator beginiter = bestmatching.begin();
     713    SphericalPointDistribution::IndexList_t::const_iterator enditer = bestmatching.begin();
     714    std::advance(enditer, NumberIds);
     715    newSet.indices.resize(NumberIds, -1);
     716    std::copy(beginiter, enditer, newSet.indices.begin());
     717    std::copy(_newpolygon.begin(),_newpolygon.end(), std::back_inserter(newSet.polygon));
    699718
    700719    // determine rotation angles to align the two point distributions with
     
    702721    // we use the center between the three first matching points
    703722    /// the first rotation brings these two centers to coincide
    704     VectorArray_t rotated_newpolygon = remainingnew;
     723    PolygonWithIndices rotatednewSet = newSet;
    705724    {
    706       Rotation_t Rotation = findPlaneAligningRotation(
    707           remainingold,
    708           remainingnew,
    709           bestmatching);
     725      Rotation_t Rotation = findPlaneAligningRotation(oldSet, newSet);
    710726      LOG(5, "DEBUG: Rotating coordinate system by " << Rotation.second
    711727          << " around axis " << Rotation.first);
     
    713729
    714730      // apply rotation angle to bring newCenter to oldCenter
    715       for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
    716           iter != rotated_newpolygon.end(); ++iter) {
     731      for (VectorArray_t::iterator iter = rotatednewSet.polygon.begin();
     732          iter != rotatednewSet.polygon.end(); ++iter) {
    717733        Vector &current = *iter;
    718734        LOG(6, "DEBUG: Original point is " << current);
     
    728744        calculateOldAndNewCenters(
    729745            oldCenter, rotatednewCenter,
    730             remainingold, rotated_newpolygon, bestmatching);
     746            oldSet, rotatednewSet);
    731747        // NOTE: Center must not necessarily lie on the sphere with norm 1, hence, we
    732748        // have to normalize it just as before, as oldCenter and newCenter lengths may differ.
     
    736752          LOG(4, "CHECK: rotatednewCenter is " << rotatednewCenter
    737753              << ", oldCenter is " << oldCenter);
    738           ASSERT( (rotatednewCenter - oldCenter).NormSquared() < std::numeric_limits<double>::epsilon()*1e4,
     754          const double difference = (rotatednewCenter - oldCenter).NormSquared();
     755          ASSERT( difference < std::numeric_limits<double>::epsilon()*1e4,
    739756              "matchSphericalPointDistributions() - rotation does not work as expected by "
    740               +toString((rotatednewCenter - oldCenter).NormSquared())+".");
     757              +toString(difference)+".");
    741758        }
    742759      }
     
    746763    /// points themselves coincide
    747764    if (bestmatching.size() > 1) {
    748       Rotation_t Rotation = findPointAligningRotation(
    749           remainingold,
    750           rotated_newpolygon,
    751           bestmatching);
     765      Rotation_t Rotation = findPointAligningRotation(oldSet, rotatednewSet);
    752766
    753767      // construct RotationAxis and two points on its plane, defining the angle
     
    763777      {
    764778        const IndexList_t::const_iterator iter = bestmatching.begin();
     779
     780        // check whether both old and newPosition are at same distance to oldCenter
     781        Vector oldCenter = calculateCenter(oldSet);
     782        const double distance = fabs(
     783              (oldSet.polygon[0] - oldCenter).NormSquared()
     784              - (rotatednewSet.polygon[*iter] - oldCenter).NormSquared()
     785            );
     786        LOG(4, "CHECK: Squared distance between oldPosition and newPosition "
     787            << " with respect to oldCenter " << oldCenter << " is " << distance);
     788//        ASSERT( distance < warn_amplitude,
     789//            "matchSphericalPointDistributions() - old and newPosition's squared distance to oldCenter differs by "
     790//            +toString(distance));
     791
    765792        Vector rotatednew = RotationAxis.rotateVector(
    766             rotated_newpolygon[*iter],
     793            rotatednewSet.polygon[*iter],
    767794            Rotation.second);
    768795        LOG(4, "CHECK: rotated first new bestmatching is " << rotatednew
    769             << " while old was " << remainingold[0]);
    770         ASSERT( (rotatednew - remainingold[0]).Norm() < warn_amplitude,
    771             "matchSphericalPointDistributions() - orientation rotation ends up off by more than "
    772             +toString(warn_amplitude)+".");
     796            << " while old was " << oldSet.polygon[0]);
     797        const double difference = (rotatednew - oldSet.polygon[0]).NormSquared();
     798        ASSERT( difference < distance+1e-8,
     799            "matchSphericalPointDistributions() - orientation rotation ends up off by "
     800            +toString(difference)+", more than "
     801            +toString(distance+1e-8)+".");
    773802      }
    774803#endif
    775804
    776       for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
    777           iter != rotated_newpolygon.end(); ++iter) {
     805      for (VectorArray_t::iterator iter = rotatednewSet.polygon.begin();
     806          iter != rotatednewSet.polygon.end(); ++iter) {
    778807        Vector &current = *iter;
    779808        LOG(6, "DEBUG: Original point is " << current);
     
    785814    // remove all points in matching and return remaining ones
    786815    SphericalPointDistribution::Polygon_t remainingpoints =
    787         removeMatchingPoints(rotated_newpolygon, bestmatching);
     816        removeMatchingPoints(rotatednewSet);
    788817    LOG(2, "INFO: Remaining points are " << remainingpoints);
    789818    return remainingpoints;
Note: See TracChangeset for help on using the changeset viewer.