packages feed

marching-cubes-0.1.0.0: src/MarchingCubes/Utils.hs

{-# LANGUAGE BangPatterns     #-}
{-# LANGUAGE FlexibleContexts #-}
module MarchingCubes.Utils
  ( module MarchingCubes.Utils
  ) where
import           Data.Array.Unboxed             ( (!)
                                                , IArray(..)
                                                , UArray
                                                )
import           Data.List                      ( transpose )
import           Data.Matrix                    ( (<|>)
                                                , Matrix(..)
                                                , colVector
                                                , getElem
                                                , mapPos
                                                , matrix
                                                , toLists
                                                )
import qualified Data.Matrix                   as M
import           Data.Sequence                  ( (><)
                                                , Seq
                                                , (|>)
                                                )
import qualified Data.Sequence                 as S
import qualified Data.Vector                   as V
import           Data.Vector.Unboxed            ( Vector )
import qualified Data.Vector.Unboxed           as UV

levelMatrix :: Real a => Matrix a -> a -> Bool -> Matrix Int
levelMatrix mtrx level strict = mapPos (\_ x -> if lt x then 1 else 0) mtrx
  where lt = if strict then (<) level else (<=) level

arrayToMatrix :: IArray UArray a => UArray (Int, Int, Int) a -> Int -> Matrix a
arrayToMatrix arr k = matrix (nx + 1)
                             (ny + 1)
                             (\(i, j) -> arr ! (i - 1, j - 1, k))
  where (_, (nx, ny, _)) = bounds arr

whichIndicesAndItems :: Matrix Int -> Seq (Int, Int)
whichIndicesAndItems mtrx = go 1 S.empty
 where
  m = nrows mtrx + 1
  n = ncols mtrx + 1
  go :: Int -> Seq (Int, Int) -> Seq (Int, Int)
  go j !out | j == n    = out
            | otherwise = go (j + 1) (inner 1 j out)
  inner i !j !out | i == m    = out
                  | otherwise = inner (i + 1) j out'
   where
    out' =
      let x = getElem i j mtrx
      in  if x > 0 && x < 255
            then out |> ((j - 1) * (m - 1) + i - 1, x)
            else out

kro1 :: Matrix Int -> Int -> Matrix Int
kro1 mtrx n = matrix p ny f
 where
  nx = nrows mtrx
  ny = ncols mtrx
  p  = nx * n + 1
  f (i, j) = if i < p then getElem ((i - 1) `mod` nx + 1) j mtrx else 0

kro2 :: Matrix Int -> Int -> Matrix Int
kro2 mtrx n = matrix p ny f
 where
  nx         = nrows mtrx
  ny         = ncols mtrx
  p          = nx * n + 1
  replicates = foldr ((><) . S.replicate n) S.empty [1 .. nx] :: Seq Int
  f (i, j) = if i < p then getElem (S.index replicates (i - 1)) j mtrx else 0

replicateEach :: [a] -> [Int] -> Seq a
replicateEach list counts = foldr (><) S.empty sequences
  where sequences = zipWith S.replicate counts list

replicateEach' :: [a] -> Int -> Seq a
replicateEach' list n = foldr ((><) . S.replicate n) S.empty list

vector2matrix :: [a] -> Int -> Matrix a
vector2matrix list ny = M.fromList (length list `div` ny) ny list

cbind :: Matrix a -> [a] -> [a] -> Matrix a
cbind mtrx col1 col2 = mtrx <|> col1' <|> col2'
 where
  col1' = colVector (V.fromList col1)
  col2' = colVector (V.fromList col2)

subMatrix :: Matrix a -> [Int] -> Vector Int -> Matrix a
subMatrix mtrx rows cols = matrix
  (length rows)
  (UV.length cols)
  (\(i, j) -> getElem (rows !! (i - 1) + 1) (cols UV.! (j - 1) + 1) mtrx)

matrix2listMinusFirstColumn :: Matrix a -> [a]
matrix2listMinusFirstColumn mtrx =
  concat $ transpose $ tail (toLists $ M.transpose mtrx)

jthColumn :: Vector Int -> Int -> Int -> Vector Int
jthColumn vec ncol j = UV.map (\i -> vec UV.! (i * ncol + j))
                              (UV.enumFromN 0 nrow)
  where nrow = UV.length vec `div` ncol