packages feed

pcd-loader 0.2.3.2 → 0.3.0.0

raw patch · 8 files changed

+409/−89 lines, 8 filesdep +HUnitdep +directorydep +string-qqdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: HUnit, directory, string-qq, test-framework, test-framework-hunit

Dependency ranges changed: base

API changes (from Hackage documentation)

- PCD.Data: asciiToBinary :: FilePath -> FilePath -> IO ()
- PCD.Data: loadAllFields :: FilePath -> IO (Text -> Vector FieldType)
+ PCD.Conversion: asciiToBinary :: FilePath -> FilePath -> IO ()
+ PCD.Data: loadFieldsByName :: FilePath -> IO (Text -> Vector FieldType)
+ PCD.Data: loadFlexiblePoints :: Header -> Handle -> IO (Vector (Vector FieldType))
+ PCD.Internal.AsciiParsers: readPoints :: Vector v a => Header -> Handle -> Parser a -> IO (v a)
+ PCD.Internal.AsciiParsers: readPointsDefault :: Header -> Handle -> IO (Vector (Vector FieldType))
+ PCD.Internal.AsciiParsers: readXYZ :: Fractional a => Parser (V3 a)
+ PCD.Internal.AsciiParsers: readXYZW :: Fractional a => Parser (V4 a)

Files

pcd-loader.cabal view
@@ -1,5 +1,5 @@ name:                pcd-loader-version:             0.2.3.2+version:             0.3.0.0 synopsis:            PCD file loader. description:         Parser for PCD (point cloud data) formats.  See                      <http://pointclouds.org/documentation/tutorials/pcd_file_format.php>@@ -12,17 +12,18 @@ category:            Robotics,Graphics build-type:          Simple cabal-version:       >=1.10+extra-source-files:  tests/SampleLoad.hs, tests/SampleData.hs  source-repository head   type: git   location: git://github.com/acowley/pcd-loader.git  library-  exposed-modules:  PCD.Data, PCD.Header, PCD.Internal.Types, -                    PCD.Internal.StorableFieldType+  exposed-modules:  PCD.Data, PCD.Header, PCD.Conversion, PCD.Internal.Types, +                    PCD.Internal.StorableFieldType, PCD.Internal.AsciiParsers   ghc-options:      -O2 -Wall   hs-source-dirs:   src-  build-depends:    base >= 4.6 && < 5, text, mtl, lens, vector, bytestring, +  build-depends:    base >= 4.5 && < 5, text, mtl, lens, vector, bytestring,                      attoparsec, binary, deepseq, linear   default-language: Haskell2010 @@ -30,6 +31,15 @@   hs-source-dirs:   src/executable   main-is:          Main.hs          ghc-options:      -O2 -Wall-  build-depends:    base >= 4.6 && < 5, pcd-loader    +  build-depends:    base >= 4.5 && < 5, pcd-loader       default-language: Haskell2010 +test-suite tests+  type: exitcode-stdio-1.0+  hs-source-dirs: tests+  main-is: SampleLoad.hs+  ghc-options: -Wall -O2+  default-language: Haskell2010+  build-depends: base >= 4.5 && < 5,+                 test-framework, test-framework-hunit, HUnit,+                 vector, lens, text, directory, string-qq, pcd-loader
+ src/PCD/Conversion.hs view
@@ -0,0 +1,31 @@+-- |Facility to convert an ASCII PCD file to a Binary one.+module PCD.Conversion where+import Control.Lens ((^.), (.~))+import Control.Monad (when)+import qualified Data.Text.IO as T+import qualified Data.Vector as B+import Foreign.Marshal.Alloc (allocaBytes)+import System.IO (IOMode(..), openFile, hClose, hPutBuf, withBinaryFile)++import PCD.Header+import qualified PCD.Internal.AsciiParsers as A+import PCD.Internal.StorableFieldType (pokeBinaryPoints)++-- |@asciiToBinary inputFile outputFile@ converts a PCD file from+-- ASCII to Binary.+asciiToBinary :: FilePath -> FilePath -> IO ()+asciiToBinary i o = do h <- openFile i ReadMode+                       (pcdh,_) <- readHeader h+                       print pcdh+                       when (pcdh^.format /= ASCII)+                            (error "Input PCD is already binary!")+                       let numBytes = totalBinarySize pcdh+                       putStrLn $ "Expecting to generate "++show numBytes++" bytes"+                       v <- A.readPointsDefault pcdh h+                       putStrLn $ "Parsed "++show (B.length v)++" ASCII points"+                       hClose h+                       T.writeFile o (writeHeader (format .~ Binary $ pcdh))+                       withBinaryFile o AppendMode $ \h' ->+                         allocaBytes numBytes $ \ptr ->+                           pokeBinaryPoints ptr v >>+                           hPutBuf h' ptr numBytes
src/PCD/Data.hs view
@@ -1,21 +1,20 @@-{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}--- |Parser for PCD (point cloud data) files. Also provides a facility--- for converting from ASCII to binary formatted point data.-module PCD.Data (FieldType(..), unsafeUnwrap, loadAllFields, -                 loadXyzw, loadXyz, asciiToBinary, saveBinaryPcd, -                 projectBinaryFields, mkSimpleHeader, mkHeaderXYZ) where+{-# LANGUAGE ScopedTypeVariables #-}+-- |Parser for PCD (point cloud data) files.+module PCD.Data (-- * Accessing fields+                 FieldType(..), unsafeUnwrap, +                 -- * Loading PCD data+                 loadFieldsByName, loadFlexiblePoints, loadXyzw, loadXyz, +                 -- * Saving PCD data+                 saveBinaryPcd, projectBinaryFields,+                 -- * PCD header creation+                 mkSimpleHeader, mkHeaderXYZ) where import Control.Applicative import Control.DeepSeq import Control.Lens ((.~), (^.))-import Control.Monad (when)-import Data.Attoparsec.Text hiding (I) import qualified Data.Attoparsec.Text.Lazy as ATL import Data.Text (Text)-import qualified Data.Text.Lazy.IO as TL import qualified Data.Text.IO as T import qualified Data.Vector as B-import qualified Data.Vector.Generic as G-import qualified Data.Vector.Generic.Mutable as GM import qualified Data.Vector.Storable as V import qualified Data.Vector.Storable.Mutable as VM import Foreign.Marshal.Alloc (allocaBytes)@@ -23,35 +22,14 @@ import System.IO (Handle, openFile, hClose,                    IOMode(..), withBinaryFile, hPutBuf, hGetBuf) import PCD.Header+import qualified PCD.Internal.AsciiParsers as A import PCD.Internal.StorableFieldType import PCD.Internal.Types --- |Read point data using a user-supplied ASCII point parser.-readAsciiPoints :: (G.Vector v a) => -                   Header -> Handle -> ATL.Parser a -> IO (v a)-readAsciiPoints pcd h p = aux <$> TL.hGetContents h-  where n = fromIntegral $ pcd^.points-        aux t0 = G.create $-                 do v <- GM.new n-                    let write = GM.write v-                        go !i !t-                          | i == n = return v-                          | otherwise = case ATL.parse p t of-                                          ATL.Done !t' !pt -> write i pt >> -                                                              go (i+1) t'-                                          ATL.Fail _ _ msg -> error msg-                    go 0 t0---- |Load points of unknown dimension into a boxed vector with a list--- of 'FieldType' as the point representation.-readAsciiPointsDefault :: Header -> Handle -> IO (B.Vector (B.Vector FieldType))-readAsciiPointsDefault pcd h = readAsciiPoints pcd h $ -                               B.fromList <$> pointParser pcd- -- |Read back 'Storable' points saved as binary data.-readHomogenousBinaryPoints :: forall a. Storable a => +readStorableBinaryPoints :: forall a. Storable a =>                                Header -> Handle -> IO (Either String (Vector a))-readHomogenousBinaryPoints pcd h+readStorableBinaryPoints pcd h   | ptSize /= sz = return . Left $                     "Deserialization type is not the same size as the points "++                    "described by this file. The PCD file dicates "++@@ -71,20 +49,9 @@ readPointData :: Storable a =>                   Header -> Handle -> ATL.Parser a ->                   IO (Either String (Vector a))-readPointData hd h pa -  | hd^.format == ASCII = readAsciiPoints hd h pa >>= return . Right-  | otherwise = readHomogenousBinaryPoints hd h---- |Parse 3D points serialized in ASCII.-readXYZ_ascii :: Fractional a => ATL.Parser (V3 a)-readXYZ_ascii = (\[x,y,z] -> V3 x y z) <$> -                count 3 ((realToFrac <$> double) <* skipSpace)---- |Parse 4D points serialized to ASCII. This is useful for points--- with X,Y,Z, and RGB fields each represented by a single float.-readXYZW_ascii :: Fractional a => ATL.Parser (V4 a)-readXYZW_ascii = (\[x,y,z,w] -> V4 x y z w) <$>-                 count 4 ((realToFrac <$> double) <* skipSpace)+readPointData header handle parser+  | header^.format == ASCII = Right <$> A.readPoints header handle parser+  | otherwise = readStorableBinaryPoints header handle  -- |Use an existing PCD header to save binary point data to a -- file. The supplied header is used as-is, except that its format is@@ -99,26 +66,12 @@      withBinaryFile outputFile AppendMode $ \h ->        V.unsafeWith pts (flip (hPutBuf h) sz) --- |@asciiToBinary inputFile outputFile@ converts a PCD file from--- ASCII to Binary.-asciiToBinary :: FilePath -> FilePath -> IO ()-asciiToBinary i o = do h <- openFile i ReadMode-                       (pcdh,_) <- readHeader h-                       pcdh `deepseq` print pcdh-                       when (pcdh^.format /= ASCII)-                            (error "Input PCD is already binary!")-                       let numBytes = totalBinarySize pcdh-                       putStrLn $ "Expecting to generate "++show numBytes++" bytes"-                       v <- readAsciiPointsDefault pcdh h-                       putStrLn $ "Parsed "++show (B.length v)++" ASCII points"-                       hClose h-                       T.writeFile o (writeHeader (format .~ Binary $ pcdh))-                       withBinaryFile o AppendMode $ \h' ->-                         allocaBytes numBytes $ \ptr ->-                           pokeBinaryPoints ptr v >>-                           hPutBuf h' ptr numBytes---- |Save a binary PCD file including only the named fields.+-- |Save a binary PCD file including only the named fields. This is+-- useful when you have a PCD file that has more fields for each point+-- than you care about. For instance, you may wish to extract just the+-- \"x\", \"y\", and \"z\" fields for each point. This can be+-- accomplished using, @projectBinaryFields [\"x\", \"y\", \"z\"]+-- inputFile outputFile@. projectBinaryFields :: [Text] -> FilePath -> FilePath -> IO () projectBinaryFields fs i o =    do h <- openFile i ReadMode@@ -142,7 +95,10 @@ -- |Load points stored in a PCD file into a 'Vector'. This requires a -- 'Storable' instance for the type used to represent a point. If the -- point is a monotyped collection of fields, consider using--- 'Linear.V2.V2' or 'Linear.V3.V3' to represent points.+-- 'Linear.V2', 'Linear.V3', or 'Linear.V4' to represent points. When+-- using a representation from the @linear@ package, you may wish to+-- use 'loadXyz' or 'loadXyzw' which can handle ASCII and Binary+-- serializations of 3D or 4D points. loadPoints :: Storable a => ATL.Parser a -> FilePath -> IO (Vector a) loadPoints parser pcdFile = do h <- openFile pcdFile ReadMode                                (pcdh,_) <- readHeader h@@ -153,7 +109,7 @@ -- |Read a PCD file consisting of floating point XYZ coordinates for -- each point. loadXyz :: (Fractional a, Storable a) => FilePath -> IO (Vector (V3 a))-loadXyz = loadPoints readXYZ_ascii+loadXyz = loadPoints A.readXYZ {-# SPECIALIZE loadXyz :: FilePath -> IO (Vector (V3 Float)) #-} {-# SPECIALIZE loadXyz :: FilePath -> IO (Vector (V3 Double)) #-} @@ -161,26 +117,25 @@ -- each point (where the final \"W\" field may be an RGB triple -- encoded as a float). loadXyzw :: (Fractional a, Storable a) => FilePath -> IO (Vector (V4 a))-loadXyzw = loadPoints readXYZW_ascii+loadXyzw = loadPoints A.readXYZW {-# SPECIALIZE loadXyzw :: FilePath -> IO (Vector (V4 Float)) #-} {-# SPECIALIZE loadXyzw :: FilePath -> IO (Vector (V4 Double)) #-} +-- |Load a 'B.Vector' of points, each represented as a 'B.Vector' of+-- 'FieldType' fields. If you wish to use field names to access to the+-- data, consider using 'loadFieldsByName'. loadFlexiblePoints :: Header -> Handle -> IO (B.Vector (B.Vector FieldType)) loadFlexiblePoints pcdh h   | pcdh ^. format == Binary = parseBinaryPoints pcdh h-  | otherwise = readAsciiPointsDefault pcdh h+  | otherwise = A.readPointsDefault pcdh h  -- |Parse every field of every point in a PCD file. Returns a function -- that may be used to project out a named field.-loadAllFields :: FilePath -> IO (Text -> B.Vector FieldType)-loadAllFields f = do h <- openFile f ReadMode-                     (pcdh,_) <- readHeader h-                     (mkProjector pcdh <$>-                       if pcdh ^. format == ASCII-                         then readAsciiPoints pcdh h -                                              (B.fromList <$> pointParser pcdh)-                         else parseBinaryPoints pcdh h)-                       <* hClose h+loadFieldsByName :: FilePath -> IO (Text -> B.Vector FieldType)+loadFieldsByName f = do h <- openFile f ReadMode+                        (pcdh,_) <- readHeader h+                        (mkProjector pcdh <$> loadFlexiblePoints pcdh h) +                          <* hClose h   where mkProjector :: Header -> B.Vector (B.Vector FieldType) ->                         (Text -> B.Vector FieldType)         mkProjector h pts = let fieldNames = B.fromList $ h ^. fields
src/PCD/Header.hs view
@@ -124,7 +124,8 @@ -- |Make a PCD header for a monotyped vector point -- type. @mkSimpleHeader fields (type,sz) n@ prepares a 'Header' for -- @n@ points with field names @fields@, field type given by @type@,--- and field size given by @sz@. Example to save 1000 3D points:+-- and field size given by @sz@. Example to save 1000 3D points using+-- a single-precision floating point number (4 bytes) for each field: -- -- > mkSimpleHeader ["x","y","z"] (F,4) 1000 mkSimpleHeader :: [Text] -> (DimType,Int) -> Int -> Header
+ src/PCD/Internal/AsciiParsers.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE BangPatterns #-}+module PCD.Internal.AsciiParsers where+import Control.Applicative+import Control.Lens ((^.))+import Data.Attoparsec.Text (double, count, skipSpace)+import qualified Data.Attoparsec.Text.Lazy as ATL+import qualified Data.Text.Lazy.IO as TL+import qualified Data.Vector as B+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import System.IO (Handle)++import PCD.Header (Header, FieldType, pointParser, points)+import PCD.Internal.Types (V3(..), V4(..))++-- |Read point data using a user-supplied ASCII point parser.+readPoints :: (G.Vector v a) => +                   Header -> Handle -> ATL.Parser a -> IO (v a)+readPoints pcd h p = aux <$> TL.hGetContents h+  where n = fromIntegral $ pcd^.points+        aux t0 = G.create $+                 do v <- GM.new n+                    let write = GM.write v+                        go !i !t+                          | i == n = return v+                          | otherwise = case ATL.parse p t of+                                          ATL.Done !t' !pt -> write i pt >> +                                                              go (i+1) t'+                                          ATL.Fail _ _ msg -> error msg+                    go 0 t0++-- |Load points of arbitrary dimension into a boxed vector with a+-- 'B.Vector' of 'FieldType' as the point representation.+readPointsDefault :: Header -> Handle -> IO (B.Vector (B.Vector FieldType))+readPointsDefault pcd h = readPoints pcd h $ B.fromList <$> pointParser pcd++-- |Parse 3D points serialized in ASCII.+readXYZ :: Fractional a => ATL.Parser (V3 a)+readXYZ = (\[x,y,z] -> V3 x y z) <$> +          count 3 ((realToFrac <$> double) <* skipSpace)++-- |Parse 4D points serialized to ASCII. This is useful for points+-- with X,Y,Z, and RGB fields each represented by a single float.+readXYZW :: Fractional a => ATL.Parser (V4 a)+readXYZW = (\[x,y,z,w] -> V4 x y z w) <$>+           count 4 ((realToFrac <$> double) <* skipSpace)
src/executable/Main.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} module Main (main) where import System.Environment (getArgs)-import PCD.Data (asciiToBinary, projectBinaryFields)+import PCD.Conversion (asciiToBinary)+import PCD.Data (projectBinaryFields)  data Args = Args { _inputFile  :: FilePath                  , _outputFile :: FilePath
+ tests/SampleData.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}+-- |Sample PCD file from http://pointclouds.org/documentation/tutorials/pcd_file_format.php+module SampleData where+import Data.String.QQ+import Data.Text (Text)++sampleData :: Text+sampleData = [s|+# .PCD v.7 - Point Cloud Data file format+VERSION .7+FIELDS x y z rgb+SIZE 4 4 4 4+TYPE F F F F+COUNT 1 1 1 1+WIDTH 213+HEIGHT 1+VIEWPOINT 0 0 0 1 0 0 0+POINTS 213+DATA ascii+0.93773 0.33763 0 4.2108e+06+0.90805 0.35641 0 4.2108e+06+0.81915 0.32 0 4.2108e+06+0.97192 0.278 0 4.2108e+06+0.944 0.29474 0 4.2108e+06+0.98111 0.24247 0 4.2108e+06+0.93655 0.26143 0 4.2108e+06+0.91631 0.27442 0 4.2108e+06+0.81921 0.29315 0 4.2108e+06+0.90701 0.24109 0 4.2108e+06+0.83239 0.23398 0 4.2108e+06+0.99185 0.2116 0 4.2108e+06+0.89264 0.21174 0 4.2108e+06+0.85082 0.21212 0 4.2108e+06+0.81044 0.32222 0 4.2108e+06+0.74459 0.32192 0 4.2108e+06+0.69927 0.32278 0 4.2108e+06+0.8102 0.29315 0 4.2108e+06+0.75504 0.29765 0 4.2108e+06+0.8102 0.24399 0 4.2108e+06+0.74995 0.24723 0 4.2108e+06+0.68049 0.29768 0 4.2108e+06+0.66509 0.29002 0 4.2108e+06+0.69441 0.2526 0 4.2108e+06+0.62807 0.22187 0 4.2108e+06+0.58706 0.32199 0 4.2108e+06+0.52125 0.31955 0 4.2108e+06+0.49351 0.32282 0 4.2108e+06+0.44313 0.32169 0 4.2108e+06+0.58678 0.2929 0 4.2108e+06+0.53436 0.29164 0 4.2108e+06+0.59308 0.24134 0 4.2108e+06+0.5357 0.2444 0 4.2108e+06+0.50043 0.31235 0 4.2108e+06+0.44107 0.29711 0 4.2108e+06+0.50727 0.22193 0 4.2108e+06+0.43957 0.23976 0 4.2108e+06+0.8105 0.21112 0 4.2108e+06+0.73555 0.2114 0 4.2108e+06+0.69907 0.21082 0 4.2108e+06+0.63327 0.21154 0 4.2108e+06+0.59165 0.21201 0 4.2108e+06+0.52477 0.21491 0 4.2108e+06+0.49375 0.21006 0 4.2108e+06+0.4384 0.19632 0 4.2108e+06+0.43425 0.16052 0 4.2108e+06+0.3787 0.32173 0 4.2108e+06+0.33444 0.3216 0 4.2108e+06+0.23815 0.32199 0 4.808e+06+0.3788 0.29315 0 4.2108e+06+0.33058 0.31073 0 4.2108e+06+0.3788 0.24399 0 4.2108e+06+0.30249 0.29189 0 4.2108e+06+0.23492 0.29446 0 4.808e+06+0.29465 0.24399 0 4.2108e+06+0.23514 0.24172 0 4.808e+06+0.18836 0.32277 0 4.808e+06+0.15992 0.32176 0 4.808e+06+0.08642 0.32181 0 4.808e+06+0.039994 0.32283 0 4.808e+06+0.20039 0.31211 0 4.808e+06+0.1417 0.29506 0 4.808e+06+0.20921 0.22332 0 4.808e+06+0.13884 0.24227 0 4.808e+06+0.085123 0.29441 0 4.808e+06+0.048446 0.31279 0 4.808e+06+0.086957 0.24399 0 4.808e+06+0.3788 0.21189 0 4.2108e+06+0.29465 0.19323 0 4.2108e+06+0.23755 0.19348 0 4.808e+06+0.29463 0.16054 0 4.2108e+06+0.23776 0.16054 0 4.808e+06+0.19016 0.21038 0 4.808e+06+0.15704 0.21245 0 4.808e+06+0.08678 0.21169 0 4.808e+06+0.012746 0.32168 0 4.808e+06+-0.075715 0.32095 0 4.808e+06+-0.10622 0.32304 0 4.808e+06+-0.16391 0.32118 0 4.808e+06+0.00088411 0.29487 0 4.808e+06+-0.057568 0.29457 0 4.808e+06+-0.0034333 0.24399 0 4.808e+06+-0.055185 0.24185 0 4.808e+06+-0.10983 0.31352 0 4.808e+06+-0.15082 0.29453 0 4.808e+06+-0.11534 0.22049 0 4.808e+06+-0.15155 0.24381 0 4.808e+06+-0.1912 0.32173 0 4.808e+06+-0.281 0.3185 0 4.808e+06+-0.30791 0.32307 0 4.808e+06+-0.33854 0.32148 0 4.808e+06+-0.21248 0.29805 0 4.808e+06+-0.26372 0.29905 0 4.808e+06+-0.22562 0.24399 0 4.808e+06+-0.25035 0.2371 0 4.808e+06+-0.29941 0.31191 0 4.808e+06+-0.35845 0.2954 0 4.808e+06+-0.29231 0.22236 0 4.808e+06+-0.36101 0.24172 0 4.808e+06+-0.0034393 0.21129 0 4.808e+06+-0.07306 0.21304 0 4.808e+06+-0.10579 0.2099 0 4.808e+06+-0.13642 0.21411 0 4.808e+06+-0.22562 0.19323 0 4.808e+06+-0.24439 0.19799 0 4.808e+06+-0.22591 0.16041 0 4.808e+06+-0.23466 0.16082 0 4.808e+06+-0.3077 0.20998 0 4.808e+06+-0.3413 0.21239 0 4.808e+06+-0.40551 0.32178 0 4.2108e+06+-0.50568 0.3218 0 4.2108e+06+-0.41732 0.30844 0 4.2108e+06+-0.44237 0.28859 0 4.2108e+06+-0.41591 0.22004 0 4.2108e+06+-0.44803 0.24236 0 4.2108e+06+-0.50623 0.29315 0 4.2108e+06+-0.50916 0.24296 0 4.2108e+06+-0.57019 0.22334 0 4.2108e+06+-0.59611 0.32199 0 4.2108e+06+-0.65104 0.32199 0 4.2108e+06+-0.72566 0.32129 0 4.2108e+06+-0.75538 0.32301 0 4.2108e+06+-0.59653 0.29315 0 4.2108e+06+-0.65063 0.29315 0 4.2108e+06+-0.59478 0.24245 0 4.2108e+06+-0.65063 0.24399 0 4.2108e+06+-0.70618 0.29525 0 4.2108e+06+-0.76203 0.31284 0 4.2108e+06+-0.70302 0.24183 0 4.2108e+06+-0.77062 0.22133 0 4.2108e+06+-0.41545 0.21099 0 4.2108e+06+-0.45004 0.19812 0 4.2108e+06+-0.4475 0.1673 0 4.2108e+06+-0.52031 0.21236 0 4.2108e+06+-0.55182 0.21045 0 4.2108e+06+-0.5965 0.21131 0 4.2108e+06+-0.65064 0.2113 0 4.2108e+06+-0.72216 0.21286 0 4.2108e+06+-0.7556 0.20987 0 4.2108e+06+-0.78343 0.31973 0 4.2108e+06+-0.87572 0.32111 0 4.2108e+06+-0.90519 0.32263 0 4.2108e+06+-0.95526 0.34127 0 4.2108e+06+-0.79774 0.29271 0 4.2108e+06+-0.85618 0.29497 0 4.2108e+06+-0.79975 0.24326 0 4.2108e+06+-0.8521 0.24246 0 4.2108e+06+-0.91157 0.31224 0 4.2108e+06+-0.95031 0.29572 0 4.2108e+06+-0.92223 0.2213 0 4.2108e+06+-0.94979 0.24354 0 4.2108e+06+-0.78641 0.21505 0 4.2108e+06+-0.87094 0.21237 0 4.2108e+06+-0.90637 0.20934 0 4.2108e+06+-0.93777 0.21481 0 4.2108e+06+0.22244 -0.0296 0 4.808e+06+0.2704 -0.078167 0 4.808e+06+0.24416 -0.056883 0 4.808e+06+0.27311 -0.10653 0 4.808e+06+0.26172 -0.10653 0 4.808e+06+0.2704 -0.1349 0 4.808e+06+0.24428 -0.15599 0 4.808e+06+0.19017 -0.025297 0 4.808e+06+0.14248 -0.02428 0 4.808e+06+0.19815 -0.037432 0 4.808e+06+0.14248 -0.03515 0 4.808e+06+0.093313 -0.02428 0 4.808e+06+0.044144 -0.02428 0 4.808e+06+0.093313 -0.03515 0 4.808e+06+0.044144 -0.03515 0 4.808e+06+0.21156 -0.17357 0 4.808e+06+0.029114 -0.12594 0 4.2108e+06+0.036583 -0.15619 0 4.2108e+06+0.22446 -0.20514 0 4.808e+06+0.2208 -0.2369 0 4.808e+06+0.2129 -0.208 0 4.808e+06+0.19316 -0.25672 0 4.808e+06+0.14497 -0.27484 0 4.808e+06+0.030167 -0.18748 0 4.2108e+06+0.1021 -0.27453 0 4.808e+06+0.1689 -0.2831 0 4.808e+06+0.13875 -0.28647 0 4.808e+06+0.086993 -0.29568 0 4.808e+06+0.044924 -0.3154 0 4.808e+06+-0.0066125 -0.02428 0 4.808e+06+-0.057362 -0.02428 0 4.808e+06+-0.0066125 -0.03515 0 4.808e+06+-0.057362 -0.03515 0 4.808e+06+-0.10653 -0.02428 0 4.808e+06+-0.15266 -0.025282 0 4.808e+06+-0.10653 -0.03515 0 4.808e+06+-0.16036 -0.037257 0 4.808e+06+0.0083286 -0.1259 0 4.2108e+06+0.0007442 -0.15603 0 4.2108e+06+-0.1741 -0.17381 0 4.808e+06+-0.18502 -0.02954 0 4.808e+06+-0.20707 -0.056403 0 4.808e+06+-0.23348 -0.07764 0 4.808e+06+-0.2244 -0.10653 0 4.808e+06+-0.23604 -0.10652 0 4.808e+06+-0.20734 -0.15641 0 4.808e+06+-0.23348 -0.13542 0 4.808e+06+0.0061083 -0.18729 0 4.2108e+06+-0.066235 -0.27472 0 4.808e+06+-0.17577 -0.20789 0 4.808e+06+-0.10861 -0.27494 0 4.808e+06+-0.15584 -0.25716 0 4.808e+06+-0.0075775 -0.31546 0 4.808e+06+-0.050817 -0.29595 0 4.808e+06+-0.10306 -0.28653 0 4.808e+06+-0.1319 -0.2831 0 4.808e+06+-0.18716 -0.20571 0 4.808e+06+-0.18369 -0.23729 0 4.808e+06|]
+ tests/SampleLoad.hs view
@@ -0,0 +1,44 @@+-- |Ensure that a sample PCD file can be loaded.+module Main where+import Control.Lens ((^.))+import qualified Data.Text.IO as T+import qualified Data.Vector as V+import System.Directory (getTemporaryDirectory)+import System.IO (openTempFile, hClose, hSeek, SeekMode(..))+import Test.Framework (defaultMain)+import Test.Framework.Providers.HUnit (hUnitTestToTests)+import Test.HUnit (Test(..), (~?), (~=?))++import SampleData+import PCD.Data+import PCD.Header++testLen :: Header -> V.Vector (V.Vector FieldType) -> Test+testLen header pts = TestLabel "Number of fields" $ +                     TestList [ 4 ~=? length (header^.fields)+                              , 4 ~=? V.length (V.head pts) ]++testPts :: Header -> V.Vector a -> Test+testPts header pts = TestLabel "Number of points" $+                     TestList [ 213 ~=? header^.points +                              , 213 ~=? V.length pts ]++within :: (Num a, Ord a) => a -> a -> a -> Bool+within delta x y = abs (y - x) < delta++testData :: V.Vector (V.Vector FieldType) -> Test+testData pts = TestLabel "Point data" $+               TestList [ within 0.001 (-0.23729) lastY ~? +                            "Last point's Y coordinate" ]+  where lastY = unsafeUnwrap (V.last pts V.! 1) :: Float++main :: IO ()+main = do d <- getTemporaryDirectory+          (_, h) <- openTempFile d "pcdTest"+          T.hPutStr h sampleData+          hSeek h AbsoluteSeek 0+          (header, _) <- readHeader h+          pts <- loadFlexiblePoints header h+          defaultMain . hUnitTestToTests $+            TestList [testLen header pts, testPts header pts, testData pts]+          hClose h