/// <summary> /// Gets the value at a particular time. /// </summary> /// <param name="time">The time at which to get the value.</param> /// <param name="isTimeAbsolute">Whether or not the specified time is absolute.</param> /// <returns>The value at the specified time.</returns> public T Get(double time, bool isTimeAbsolute = false) { T result; lock (_entryLock) { // check that there is at least one value in the timeline if (_firstEntry == null) { return(default(T)); } double absoluteTime = isTimeAbsolute ? time : _now + time; TimelineContext <T> currentContext = new TimelineContext <T>(); currentContext._time = absoluteTime; // set Context if (currentContext._time == _now) // time 0 so no need to search { currentContext._prev = _prevEntry; } else // starting at _lastEntry search back in time { currentContext._prev = _lastEntry; while (currentContext._prev != null && currentContext._prev._time > absoluteTime) { currentContext._prev = currentContext._prev._prev; } } if (currentContext._prev == null) // all entries are after the requested time { return(_firstEntry._value); } if (currentContext._prev._time == absoluteTime) { return(currentContext._prev._value); } currentContext._next = currentContext._prev._next; currentContext._prevPrev = currentContext._prev._prev; if (currentContext._next == null) { result = Extrapolate(this, currentContext); } else { result = Interpolate(this, currentContext); } } return(result); }
/// <summary> /// Filters timeline value sends based on extrapolation, but also forces a send /// periodically even if the value has not changed /// </summary> public static TimelineSendFilter <T> BuildDeltaRateFilter <T> (Func <T, T, float> getDelta, Func <float> getThreshold, Func <float> getRate) { return((timeline, entry) => { TimelineContext <T> currentContext = new TimelineContext <T>(); currentContext._prev = timeline.LastSentEntry; currentContext._prevPrev = timeline.LastLastSentEntry; currentContext._time = entry._time; return (getDelta(entry._value, timeline.Extrapolate(timeline, currentContext)) > getThreshold()) || (DateTime.Now.Subtract(timeline.LastSendTime).TotalSeconds >= (1f / getRate())); }); }
/// <summary> /// Filters timeline value sends based on extrapolation /// </summary> public static TimelineSendFilter <T> BuildExtrapolatedDeltaFilter <T> (Func <T, T, float> getDelta, Func <float> getThreshold) { return((timeline, entry) => { if (timeline.LastSentEntry == null) { return true; } TimelineContext <T> currentContext = new TimelineContext <T>(); currentContext._prev = timeline.LastSentEntry; currentContext._prevPrev = timeline.LastLastSentEntry; currentContext._time = entry._time; return getDelta(entry._value, timeline.Extrapolate(timeline, currentContext)) > getThreshold(); }); }
/// <summary> /// Stepping extrapolation /// </summary> public static T SteppingExtrapolate <T>(Timeline <T> timeline, TimelineContext <T> context) { return(context.Prev != null ? context.Prev.Value : default(T)); }