packages feed

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