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