7e9eb1
shun-iwasawa ec85ad
#ifndef NDEBUG
7e9eb1
d8eddc
#include <tools modifiers="" modifiertest.h=""></tools>
7e9eb1
d8eddc
// std includes
d8eddc
#include <cmath></cmath>
7e9eb1
bdb1e2
7e9eb1
//*****************************************************************************************
bdb1e2
//    TModifierTest::Interpolator implementation
7e9eb1
//*****************************************************************************************
7e9eb1
bdb1e2
TTrackPoint TModifierTest::Interpolator::interpolateFromOriginal(double originalIndex) {
bdb1e2
  Handler *handler = track.original
bdb1e2
                   ? dynamic_cast<handler*>(track.original->handler.getPointer())</handler*>
bdb1e2
                   : nullptr;
bdb1e2
  if (!handler)
bdb1e2
    return track.interpolateLinear(track.indexByOriginalIndex(originalIndex));
bdb1e2
  
bdb1e2
  TTrackPoint p = track.calcPointFromOriginal(originalIndex);
bdb1e2
bdb1e2
  double frac;
bdb1e2
  int i0 = track.original->floorIndex(originalIndex, &frac);
bdb1e2
  int i1 = track.original->ceilIndex(originalIndex);
bdb1e2
bdb1e2
  double angle = TTrack::interpolationLinear(
bdb1e2
    handler->angles[i0], handler->angles[i1], frac );
d04010
  double a = angle*speed + this->angle;
d04010
d04010
  double kr = 1 - 1/(angle + 1);
d04010
  double s = sin(a);
d04010
  double r = radius*p.pressure*kr*s;
bdb1e2
  
bdb1e2
  double d = fabs(2.0*radius);
bdb1e2
  if (fabs(speed) > TConsts::epsilon)
bdb1e2
    d /= fabs(speed);
bdb1e2
bdb1e2
  TPointD tangent = track.original->calcTangent(originalIndex, d);
d04010
  p.position.x -= tangent.y * r;
d04010
  p.position.y += tangent.x * r;
bdb1e2
  p.pressure *= fabs(s);
7e9eb1
7e9eb1
  return p;
7e9eb1
}
7e9eb1
bdb1e2
bdb1e2
TTrackPoint TModifierTest::Interpolator::interpolate(double index) {
bdb1e2
  return interpolateFromOriginal(track.originalIndexByIndex(index));
bdb1e2
}
bdb1e2
bdb1e2
7e9eb1
//*****************************************************************************************
7e9eb1
//    TModifierTest implementation
7e9eb1
//*****************************************************************************************
7e9eb1
bdb1e2
TModifierTest::TModifierTest(int count, double radius, double speed)
bdb1e2
    : count(count), radius(radius), speed(speed) {}
7e9eb1
shun-iwasawa ec85ad
void TModifierTest::modifyTrack(const TTrack &track,
shun-iwasawa ec85ad
                                TTrackList &outTracks) {
shun-iwasawa ec85ad
  const double segmentSize = 2.0 * M_PI / 10.0;
7e9eb1
bdb1e2
  if ( !track.handler
bdb1e2
    && track.getKeyState(track.front().time).isPressed(TKey::alt) )
bdb1e2
  {
bdb1e2
    Handler *handler = new Handler(this->radius);
bdb1e2
    track.handler = handler;
bdb1e2
    for (int i = 0; i < count; ++i) {
bdb1e2
      handler->tracks.push_back(new TTrack(track));
bdb1e2
      TTrack &subTrack = *handler->tracks.back();
bdb1e2
      new Interpolator(subTrack, i*2*M_PI/(double)count, radius, 0.25);
7e9eb1
    }
7e9eb1
  }
bdb1e2
  
bdb1e2
  Handler *handler = dynamic_cast<handler*>(track.handler.getPointer());</handler*>
bdb1e2
  if (!handler)
bdb1e2
    return TInputModifier::modifyTrack(track, outTracks);
bdb1e2
  
bdb1e2
  outTracks.insert(outTracks.end(), handler->tracks.begin(), handler->tracks.end());
bdb1e2
  if (!track.changed())
7e9eb1
    return;
7e9eb1
bdb1e2
  double radius = handler->radius;
c3c215
  int start = track.size() - track.pointsAdded;
7e9eb1
  if (start < 0) start = 0;
7e9eb1
7e9eb1
  // remove angles
bdb1e2
  handler->angles.resize(start);
bdb1e2
  
7e9eb1
  // add angles
bdb1e2
  for(int i = start; i < track.size(); ++i) {
bdb1e2
    if (i) {
bdb1e2
      const TTrackPoint &p0 = track[i - 1];
bdb1e2
      const TTrackPoint &p1 = track[i];
bdb1e2
      double dl = p1.length - p0.length;
bdb1e2
      double da = p1.pressure > TConsts::epsilon
bdb1e2
                ? dl / (radius * p1.pressure)
bdb1e2
                : 0.0;
bdb1e2
      handler->angles.push_back(handler->angles.back() + da);
7e9eb1
    } else {
7e9eb1
      handler->angles.push_back(0.0);
7e9eb1
    }
7e9eb1
  }
bdb1e2
  
7e9eb1
  // process sub-tracks
bdb1e2
  for(TTrackList::const_iterator ti = handler->tracks.begin(); ti != handler->tracks.end(); ++ti) {
bdb1e2
    TTrack &subTrack = **ti;
bdb1e2
    Interpolator *intr = dynamic_cast<interpolator*>(subTrack.getInterpolator().getPointer());</interpolator*>
bdb1e2
    if (!intr)
bdb1e2
      continue;
bdb1e2
    
9f0c16
    double currentSegmentSize = segmentSize;
bdb1e2
    if (fabs(intr->speed) > TConsts::epsilon)
bdb1e2
      currentSegmentSize /= fabs(intr->speed);
7e9eb1
7e9eb1
    // remove points
bdb1e2
    int subStart = start > 0
bdb1e2
                 ? subTrack.floorIndex(subTrack.indexByOriginalIndex(start - 1)) + 1
bdb1e2
                 : 0;
00337d
    subTrack.truncate(subStart);
7e9eb1
7e9eb1
    // add points
shun-iwasawa ec85ad
    for (int i = start; i < track.size(); ++i) {
7e9eb1
      if (i > 0) {
shun-iwasawa ec85ad
        double prevAngle = handler->angles[i - 1];
7e9eb1
        double nextAngle = handler->angles[i];
shun-iwasawa ec85ad
        if (fabs(nextAngle - prevAngle) > 1.5 * currentSegmentSize) {
shun-iwasawa ec85ad
          double step = currentSegmentSize / fabs(nextAngle - prevAngle);
shun-iwasawa ec85ad
          double end  = 1.0 - 0.5 * step;
shun-iwasawa ec85ad
          for (double frac = step; frac < end; frac += step)
shun-iwasawa ec85ad
            subTrack.push_back(
bdb1e2
                intr->interpolateFromOriginal(i - 1 + frac), false );
7e9eb1
        }
7e9eb1
      }
bdb1e2
      subTrack.push_back(intr->interpolateFromOriginal(i), false);
7e9eb1
    }
7d1790
    
7d1790
    // fix points
bdb1e2
    if (track.fixedFinished())
bdb1e2
      subTrack.fix_all();
7d1790
    if (track.fixedSize())
7d1790
      subTrack.fix_to(
7d1790
        subTrack.floorIndex(subTrack.indexByOriginalIndex(track.fixedSize() - 1)) + 1 );
7e9eb1
  }
bdb1e2
  
00337d
  track.resetChanges();
7e9eb1
}
7e9eb1
7d1790
#endif