| 2139 | } |
| 2140 | |
| 2141 | float Path2d::segmentSolveTimeForDistance( size_t segment, float segmentLength, float segmentRelativeDistance, float tolerance, int maxIterations ) const |
| 2142 | { |
| 2143 | // initialize bisection endpoints |
| 2144 | float a = 0, b = 1; |
| 2145 | float p = segmentRelativeDistance / segmentLength; // make first guess |
| 2146 | |
| 2147 | // we want to calculate a value 'p' such that segmentLength( mCurrentSegment, mCurrentT, mCurrentT + p ) == lengthIncrement |
| 2148 | |
| 2149 | // iterate and look for zeros |
| 2150 | float lastArcLength = 0; |
| 2151 | float currentT = 0; |
| 2152 | for( int i = 0; i < maxIterations; ++i ) { |
| 2153 | // compute function value and test against zero |
| 2154 | lastArcLength = calcSegmentLength( segment, currentT, currentT + p ); |
| 2155 | float delta = lastArcLength - segmentRelativeDistance; |
| 2156 | if( math<float>::abs( delta ) < tolerance ) { |
| 2157 | break; |
| 2158 | } |
| 2159 | |
| 2160 | // update bisection endpoints |
| 2161 | if( delta < 0 ) |
| 2162 | a = p; |
| 2163 | else |
| 2164 | b = p; |
| 2165 | |
| 2166 | // get speed along curve |
| 2167 | const float speed = length( getSegmentTangent( segment, currentT + p ) ); |
| 2168 | |
| 2169 | // if result will lie outside [a,b] |
| 2170 | if( ((p-a)*speed - delta)*((p-b)*speed - delta) > -tolerance ) |
| 2171 | p = 0.5f*(a+b); // do bisection |
| 2172 | else |
| 2173 | p -= delta/speed; // otherwise Newton-Raphson |
| 2174 | } |
| 2175 | // If we failed to converge, hopefully 'p' is close enough |
| 2176 | |
| 2177 | return ( p + segment ) / (float)mSegments.size(); |
| 2178 | } |
| 2179 | |
| 2180 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 2181 | // Path2dCalcCache |
no test coverage detected