7e9eb1
shun-iwasawa ec85ad
#ifndef NDEBUG
7e9eb1
d8eddc
#include <tools modifiers="" modifiertest.h=""></tools>
7e9eb1
d8eddc
// std includes
d8eddc
#include <cmath></cmath>
7e9eb1
7e9eb1
//*****************************************************************************************
7e9eb1
//    TModifierTest::Modifier implementation
7e9eb1
//*****************************************************************************************
7e9eb1
shun-iwasawa ec85ad
TModifierTest::Modifier::Modifier(TTrackHandler &handler, double angle,
shun-iwasawa ec85ad
                                  double radius, double speed)
shun-iwasawa ec85ad
    : TTrackModifier(handler), angle(angle), radius(radius), speed(speed) {}
7e9eb1
shun-iwasawa ec85ad
TTrackPoint TModifierTest::Modifier::calcPoint(double originalIndex) {
7e9eb1
  TTrackPoint p = TTrackModifier::calcPoint(originalIndex);
7e9eb1
9f0c16
  if (p.length > TConsts::epsilon) {
7e9eb1
    double frac;
7e9eb1
    int i0 = original.floorIndex(originalIndex, &frac);
7e9eb1
    int i1 = original.ceilIndex(originalIndex);
7e9eb1
    if (i0 < 0) return p;
7e9eb1
shun-iwasawa ec85ad
    if (Handler *handler = dynamic_cast<handler *="">(&this->handler)) {</handler>
shun-iwasawa ec85ad
      double angle = this->angle + speed * TTrack::interpolationLinear(
shun-iwasawa ec85ad
                                               handler->angles[i0],
shun-iwasawa ec85ad
                                               handler->angles[i1], frac);
shun-iwasawa ec85ad
      double radius = 2.0 * this->radius * p.pressure;
shun-iwasawa ec85ad
      double s      = sin(angle);
shun-iwasawa ec85ad
      double c      = cos(angle);
shun-iwasawa ec85ad
shun-iwasawa ec85ad
      TPointD tangent =
shun-iwasawa ec85ad
          original.calcTangent(originalIndex, fabs(2.0 * this->radius / speed));
shun-iwasawa ec85ad
      p.position.x -= tangent.y * s * radius;
shun-iwasawa ec85ad
      p.position.y += tangent.x * s * radius;
shun-iwasawa ec85ad
      p.pressure *= 1.0 - 0.5 * c;
7e9eb1
    }
7e9eb1
  } else {
7e9eb1
    p.pressure = 0.0;
7e9eb1
  }
7e9eb1
7e9eb1
  return p;
7e9eb1
}
7e9eb1
7e9eb1
//*****************************************************************************************
7e9eb1
//    TModifierTest implementation
7e9eb1
//*****************************************************************************************
7e9eb1
shun-iwasawa ec85ad
TModifierTest::TModifierTest(int count, double radius)
shun-iwasawa ec85ad
    : count(count), radius(radius) {}
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
c3c215
  if (!track.handler) {
c3c215
    if (track.getKeyState(track.front().time).isPressed(TKey(Qt::Key_Alt))) {
7e9eb1
      // TModifierTest::Handler for spiro
c3c215
      track.handler = new Handler(track);
shun-iwasawa ec85ad
      for (int i = 0; i < count; ++i)
shun-iwasawa ec85ad
        track.handler->tracks.push_back(new TTrack(new Modifier(
shun-iwasawa ec85ad
            *track.handler, i * 2.0 * M_PI / (double)count, radius, 0.25)));
7e9eb1
    }
7e9eb1
  }
7e9eb1
shun-iwasawa ec85ad
  Handler *handler = dynamic_cast<handler *="">(track.handler.getPointer());</handler>
7e9eb1
  if (!handler) {
f278a5
    TInputModifier::modifyTrack(track, outTracks);
7e9eb1
    return;
7e9eb1
  }
7e9eb1
shun-iwasawa ec85ad
  outTracks.insert(outTracks.end(), track.handler->tracks.begin(),
shun-iwasawa ec85ad
                   track.handler->tracks.end());
shun-iwasawa ec85ad
  if (!track.changed()) return;
7e9eb1
c3c215
  int start = track.size() - track.pointsAdded;
7e9eb1
  if (start < 0) start = 0;
7e9eb1
7e9eb1
  // remove angles
shun-iwasawa ec85ad
  double lastAngle = start < (int)handler->angles.size()
shun-iwasawa ec85ad
                         ? handler->angles[start]
shun-iwasawa ec85ad
                     : handler->angles.empty() ? 0.0
shun-iwasawa ec85ad
                                               : handler->angles.back();
00337d
  handler->angles.resize(start, lastAngle);
7e9eb1
7e9eb1
  // add angles
shun-iwasawa ec85ad
  for (int i = start; i < track.size(); ++i) {
7e9eb1
    if (i > 0) {
shun-iwasawa ec85ad
      double dl = track[i].length - track[i - 1].length;
9f0c16
      double da = track[i].pressure > TConsts::epsilon
shun-iwasawa ec85ad
                      ? dl / (radius * track[i].pressure)
shun-iwasawa ec85ad
                      : 0.0;
shun-iwasawa ec85ad
      handler->angles.push_back(handler->angles[i - 1] + da);
7e9eb1
    } else {
7e9eb1
      handler->angles.push_back(0.0);
7e9eb1
    }
7e9eb1
  }
7e9eb1
7e9eb1
  // process sub-tracks
shun-iwasawa ec85ad
  for (TTrackList::const_iterator ti = handler->tracks.begin();
shun-iwasawa ec85ad
       ti != handler->tracks.end(); ++ti) {
shun-iwasawa ec85ad
    TTrack &subTrack          = **ti;
9f0c16
    double currentSegmentSize = segmentSize;
shun-iwasawa ec85ad
    if (const Modifier *modifier =
shun-iwasawa ec85ad
            dynamic_cast<const *="" modifier="">(subTrack.modifier.getPointer()))</const>
9f0c16
      if (fabs(modifier->speed) > TConsts::epsilon)
shun-iwasawa ec85ad
        currentSegmentSize = segmentSize / fabs(modifier->speed);
7e9eb1
7e9eb1
    // remove points
shun-iwasawa ec85ad
    int subStart =
shun-iwasawa ec85ad
        subTrack.floorIndex(subTrack.indexByOriginalIndex(start - 1)) + 1;
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(
f278a5
                subTrack.modifier->calcPoint((double)i - 1.0 + frac), false);
7e9eb1
        }
7e9eb1
      }
f278a5
      subTrack.push_back(subTrack.modifier->calcPoint(i), false);
7e9eb1
    }
f278a5
    
f278a5
    // fix points
f278a5
    if (track.fixedSize())
f278a5
      subTrack.fix_to(
f278a5
        subTrack.floorIndex(subTrack.indexByOriginalIndex(track.fixedSize() - 1)) + 1 );
7e9eb1
  }
7e9eb1
00337d
  track.resetChanges();
7e9eb1
}
7e9eb1
f278a5
#endif