RANSAC-0.1.0.2: tests/SmokeTest.hs
-- |Basic linear fit unit test. There is no noise in the data set, so
-- it is very unlikely that the correct model will not be found.
module Main where
import Control.Applicative
import Control.Lens (view)
import qualified Data.Foldable as F
import Data.Vector.Storable (Vector)
import qualified Data.Vector.Storable as V
import Linear
import Test.Framework (defaultMain)
import Test.Framework.Providers.HUnit (hUnitTestToTests)
import Test.HUnit (Test, (~?))
import Numeric.Ransac
type Point = V2 Float
sq :: Float -> Float
sq x = x * x
-- | Fit a 2D line to a collection of 'Point's.
fitLine :: Vector Point -> Maybe (V2 Float)
fitLine pts = (!* b) <$> inv22' a
where sx = V.sum $ V.map (view _x) pts
a = V2 (V2 (V.sum (V.map (sq . view _x) pts)) sx)
(V2 sx (fromIntegral (V.length pts)))
b = V2 (V.sum (V.map F.product pts))
(V.sum (V.map (view _y) pts))
inv22' m = let m' = inv22 m
in if F.any (F.any isNaN) m' then Nothing else Just m'
-- | Compute the error of a 'Point' with respect to a hypothesized
-- linear model.
ptError :: V2 Float -> Point -> Float
ptError (V2 m b) (V2 x y) = sq $ y - (m*x+b)
test1 :: Test
test1 = tst ~? "noise-free linear fit"
where model = ransac 20 2 0.8 fitLine ptError (< 0.1) pts
pts :: Vector Point
pts = V.generate 100 mkPoint
mkPoint i = let x = fromIntegral i * 0.1
in V2 x (3 * x + 1)
tst = do mm <- model
return $ case mm of
Nothing -> False
Just (m,_) -> qd (V2 3 1) m < 0.1
main :: IO ()
main = defaultMain $ hUnitTestToTests test1