5 #ifndef CNOID_UTIL_RANGE_LIMITER_H_INCLUDED
6 #define CNOID_UTIL_RANGE_LIMITER_H_INCLUDED
10 #include "exportdecl.h"
17 template <
class TArray>
18 bool apply(TArray& valueSeq,
double upperLimit,
double lowerLimit,
double limitGrad,
double edgeGradRatio = 0.5);
35 std::vector<TSegment> segments;
37 CNOID_EXPORT
void calcCrossPoint(TSegment* seg);
38 CNOID_EXPORT TSegment* mergeSegment(TSegment* seg, TSegment* prevSeg);
40 template <
class TArray>
41 TSegment* finalizeSegment(TSegment* seg,
int endFrame, TArray& valueSeq);
45 template <
class TArray>
46 RangeLimiter::TSegment* RangeLimiter::finalizeSegment
47 (RangeLimiter::TSegment* seg,
int endFrame, TArray& valueSeq)
50 int backFrame = seg->begin - 1;
51 TSegment* prevSeg = &segments[segments.size() - 2];
52 while(backFrame >= 0){
53 if(backFrame < prevSeg->end){
54 return mergeSegment(seg, prevSeg);
56 double v = valueSeq[backFrame];
58 if((v < seg->uc) && (v > seg->lc)){
64 seg->begin = backFrame;
69 template <
class TArray>
71 (TArray& valueSeq,
double upperLimit,
double lowerLimit,
double limitGrad,
double edgeGradRatio)
82 segments.push_back(dummy);
84 segments.push_back(TSegment());
86 TSegment* seg = &segments.back();
95 int n = valueSeq.size();
98 double v = valueSeq[frame];
104 }
else if(v < seg->lower){
115 }
else if(seg->isOver) {
116 if((v < seg->uc) && (v > seg->lc)){
117 TSegment* finalized = finalizeSegment(seg, frame, valueSeq);
119 if(finalized != seg){
124 nextSeg.begin = finalized->end;
127 nextSeg.isOver =
false;
128 calcCrossPoint(&nextSeg);
129 segments.push_back(nextSeg);
130 seg = &segments.back();
139 TSegment* finalized = finalizeSegment(seg, frame, valueSeq);
140 if(finalized == seg){
150 for(std::size_t i=1; i < segments.size(); i++){
151 TSegment& seg = segments[i];
160 double k = ((uL - seg.uc) / (seg.upper - seg.uc)) * edgeGradRatio;
161 double u = seg.upper - seg.uc;
162 double l = uL - seg.uc;
163 ub = ((1.0 - k) * u - 3.0 * (u - l)) / (u * u);
164 ua = (-2.0 * u * ub - 1.0 + k) / (3.0 * u * u);
172 double k = ((lL - seg.lc) / (seg.lower - seg.lc)) * edgeGradRatio;
173 double u = seg.lower - seg.lc;
174 double l = lL - seg.lc;
175 lb = ((1.0 - k) * u - 3.0 * (u - l)) / (u * u);
176 la = (-2.0 * u * lb - 1.0 + k) / (3.0 * u * u);
180 for(
int frame=seg.begin; frame < seg.end; frame++){
181 double v = valueSeq[frame];
183 double x = v - seg.uc;
184 valueSeq[frame] = ua * x*x*x + ub * x*x + x + seg.uc;
185 }
else if(v <= seg.lc){
186 double x = v - seg.lc;
187 valueSeq[frame] = la * x*x*x + lb * x*x + x + seg.lc;