packages feed

arcgrid-viewer (empty) → 0.1.0.0

raw patch · 10 files changed

+382/−0 lines, 10 filesdep +arcgriddep +basedep +bytestringsetup-changed

Dependencies added: arcgrid, base, bytestring, gloss, transformers

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Author name here (c) 2017++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,75 @@+# Simple viewer of ArcGrid geospatial data written in Haskell++## Synopsis+A simple viewer for ESRI/ArcInfo (ArcGrid) files. A user can pan, zoom and+rotate the rendered dataset with keyboard and mouse (see _Controls_).+++![alt text](https://github.com/nbrk/arcgrid-viewer/blob/master/doc/scr_alps3.png "Screenshot")+++The program uses shades of red (by default) normalized by minimum and maximum+value in the VAT of the curent dataset. Black colour represents lower value than+the red one.++## Installation+The program depends on `gloss` and `arcgrid` libraries. The easiest way is to+install utulity `stack` and build the software from the source code.++Currently, as this:++``` sh+$ git clone https://github.com/nbrk/arcgrid.git+$ git clone https://github.com/nbrk/arcgrid-viewer.git+$ cd arcgrid-viewer+$ stack install+# Usually stack will install the program binary in ~/.local/bin .+# You can add it to PATH of you want.+$ ~/.local/bin/arcgrid-viewer ../arcgrid/sample/alps_huge.asc+```++## Usage+The program supports rendering the dataset in few color schemes (red, black and+white, a spectre) in both vector and raster modes. ++```+Usage: arcgrid-viewer [OPTION...] <file>+  -c MODE  --color=MODE  color scheme: red|bw|fancy+  -r MODE  --mode=MODE   rendering mode: vector|raster+```++The defaults are to render **in raster** with **red gradient**.+Please keep in mind that big datasets take time and resources to parse and render!++There is some sample `.asc` elevation data from the Alps. It resides in `arcgrid`+library and is [located](https://github.com/nbrk/arcgrid/tree/master/sample) in `arcgrid/sample`.++## Controls+The program uses `gloss` library for rendering and display. Therefore, the+controls are:++```+* Quit+  - esc-key++* Move Viewport+  - arrow keys+  - left-click drag++* Zoom Viewport+  - page up/down-keys+  - control-left-click drag+  - right-click drag+  - mouse wheel++* Rotate Viewport+  - home/end-keys+  - alt-left-click drag++* Reset Viewport+  r-key+```++## TODO+- Optimization. The viewer is too damn slow!+- Maybe restrict display only to a selected rectangle.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ arcgrid-viewer.cabal view
@@ -0,0 +1,30 @@+name:                arcgrid-viewer+version:             0.1.0.0+synopsis:            Simple viewer for ESRI/ArcInfo (ArcGrid) geospatial data+description:         A simple viewer for ESRI/ArcInfo (ArcGrid) files. Users+                     can pan, zoom and rotate the rendered dataset.+homepage:            https://github.com/nbrk/arcgrid-viewer+license:             BSD3+license-file:        LICENSE+author:              Nikolay Burkov+maintainer:          nbrk@linklevel.net+category:            Geo+build-type:          Simple+extra-source-files:  README.md+cabal-version:       >=1.10++executable arcgrid-viewer+  hs-source-dirs:      src+  main-is:             Main.hs+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  build-depends:       base >= 4.9 && < 5.0+                     , transformers+                     , bytestring+                     , arcgrid+                     , gloss+  other-modules:       Types, View, ColorScheme, Raster, Vector+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/nbrk/arcgrid-viewer
+ src/ColorScheme.hs view
@@ -0,0 +1,41 @@+module ColorScheme where++import Graphics.Gloss+import Control.Monad.Trans.Reader++import Types++colorFromValue :: Int -> ReaderT ViewerCtx IO Color+colorFromValue v = do+  (vmin, vmax) <- asks vctxMinMaxVal+  c <- asks vctxColorScheme+  -- X between A and B; we want Y to fall between C and D+  -- Y = (X-A)/(B-A) * (D-C) + C+  let d = fromIntegral $ abs $ vmax - vmin+  let dv = fromIntegral $ abs $ v - vmin+  let int = dv / d * (1.0 - 0) + 0+  case c of+    RedScheme -> return $ makeColor int 0 0 1+    BWScheme -> return $ greyN int+    FancyScheme -> fancyColor int+++fancyColor :: Float -> ReaderT ViewerCtx IO Color+fancyColor int = do+  let tz = thermalZone int+  let c = case tz of+        1 -> makeColor 0 0 int 1+        2 -> makeColor 0 int 1 1+        3 -> makeColor 0 1 (1 - int) 1+        4 -> makeColor int 1 0 1+        _ -> makeColor 1 (1 - int) 0 1+  -- let c = case tz of+  --       1 -> makeColor 0 int 1 1+  --       2 -> makeColor 0 1 (1 - int) 1+  --       3 -> makeColor int 1 0 1+  --       _ -> makeColor 1 (1 - int) 0 1++  return c+  where+    thermalZone i = truncate $ i / 0.2 + 1 -- 1 / 0.2, so 5 thermal zones+--    thermalZone i = truncate $ i / 0.25 + 1
+ src/Main.hs view
@@ -0,0 +1,71 @@+module Main where++import Graphics.Gloss (white)+import System.Console.GetOpt+import System.Environment+import Data.Maybe ( fromMaybe )+import Control.Monad.Trans.Reader++import Types+import View++defaultOptions = Options+               { optColorScheme = RedScheme+               , optRenderMode = RasterMode+               , optBGColor = white+               , optSqSize = 1+               , optInput = ""+               }++parseColorScheme :: String -> ColorScheme+parseColorScheme "red" = RedScheme+parseColorScheme "bw" = BWScheme+parseColorScheme "fancy" = FancyScheme+parseColorScheme _ = error "Incorrect color scheme"++parseRenderMode :: String -> RenderMode+parseRenderMode "raster" = RasterMode+parseRenderMode "vector" = VectorMode+parseRenderMode _ = error "Incorrect rendering mode"+++options :: [OptDescr (Options -> Options)]+options =+  [ Option ['c'] ["color"]+    (ReqArg (\a opts -> opts {optColorScheme = parseColorScheme a}) "MODE") "color scheme: red|bw|fancy"+  ,+    Option ['r'] ["mode"]+    (ReqArg (\a opts -> opts {optRenderMode = parseRenderMode a}) "MODE") "rendering mode: vector|raster"+  ]+++programOpts :: [String] -> IO (Options, [String])+programOpts argv = do+  pn <- getProgName+  case getOpt Permute options argv of+    (o,n,[]  ) -> return (foldl (flip id) defaultOptions o, n)+    (_,_,errs) -> do+      putStrLn $ "Error: " ++ concat errs+      errorUsage options+++errorUsage :: [OptDescr a] -> IO b+errorUsage opts = do+  pn <- getProgName+  putStrLn $ usageInfo (usageHeader pn) options+  ioError $ userError ""+  where+    usageHeader pn = "Usage: " ++ pn ++ " [OPTION...] <file>"+++main :: IO ()+main = do+  argv <- getArgs++  (opts, argv') <- programOpts argv+  case argv' of+    fname:_ -> runReaderT viewArcGridFile $ opts {optInput = fname}+    otherwise -> do+      putStrLn "Error: filename required"+      putStrLn ""+      errorUsage options
+ src/Raster.hs view
@@ -0,0 +1,24 @@+module Raster where++import Graphics.Gloss+import Control.Monad.Trans.Reader+import qualified Data.ByteString as B+import Data.Word++import Types+import ColorScheme+++packRGBA :: (Float, Float, Float, Float) -> [Word8]+packRGBA (r, g, b, a) = map (fromIntegral . round) [r * 255, g * 255, b * 255, a * 255]+++makeRasterPicture :: ReaderT ViewerCtx IO Picture+makeRasterPicture = do+   vs <- asks vctxValTblData+   (w, h) <- asks vctxValTblSize+   colors <- mapM (\(_, v) -> colorFromValue v) vs+   let rgbas = concatMap (packRGBA . rgbaOfColor) colors+   let bs = B.pack rgbas++   return $ bitmapOfByteString w h (BitmapFormat TopToBottom PxRGBA) bs False
+ src/Types.hs view
@@ -0,0 +1,26 @@+module Types where++import Graphics.Gloss (Color)++data ColorScheme = RedScheme | BWScheme | FancyScheme+data RenderMode = RasterMode | VectorMode++data Options = Options+               { optColorScheme  :: ColorScheme+               , optRenderMode :: RenderMode+               , optBGColor :: Color+               , optSqSize :: Float+               , optInput :: FilePath+               }+++data ViewerCtx = ViewerCtx+                 { vctxRenderMode :: RenderMode+                 , vctxColorScheme :: ColorScheme+                 , vctxBGColor :: Color+                 , vctxSqSize :: Float+                 , vctxValTblSize :: (Int, Int)+                 , vctxValTblData :: [((Int, Int), Int)]+                 , vctxMinMaxVal :: (Int, Int)+                 , vctxNodataVal :: Maybe Int+                 }
+ src/Vector.hs view
@@ -0,0 +1,27 @@+module Vector where++import Graphics.Gloss+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Reader+import Data.Monoid++import Types+import ColorScheme++makeVectorPicture :: ReaderT ViewerCtx IO Picture+makeVectorPicture = do+  vs <- asks vctxValTblData+  ps <- mapM pictureFromRowColValue vs+  return $ pictures ps+++pictureFromRowColValue :: ((Int, Int), Int) -> ReaderT ViewerCtx IO Picture+pictureFromRowColValue ((r, c), v) = do+  sq <- asks vctxSqSize+  vcolor <- colorFromValue v+  let mon = mconcat+        [ Endo $ translate (fromIntegral c * sq) (negate (fromIntegral r * sq))+        , Endo $ color vcolor+        ]+--  lift $ putStrLn $ "((r,c,),val)=" ++ show ((r,c), v) ++ " vcolor=" ++ show vcolor ++ " "+  return $ appEndo mon $ rectangleSolid sq sq
+ src/View.hs view
@@ -0,0 +1,56 @@+module View where++import Graphics.Gloss+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Reader+import qualified Data.List as L+import ArcGrid++import Types+import ColorScheme+import Vector+import Raster++viewArcGridFile :: ReaderT Options IO ()+viewArcGridFile = do+  opts <- ask+  ag <- lift $ arcGridFromFile (optInput opts)+  lift $ putStrLn $+    "Parser done. " +++    "Forming " ++ show (ncols ag) ++ "x" ++ show (nrows ag) ++ " viewport... "++  let rcs = [(r, c) | r <- [0..(nrows ag) - 1], c <- [0..(ncols ag) - 1]]+  let vs' = L.sort $ vat ag+  let vctx = ViewerCtx+             { vctxRenderMode = optRenderMode opts+             , vctxColorScheme = optColorScheme opts+             , vctxBGColor = optBGColor opts+             , vctxSqSize = optSqSize opts+             , vctxValTblSize = (ncols ag, nrows ag)+             , vctxValTblData = zip rcs (vat ag)+             , vctxMinMaxVal = (head vs', last vs')+             , vctxNodataVal = nodata_value ag+             }+--  lift $ putStrLn $ show $ vctxValTblData vctx++  lift $ runReaderT viewContext vctx+++makePicture :: ReaderT ViewerCtx IO Picture+makePicture = do+  r <- asks vctxRenderMode+  case r of+    VectorMode -> makeVectorPicture+    RasterMode -> makeRasterPicture+++viewContext :: ReaderT ViewerCtx IO ()+viewContext = do+  bg <- asks vctxBGColor+  pic <- makePicture+  lift $ display FullScreen bg pic+++++