X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.runtime%2Fscl%2FInterpolation.scl;h=add8157554347f40dbdb7bdca83ce546139f48dc;hb=33b30297f751e06e9abac260d31313e2f833fedc;hp=7840c7cb9470bc16733c1267a23eb7b7f7362723;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.runtime/scl/Interpolation.scl b/bundles/org.simantics.scl.runtime/scl/Interpolation.scl index 7840c7cb9..add815755 100644 --- a/bundles/org.simantics.scl.runtime/scl/Interpolation.scl +++ b/bundles/org.simantics.scl.runtime/scl/Interpolation.scl @@ -1,50 +1,50 @@ -import "Prelude" -include "Vector" - - -@private -@inline -chooseInterval :: Vector Double -> Double -> ( a) -> (Integer -> a) -> ( a) -> a -chooseInterval table x down inRange up - | x < table!0 = down - | x >= table!(len-1) = up - | otherwise = search 0 (len-1) - where - len = length table - search low high | high <= low+1 = inRange low - | otherwise = do - middle = (low + high) `div` 2 - if x < table!middle - then search low middle - else search middle high - - -interpolateNearest :: Vector Double -> Vector Double -> Double -> Double -interpolateNearest xs ys x = chooseInterval xs x - (ys!0) - (\i -> if x - xs!i < xs!(i+1) - x then ys!i else ys!(i+1)) - (ys!(length xs-1)) - -interpolateLinear :: Vector Double -> Vector Double -> Double -> Double -interpolateLinear xs ys x = chooseInterval xs x - (ys!0) - (\i -> lin (xs!i) (xs!(i+1)) (ys!i) (ys!(i+1))) - (ys!(length ys-1)) - where - lin x0 x1 y0 y1 = y0 + (y1-y0) * (x-x0) / (x1-x0) - -interpolateCubic :: Vector Double -> Vector Double -> Double -> Double -interpolateCubic xs ys x = chooseInterval xs x - (ys!0) - (\i -> let a = max 0 (i-1) ; b = min (i+2) (length xs-1) in - cubic (xs!a) (xs!i) (xs!(i+1)) (xs!b) - (ys!a) (ys!i) (ys!(i+1)) (ys!b)) - (ys!(length ys-1)) - where - cubic x0 x1 x2 x3 y0 y1 y2 y3 = let - l = x2-x1 - dx1 = (y2-y0) * l / (x2-x0) - dx2 = (y3-y1) * l / (x3-x1) - t = (x-x1) / l - in - y1 + t * (dx1 + t * ((-3*y1 + 3*y2 - 2*dx1 - dx2) + t * (2*y1 - 2*y2 + dx1 + dx2))) +import "Prelude" +include "Vector" + + +@private +@inline +chooseInterval :: Vector Double -> Double -> ( a) -> (Integer -> a) -> ( a) -> a +chooseInterval table x down inRange up + | x < table!0 = down + | x >= table!(len-1) = up + | otherwise = search 0 (len-1) + where + len = length table + search low high | high <= low+1 = inRange low + | otherwise = do + middle = (low + high) `div` 2 + if x < table!middle + then search low middle + else search middle high + + +interpolateNearest :: Vector Double -> Vector Double -> Double -> Double +interpolateNearest xs ys x = chooseInterval xs x + (ys!0) + (\i -> if x - xs!i < xs!(i+1) - x then ys!i else ys!(i+1)) + (ys!(length xs-1)) + +interpolateLinear :: Vector Double -> Vector Double -> Double -> Double +interpolateLinear xs ys x = chooseInterval xs x + (ys!0) + (\i -> lin (xs!i) (xs!(i+1)) (ys!i) (ys!(i+1))) + (ys!(length ys-1)) + where + lin x0 x1 y0 y1 = y0 + (y1-y0) * (x-x0) / (x1-x0) + +interpolateCubic :: Vector Double -> Vector Double -> Double -> Double +interpolateCubic xs ys x = chooseInterval xs x + (ys!0) + (\i -> let a = max 0 (i-1) ; b = min (i+2) (length xs-1) in + cubic (xs!a) (xs!i) (xs!(i+1)) (xs!b) + (ys!a) (ys!i) (ys!(i+1)) (ys!b)) + (ys!(length ys-1)) + where + cubic x0 x1 x2 x3 y0 y1 y2 y3 = let + l = x2-x1 + dx1 = (y2-y0) * l / (x2-x0) + dx2 = (y3-y1) * l / (x3-x1) + t = (x-x1) / l + in + y1 + t * (dx1 + t * ((-3*y1 + 3*y2 - 2*dx1 - dx2) + t * (2*y1 - 2*y2 + dx1 + dx2)))