Ignore:
Timestamp:
Aug 20, 2014, 1:06:16 PM (11 years ago)
Author:
Frederik Heber <heber@…>
Children:
a2f8a9
Parents:
23c605
git-author:
Frederik Heber <heber@…> (07/09/14 21:14:53)
git-committer:
Frederik Heber <heber@…> (08/20/14 13:06:16)
Message:

Refactoring SphericalPointDistribution to combine point list and subset of indices.

File:
1 edited

Legend:

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

    r23c605 r1cde4e8  
    9898}
    9999
     100/** Calculate the center of a given set of points in \a _positions but only
     101 * for those indicated by \a _indices.
     102 *
     103 */
     104inline
     105Vector calculateCenter(
     106    const SphericalPointDistribution::PolygonWithIndices &_polygon)
     107{
     108  return calculateCenter(_polygon.polygon, _polygon.indices);
     109}
     110
    100111inline
    101112DistanceArray_t calculatePairwiseDistances(
     
    176187    Vector &_oldCenter,
    177188    Vector &_newCenter,
    178     const SphericalPointDistribution::VectorArray_t &_referencepositions,
    179     const SphericalPointDistribution::VectorArray_t &_currentpositions,
    180     const SphericalPointDistribution::IndexList_t &_bestmatching)
    181 {
    182   const size_t NumberIds = std::min(_bestmatching.size(), (size_t)3);
    183   SphericalPointDistribution::IndexList_t continuousIds(NumberIds, -1);
    184   std::generate(continuousIds.begin(), continuousIds.end(), UniqueNumber);
    185   _oldCenter = calculateCenter(_referencepositions, continuousIds);
     189    const SphericalPointDistribution::PolygonWithIndices &_referencepositions,
     190    const SphericalPointDistribution::PolygonWithIndices &_currentpositions)
     191{
     192  _oldCenter = calculateCenter(_referencepositions.polygon, _referencepositions.indices);
    186193  // C++11 defines a copy_n function ...
    187   SphericalPointDistribution::IndexList_t::const_iterator enditer = _bestmatching.begin();
    188   std::advance(enditer, NumberIds);
    189   SphericalPointDistribution::IndexList_t firstbestmatchingIds(NumberIds, -1);
    190   std::copy(_bestmatching.begin(), enditer, firstbestmatchingIds.begin());
    191   _newCenter = calculateCenter( _currentpositions, firstbestmatchingIds);
     194  _newCenter = calculateCenter( _currentpositions.polygon, _currentpositions.indices);
    192195}
    193196/** Returns squared L2 error of the given \a _Matching.
     
    250253
    251254SphericalPointDistribution::Polygon_t SphericalPointDistribution::removeMatchingPoints(
    252     const VectorArray_t &_points,
    253     const IndexList_t &_matchingindices
     255    const PolygonWithIndices &_points
    254256    )
    255257{
    256258  SphericalPointDistribution::Polygon_t remainingpoints;
    257   IndexArray_t indices(_matchingindices.begin(), _matchingindices.end());
     259  IndexArray_t indices(_points.indices.begin(), _points.indices.end());
    258260  std::sort(indices.begin(), indices.end());
    259261  LOG(4, "DEBUG: sorted matching is " << indices);
    260   IndexArray_t remainingindices(_points.size(), -1);
     262  IndexArray_t remainingindices(_points.polygon.size(), -1);
    261263  std::generate(remainingindices.begin(), remainingindices.end(), UniqueNumber);
    262264  IndexArray_t::iterator remainiter = std::set_difference(
     
    268270  for (IndexArray_t::const_iterator iter = remainingindices.begin();
    269271      iter != remainingindices.end(); ++iter) {
    270     remainingpoints.push_back(_points[*iter]);
     272    remainingpoints.push_back(_points.polygon[*iter]);
    271273  }
    272274
     
    500502
    501503SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPlaneAligningRotation(
    502     const VectorArray_t &_referencepositions,
    503     const VectorArray_t &_currentpositions,
    504     const IndexList_t &_bestmatching
     504    const PolygonWithIndices &_referencepositions,
     505    const PolygonWithIndices &_currentpositions
    505506    )
    506507{
     
    517518  calculateOldAndNewCenters(
    518519      oldCenter, newCenter,
    519       _referencepositions, _currentpositions, _bestmatching);
     520      _referencepositions, _currentpositions);
    520521
    521522  if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) {
     
    535536    if ((oldCenter.IsZero()) && (newCenter.IsZero())) {
    536537      // either oldCenter or newCenter (or both) is directly at origin
    537       if (_bestmatching.size() == 2) {
     538      if (_currentpositions.indices.size() == 2) {
    538539        // line case
    539         Vector oldPosition = _currentpositions[*_bestmatching.begin()];
    540         Vector newPosition = _referencepositions[0];
     540        Vector oldPosition = _currentpositions.polygon[*_currentpositions.indices.begin()];
     541        Vector newPosition = _referencepositions.polygon[0];
    541542        // check whether we need to rotate at all
    542543        if (!oldPosition.IsEqualTo(newPosition)) {
     
    552553        // both triangles/planes have same center, hence get axis by
    553554        // VectorProduct of Normals
    554         Plane newplane(_referencepositions[0], _referencepositions[1], _referencepositions[2]);
     555        Plane newplane(_referencepositions.polygon[0], _referencepositions.polygon[1], _referencepositions.polygon[2]);
    555556        VectorArray_t vectors;
    556         for (IndexList_t::const_iterator iter = _bestmatching.begin();
    557             iter != _bestmatching.end(); ++iter)
    558           vectors.push_back(_currentpositions[*iter]);
     557        for (IndexList_t::const_iterator iter = _currentpositions.indices.begin();
     558            iter != _currentpositions.indices.end(); ++iter)
     559          vectors.push_back(_currentpositions.polygon[*iter]);
    559560        Plane oldplane(vectors[0], vectors[1], vectors[2]);
    560561        Vector oldPosition = oldplane.getNormal();
     
    602603
    603604SphericalPointDistribution::Rotation_t SphericalPointDistribution::findPointAligningRotation(
    604     const VectorArray_t &remainingold,
    605     const VectorArray_t &remainingnew,
    606     const IndexList_t &_bestmatching)
     605    const PolygonWithIndices &remainingold,
     606    const PolygonWithIndices &remainingnew)
    607607{
    608608  // initialize rotation to zero
     
    617617  calculateOldAndNewCenters(
    618618      oldCenter, newCenter,
    619       remainingold, remainingnew, _bestmatching);
    620 
    621   Vector oldPosition = remainingnew[*_bestmatching.begin()];
    622   Vector newPosition = remainingold[0];
    623   LOG(6, "DEBUG: oldPosition is " << oldPosition << " and newPosition is " << newPosition);
     619      remainingold, remainingnew);
     620
     621  Vector oldPosition = remainingnew.polygon[*remainingnew.indices.begin()];
     622  Vector newPosition = remainingold.polygon[0];
     623  LOG(6, "DEBUG: oldPosition is " << oldPosition << " (length: "
     624      << oldPosition.Norm() << ") and newPosition is " << newPosition << " length(: "
     625      << newPosition.Norm() << ")");
    624626  if (!oldPosition.IsEqualTo(newPosition)) {
    625627    if ((!oldCenter.IsZero()) && (!newCenter.IsZero())) {
    626       oldCenter.Normalize();  // note weighted sum of normalized weight is not normalized
     628      // we rotate at oldCenter and around the radial direction, which is again given
     629      // by oldCenter.
    627630      Rotation.first = oldCenter;
    628       LOG(6, "DEBUG: Picking normalized oldCenter as Rotation.first " << oldCenter);
    629       oldPosition.ProjectOntoPlane(Rotation.first);
    630       newPosition.ProjectOntoPlane(Rotation.first);
     631      Rotation.first.Normalize();  // note weighted sum of normalized weight is not normalized
     632      LOG(6, "DEBUG: Using oldCenter " << oldCenter << " as rotation center and "
     633          << Rotation.first << " as axis.");
     634      oldPosition -= oldCenter;
     635      newPosition -= oldCenter;
     636      oldPosition = (oldPosition - oldPosition.Projection(Rotation.first));
     637      newPosition = (newPosition - newPosition.Projection(Rotation.first));
    631638      LOG(6, "DEBUG: Positions after projection are " << oldPosition << " and " << newPosition);
    632639    } else {
    633       if (_bestmatching.size() == 2) {
     640      if (remainingnew.indices.size() == 2) {
    634641        // line situation
    635642        try {
     
    652659      } else {
    653660        // triangle situation
    654         Plane oldplane(remainingold[0], remainingold[1], remainingold[2]);
     661        Plane oldplane(remainingold.polygon[0], remainingold.polygon[1], remainingold.polygon[2]);
    655662        Rotation.first = oldplane.getNormal();
    656663        LOG(6, "DEBUG: oldPlane is " << oldplane << " and normal is " << Rotation.first);
     
    677684{
    678685  SphericalPointDistribution::Polygon_t remainingpoints;
    679   VectorArray_t remainingold;
    680   for (WeightedPolygon_t::const_iterator iter = _polygon.begin();
    681       iter != _polygon.end(); ++iter)
    682     remainingold.push_back(iter->first);
     686
    683687  LOG(2, "INFO: Matching old polygon " << _polygon
    684688      << " with new polygon " << _newpolygon);
     
    694698    LOG(2, "INFO: Best matching is " << bestmatching);
    695699
    696     // _newpolygon has changed, so now convert to array
    697     VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end());
     700    const size_t NumberIds = std::min(bestmatching.size(), (size_t)3);
     701    // create old set
     702    PolygonWithIndices oldSet;
     703    oldSet.indices.resize(NumberIds, -1);
     704    std::generate(oldSet.indices.begin(), oldSet.indices.end(), UniqueNumber);
     705    for (WeightedPolygon_t::const_iterator iter = _polygon.begin();
     706        iter != _polygon.end(); ++iter)
     707      oldSet.polygon.push_back(iter->first);
     708
     709    // _newpolygon has changed, so now convert to array with matched indices
     710    PolygonWithIndices newSet;
     711    SphericalPointDistribution::IndexList_t::const_iterator beginiter = bestmatching.begin();
     712    SphericalPointDistribution::IndexList_t::const_iterator enditer = bestmatching.begin();
     713    std::advance(enditer, NumberIds);
     714    newSet.indices.resize(NumberIds, -1);
     715    std::copy(beginiter, enditer, newSet.indices.begin());
     716    std::copy(_newpolygon.begin(),_newpolygon.end(), std::back_inserter(newSet.polygon));
    698717
    699718    // determine rotation angles to align the two point distributions with
     
    701720    // we use the center between the three first matching points
    702721    /// the first rotation brings these two centers to coincide
    703     VectorArray_t rotated_newpolygon = remainingnew;
     722    PolygonWithIndices rotatednewSet = newSet;
    704723    {
    705       Rotation_t Rotation = findPlaneAligningRotation(
    706           remainingold,
    707           remainingnew,
    708           bestmatching);
     724      Rotation_t Rotation = findPlaneAligningRotation(oldSet, newSet);
    709725      LOG(5, "DEBUG: Rotating coordinate system by " << Rotation.second
    710726          << " around axis " << Rotation.first);
     
    712728
    713729      // apply rotation angle to bring newCenter to oldCenter
    714       for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
    715           iter != rotated_newpolygon.end(); ++iter) {
     730      for (VectorArray_t::iterator iter = rotatednewSet.polygon.begin();
     731          iter != rotatednewSet.polygon.end(); ++iter) {
    716732        Vector &current = *iter;
    717733        LOG(6, "DEBUG: Original point is " << current);
     
    727743        calculateOldAndNewCenters(
    728744            oldCenter, rotatednewCenter,
    729             remainingold, rotated_newpolygon, bestmatching);
     745            oldSet, rotatednewSet);
    730746        // NOTE: Center must not necessarily lie on the sphere with norm 1, hence, we
    731747        // have to normalize it just as before, as oldCenter and newCenter lengths may differ.
     
    735751          LOG(4, "CHECK: rotatednewCenter is " << rotatednewCenter
    736752              << ", oldCenter is " << oldCenter);
    737           ASSERT( (rotatednewCenter - oldCenter).NormSquared() < std::numeric_limits<double>::epsilon()*1e4,
     753          const double difference = (rotatednewCenter - oldCenter).NormSquared();
     754          ASSERT( difference < std::numeric_limits<double>::epsilon()*1e4,
    738755              "matchSphericalPointDistributions() - rotation does not work as expected by "
    739               +toString((rotatednewCenter - oldCenter).NormSquared())+".");
     756              +toString(difference)+".");
    740757        }
    741758      }
     
    745762    /// points themselves coincide
    746763    if (bestmatching.size() > 1) {
    747       Rotation_t Rotation = findPointAligningRotation(
    748           remainingold,
    749           rotated_newpolygon,
    750           bestmatching);
     764      Rotation_t Rotation = findPointAligningRotation(oldSet, rotatednewSet);
    751765
    752766      // construct RotationAxis and two points on its plane, defining the angle
     
    762776      {
    763777        const IndexList_t::const_iterator iter = bestmatching.begin();
     778
     779        // check whether both old and newPosition are at same distance to oldCenter
     780        Vector oldCenter = calculateCenter(oldSet);
     781        const double distance = fabs(
     782              (oldSet.polygon[0] - oldCenter).NormSquared()
     783              - (rotatednewSet.polygon[*iter] - oldCenter).NormSquared()
     784            );
     785        LOG(4, "CHECK: Squared distance between oldPosition and newPosition "
     786            << " with respect to oldCenter " << oldCenter << " is " << distance);
     787//        ASSERT( distance < warn_amplitude,
     788//            "matchSphericalPointDistributions() - old and newPosition's squared distance to oldCenter differs by "
     789//            +toString(distance));
     790
    764791        Vector rotatednew = RotationAxis.rotateVector(
    765             rotated_newpolygon[*iter],
     792            rotatednewSet.polygon[*iter],
    766793            Rotation.second);
    767794        LOG(4, "CHECK: rotated first new bestmatching is " << rotatednew
    768             << " while old was " << remainingold[0]);
    769         ASSERT( (rotatednew - remainingold[0]).Norm() < warn_amplitude,
    770             "matchSphericalPointDistributions() - orientation rotation ends up off by more than "
    771             +toString(warn_amplitude)+".");
     795            << " while old was " << oldSet.polygon[0]);
     796        const double difference = (rotatednew - oldSet.polygon[0]).NormSquared();
     797        ASSERT( difference < distance+1e-8,
     798            "matchSphericalPointDistributions() - orientation rotation ends up off by "
     799            +toString(difference)+", more than "
     800            +toString(distance+1e-8)+".");
    772801      }
    773802#endif
    774803
    775       for (VectorArray_t::iterator iter = rotated_newpolygon.begin();
    776           iter != rotated_newpolygon.end(); ++iter) {
     804      for (VectorArray_t::iterator iter = rotatednewSet.polygon.begin();
     805          iter != rotatednewSet.polygon.end(); ++iter) {
    777806        Vector &current = *iter;
    778807        LOG(6, "DEBUG: Original point is " << current);
     
    784813    // remove all points in matching and return remaining ones
    785814    SphericalPointDistribution::Polygon_t remainingpoints =
    786         removeMatchingPoints(rotated_newpolygon, bestmatching);
     815        removeMatchingPoints(rotatednewSet);
    787816    LOG(2, "INFO: Remaining points are " << remainingpoints);
    788817    return remainingpoints;
Note: See TracChangeset for help on using the changeset viewer.