#include <tools/track.h>
//*****************************************************************************************
// Class definitions
//*****************************************************************************************
const double TTrack::epsilon = 1e-9;
TTrack::Id TTrack::lastId = 0;
DEFINE_CLASS_CODE(TTrackHandler, 130)
DEFINE_CLASS_CODE(TTrackModifier, 131)
DEFINE_CLASS_CODE(TTrack, 132)
//*****************************************************************************************
// TTrackModifier implemantation
//*****************************************************************************************
TTrackPoint
TTrackModifier::calcPoint(double originalIndex) {
TTrackPoint p = original.calcPoint(originalIndex);
p.originalIndex = originalIndex;
return p;
}
//*****************************************************************************************
// TTrack implemantation
//*****************************************************************************************
TTrack::TTrack(
DeviceId deviceId,
TouchId touchId,
const TKeyHistoryT<Qt::Key>::Holder &keyHistory,
const TKeyHistoryT<Qt::MouseButton>::Holder &buttonHistory
):
id(++lastId),
deviceId(deviceId),
touchId(touchId),
keyHistory(keyHistory),
buttonHistory(buttonHistory),
wayPointsRemoved(),
wayPointsAdded()
{ }
TTrack::TTrack(const TTrackModifierP &modifier):
id(++lastId),
deviceId(modifier->original.deviceId),
touchId(modifier->original.touchId),
keyHistory(modifier->original.keyHistory),
buttonHistory(modifier->original.buttonHistory),
wayPointsRemoved(),
wayPointsAdded()
{ }
const TTrack*
TTrack::root() const
{ return original() ? original()->root() : this; }
TTrack*
TTrack::root()
{ return original() ? original()->root() : this; }
int
TTrack::level() const
{ return original() ? original()->level() + 1 : 0; }
int
TTrack::floorIndex(double index, double &outFrac) const {
int i = (int)floor(index + epsilon);
if (i > size() - 1)
{ outFrac = 0.0; return size() - 1; }
if (i < 0)
{ outFrac = 0.0; return 0; }
outFrac = std::max(0.0, index - (double)i);
return i;
}
void
TTrack::push_back(const TTrackPoint &point) {
points_.push_back(point);
if (size() == 1) return;
const TTrackPoint &prev = *(points_.end() - 2);
TTrackPoint &p = points_.back();
if (p.originalIndex < prev.originalIndex)
p.originalIndex = prev.originalIndex;
if (p.time < prev.time)
p.time = prev.time;
TPointD d = p.position - prev.position;
p.length = prev.length + sqrt(d.x*d.x + d.y*d.y);
}
void
TTrack::pop_back(int count) {
if (count > (int)size()) count = size();
if (count <= 0) return;
points_.erase(points_.end() - count, points_.end());
}
TTrackPoint
TTrack::calcPoint(double index) const {
return modifier
? modifier->calcPoint( originalIndexByIndex(index) )
: interpolateLinear(index);
}
TPointD
TTrack::calcTangent(double index, double distance) const {
double minDistance = 10.0*epsilon;
if (distance < minDistance) distance = minDistance;
TTrackPoint p = calcPoint(index);
TTrackPoint pp = calcPoint(indexByLength(p.length - distance));
TPointD dp = p.position - pp.position;
double lenSqr = dp.x*dp.x + dp.y*dp.y;
return lenSqr > epsilon*epsilon ? dp*sqrt(1.0/lenSqr) : TPointD();
}