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