{-# LANGUAGE ViewPatterns #-} -------------------------------------------------------------------------------- -- | -- Module : ArrayFire.Graphics -- Copyright : David Johnson (c) 2019-2020 -- License : BSD 3 -- Maintainer : David Johnson <djohnson.m@gmail.com> -- Stability : Experimental -- Portability : GHC -- -------------------------------------------------------------------------------- module ArrayFire.Graphics where import Control.Exception import Foreign.Marshal import Foreign.Storable import Foreign.ForeignPtr import Foreign.C.String import ArrayFire.Internal.Graphics import ArrayFire.Exception import ArrayFire.FFI import ArrayFire.Internal.Types -- | Create window -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm) -- -- >>> window <- createWindow 800 600 "New Chart" -- createWindow :: Int -- ^ width -> Int -- ^ height -> String -- ^ title -> IO Window -- ^ 'Window' handle createWindow (fromIntegral -> x) (fromIntegral -> y) str = withCString str $ \cstr -> createWindow' (\p -> af_create_window p x y cstr) -- | Sets 'Window' position -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm) -- -- >>> window <- createWindow 800 600 "New Chart" -- >>> setPosition window 800 600 -- setPosition :: Window -- ^ 'Window' handle -> Int -- ^ Horizontal start coordinate -> Int -- ^ Vertical start coordinate -> IO () setPosition w (fromIntegral -> x) (fromIntegral -> y) = w `opw` (\p -> af_set_position p x y) -- | Sets 'Window' title -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm) -- -- >>> window <- createWindow 800 600 "New Chart" -- >>> setTitle window "window title" -- setTitle :: Window -- ^ 'Window' handle -> String -- ^ title -> IO () setTitle w str = withCString str $ \cstr -> w `opw` (\p -> af_set_title p cstr) -- | Sets 'Window' size -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm) -- -- >>> window <- createWindow 800 600 "New Chart" -- >>> setSize window 800 600 -- setSize :: Window -- ^ 'Window' handle -> Int -- ^ target width of the window -> Int -- ^ target height of the window -> IO () setSize w (fromIntegral -> x) (fromIntegral -> y) = w `opw` (\p -> af_set_size p x y) -- | Draw an image onto a Window -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- >>> drawImage window ('constant' \@'Int' 1) ('Cell' 10 10 "test" 'ColorMapSpectrum') -- drawImage :: Window -- ^ 'Window' handle -> Array a -- ^ Image -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawImage (Window wfptr) (Array fptr) cell = mask_ $ withForeignPtr fptr $ \aptr -> withForeignPtr wfptr $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_image wptr aptr cellPtr free cellPtr -- | Draw a plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- >>> drawPlot window ('constant' \@'Int' 1) ('constant' \@'Int' 1) ('Cell' 10 10 "test" 'ColorMapSpectrum') -- -- *Note* X and Y should be vectors. -- drawPlot :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the x-axis data points -> Array a -- ^ is an 'Array' with the y-axis data points -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawPlot (Window w) (Array fptr1) (Array fptr2) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_plot wptr ptr1 ptr2 cellPtr free cellPtr -- | Draw a plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- *Note* P should be a 3n x 1 vector or one of a 3xn or nx3 matrices. -- drawPlot3 :: Window -- ^ the window handle -> Array a -- ^ is an af_array or matrix with the xyz-values of the points -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () drawPlot3 (Window w) (Array fptr) cell = mask_ $ withForeignPtr fptr $ \aptr -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_plot3 wptr aptr cellPtr free cellPtr -- | Draw a plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- *Note* in must be 2d and of the form [n, order], where order is either 2 or 3. If order is 2, then chart is 2D and if order is 3, then chart is 3D. -- drawPlotNd :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' or matrix with the xyz-values of the points -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawPlotNd (Window w) (Array fptr) cell = mask_ $ withForeignPtr fptr $ \aptr -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_plot_nd wptr aptr cellPtr free cellPtr -- | Draw a plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- *Note* X and Y should be vectors. -- drawPlot2d :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the x-axis data points -> Array a -- ^ is an 'Array' with the y-axis data points -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawPlot2d (Window w) (Array fptr1) (Array fptr2) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_plot_2d wptr ptr1 ptr2 cellPtr free cellPtr -- | Draw a 3D plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- *Note* X, Y and Z should be vectors. -- drawPlot3d :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the x-axis data points -> Array a -- ^ is an 'Array' with the y-axis data points -> Array a -- ^ is an 'Array' with the z-axis data points -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawPlot3d (Window w) (Array fptr1) (Array fptr2) (Array fptr3) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr fptr3 $ \ptr3 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_plot_3d wptr ptr1 ptr2 ptr3 cellPtr free cellPtr -- | Draw a scatter plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm) -- -- *Note* X and Y should be vectors. -- drawScatter :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the x-axis data points -> Array a -- ^ is an 'Array' with the y-axis data points -> MarkerType -- ^ enum specifying which marker to use in the scatter plot -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawScatter (Window w) (Array fptr1) (Array fptr2) (fromMarkerType -> m) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_scatter wptr ptr1 ptr2 m cellPtr free cellPtr -- | Draw a scatter plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#ga764410fbdf0cd60c7044c77e36fb2577) -- -- *Note* X and Y should be vectors. -- drawScatter3 :: Window -- ^ is the window handle -> Array a -- ^ is an af_array or matrix with the xyz-values of the points -> MarkerType -- ^ is an af_marker_type enum specifying which marker to use in the scatter plot -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () drawScatter3 (Window w) (Array fptr1) (fromMarkerType -> m) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_scatter3 wptr ptr1 m cellPtr free cellPtr -- | Draw a scatter plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#ga9991b93681e0c18693a5464458781d22) -- -- *Note* in must be 2d and of the form [n, order], where order is either 2 or 3. If order is 2, then chart is 2D and if order is 3, then chart is 3D. -- drawScatterNd :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' or matrix with the xyz-values of the points -> MarkerType -- ^ is an af_marker_type enum specifying which marker to use in the scatter plot -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () drawScatterNd (Window w) (Array fptr1) (fromMarkerType -> m) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_scatter_nd wptr ptr1 m cellPtr free cellPtr -- | Draw a scatter plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#ga79417722c69883e7a91282b138288010) -- -- *Note* in must be 2d and of the form [n, order], where order is either 2 or 3. If order is 2, then chart is 2D and if order is 3, then chart is 3D. -- drawScatter2d :: Window -- ^ is the window handle -> Array a -- ^ is an af_array with the x-axis data points -> Array a -- ^ is an af_array with the y-axis data points -> MarkerType -- ^ is an af_marker_type enum specifying which marker to use in the scatter plot -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () drawScatter2d (Window w) (Array fptr1) (Array fptr2) (fromMarkerType -> m) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr w $ \wptr -> withForeignPtr fptr2 $ \ptr2 -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_scatter_2d wptr ptr1 ptr2 m cellPtr free cellPtr -- | Draw a scatter plot onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#ga2b3d0dd690ebcba4c4dbb09cdcaed304) -- -- *Note* X, Y and Z should be vectors. -- drawScatter3d :: Window -- ^ is the window handle -> Array a -- ^ is an af_array with the x-axis data points -> Array a -- ^ is an af_array with the y-axis data points -> Array a -- ^ is an af_array with the z-axis data points -> MarkerType -- ^ is an af_marker_type enum specifying which marker to use in the scatter plot -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () drawScatter3d (Window w) (Array fptr1) (Array fptr2) (Array fptr3) (fromMarkerType -> m) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr w $ \wptr -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr fptr3 $ \ptr3 -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_scatter_3d wptr ptr1 ptr2 ptr3 m cellPtr free cellPtr -- | Draw a Histogram onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#gaf1648ee35739c86116bfa9c22644dbd7) -- -- *Note* X should be a vector. -- drawHistogram :: Window -- ^ is the window handle -> Array a -- ^ is the data frequency af_array -> Double -- ^ is the value of the minimum data point of the array whose histogram(X) is going to be rendered. -> Double -- ^ is the value of the maximum data point of the array whose histogram(X) is going to be rendered. -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawHistogram (Window w) (Array fptr1) minval maxval cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_hist wptr ptr1 minval maxval cellPtr -- | Draw a Surface onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#gaaee14e457272b2cd1bd4ed1228370229) -- -- *Note* X and Y should be vectors. S should be a 2D array -- drawSurface :: Window -- ^ is the window handle -> Array a -- ^ is an af_array with the x-axis data points -> Array a -- ^ is an af_array with the y-axis data points -> Array a -- ^ is an af_array with the z-axis data points -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () drawSurface (Window w) (Array fptr1) (Array fptr2) (Array fptr3) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr w $ \wptr -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr fptr3 $ \ptr3 -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_surface wptr ptr1 ptr2 ptr3 cellPtr free cellPtr -- | Draw a Vector Field onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#ga2d31a148578d749be4224e7119b386bc) -- -- *Note* all the 'Array' inputs should be vectors and the same size -- drawVectorFieldND :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the points -> Array a -- ^ is an 'Array' with the directions -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawVectorFieldND (Window w) (Array fptr1) (Array fptr2) cell = mask_ $ withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_vector_field_nd wptr ptr1 ptr2 cellPtr free cellPtr -- | Draw a Vector Field onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#gaf2d3be32c1b6a9034a3bb851206b4b5a) -- -- *Note* all the 'Array' inputs should be vectors and the same size -- drawVectorField3d :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the x-axis points -> Array a -- ^ is an 'Array' with the y-axis points -> Array a -- ^ is an 'Array' with the z-axis points -> Array a -- ^ is an 'Array' with the x-axis directions -> Array a -- ^ is an 'Array' with the y-axis directions -> Array a -- ^ is an 'Array' with the z-axis directions -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () drawVectorField3d (Window w) (Array fptr1) (Array fptr2) (Array fptr3) (Array fptr4) (Array fptr5) (Array fptr6) cell = mask_ $ do withForeignPtr w $ \wptr -> withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr fptr3 $ \ptr3 -> withForeignPtr fptr4 $ \ptr4 -> withForeignPtr fptr5 $ \ptr5 -> withForeignPtr fptr6 $ \ptr6 -> do alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_vector_field_3d wptr ptr1 ptr2 ptr3 ptr4 ptr5 ptr6 cellPtr free cellPtr -- | Draw a Vector Field onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__draw.htm#gaa1a667e4d29ab089629acd5296f29a7b) -- -- *Note* all the 'Array' inputs should be vectors and the same size -- drawVectorField2d :: Window -- ^ is the window handle -> Array a -- ^ is an 'Array' with the x-axis points -> Array a -- ^ is the window handle -> Array a -- ^ is the window handle -> Array a -- ^ is the window handle -> Cell -- ^ is the window handle -> IO () drawVectorField2d (Window w) (Array fptr1) (Array fptr2) (Array fptr3) (Array fptr4) cell = mask_ $ do withForeignPtr w $ \wptr -> withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr fptr3 $ \ptr3 -> withForeignPtr fptr4 $ \ptr4 -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_draw_vector_field_2d wptr ptr1 ptr2 ptr3 ptr4 cellPtr free cellPtr -- | Draw a grid onto a 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#ga37fc7eb00ae11c25e1a60d341663d68d) -- -- *Note* all the 'Array' inputs should be vectors and the same size -- grid :: Window -- ^ is the window handle -> Int -- ^ is number of rows you want to show in a window -> Int -- ^ is number of coloumns you want to show in a window -> IO () grid (Window w) (fromIntegral -> rows) (fromIntegral -> cols) = mask_ . withForeignPtr w $ \wptr -> throwAFError =<< af_grid wptr rows cols -- | Setting axes limits for a histogram/plot/surface/vector field. -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#ga62d2cad30e3aad06c24999fe5ac34598) -- -- *Note* Set to NULL if the chart is 2D. -- setAxesLimitsCompute :: Window -- ^ is the window handle -> Array a -- ^ the data to compute the limits for x-axis. -> Array a -- ^ the data to compute the limits for y-axis. -> Array a -- ^ the data to compute the limits for z-axis. -> Bool -- ^ is for using the exact min/max values from x, y and z. If exact is false then the most significant digit is rounded up to next power of 2 and the magnitude remains the same. -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () setAxesLimitsCompute (Window w) (Array fptr1) (Array fptr2) (Array fptr3) (fromIntegral . fromEnum -> exact) cell = mask_ $ do withForeignPtr w $ \wptr -> withForeignPtr fptr1 $ \ptr1 -> withForeignPtr fptr2 $ \ptr2 -> withForeignPtr fptr3 $ \ptr3 -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_set_axes_limits_compute wptr ptr1 ptr2 ptr3 exact cellPtr free cellPtr -- | Setting axes limits for a 2D histogram/plot/surface/vector field. -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#gadadc41caf7d6a9b7ca2e674079971895) -- setAxesLimits2d :: Window -- ^ is the window handle -> Float -- ^ is the minimum on x-axis -> Float -- ^ is the maximum on x-axis -> Float -- ^ is the minimum on y-axis -> Float -- ^ is the maximum on y-axis -> Bool -- ^ is for using the exact min/max values from x, and y. If exact is false then the most significant digit is rounded up to next power of 2 and the magnitude remains the same. -> Cell -- ^ is structure af_cell that has the properties that are used for the current rendering. -> IO () setAxesLimits2d (Window w) xmin xmax ymin ymax (fromIntegral . fromEnum -> exact) cell = mask_ $ do withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_set_axes_limits_2d wptr xmin xmax ymin ymax exact cellPtr free cellPtr -- | Setting axes limits for a 3D histogram/plot/surface/vector field. -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#gadcd1bd46b9d6fabc047365ca5dc3f73d) -- setAxesLimits3d :: Window -- ^ is the window handle -> Float -- ^ is the minimum on x-axis -> Float -- ^ is the maximum on x-axis -> Float -- ^ is the minimum on y-axis -> Float -- ^ is the maximum on y-axis -> Float -- ^ is the minimum on z-axis -> Float -- ^ is the maximum on z-axis -> Bool -- ^ is for using the exact min/max values from x, y and z. If exact is false then the most significant digit is rounded up to next power of 2 and the magnitude remains the same. -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () setAxesLimits3d (Window w) xmin xmax ymin ymax zmin zmax (fromIntegral . fromEnum -> exact) cell = mask_ $ do withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_set_axes_limits_3d wptr xmin xmax ymin ymax zmin zmax exact cellPtr free cellPtr -- | Setting axes titles -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#gadcd1bd46b9d6fabc047365ca5dc3f73d) -- setAxesTitles :: Window -- ^ is the window handle -> String -- ^ is the name of the x-axis -> String -- ^ is the name of the y-axis -> String -- ^ is the name of the z-axis -> Cell -- ^ is structure 'Cell' that has the properties that are used for the current rendering. -> IO () setAxesTitles (Window w) x y z cell = mask_ $ do withForeignPtr w $ \wptr -> alloca $ \cellPtr -> do withCString x $ \xstr -> withCString y $ \ystr -> withCString z $ \zstr -> do poke cellPtr =<< cellToAFCell cell throwAFError =<< af_set_axes_titles wptr xstr ystr zstr cellPtr free cellPtr -- | Displays 'Window' -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#ga50dae861324dca1cce9f583256f5a654) -- showWindow :: Window -- ^ 'Window' handle -> IO () showWindow = (`opw` af_show) -- | Checks if 'Window' is closed -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#ga50dae861324dca1cce9f583256f5a654) -- isWindowClosed :: Window -> IO Bool isWindowClosed w = toEnum . fromIntegral <$> (w `opw1` af_is_window_closed) -- | Sets 'Window' visibility -- -- [ArrayFire Docs](http://arrayfire.org/docs/group__gfx__func__window.htm#gad7b63c70d45e101c4d8d500273e310c7) -- setVisibility :: Window -- ^ 'Window' handle -> Bool -- ^ Set to 'True' to display 'Window' -> IO () setVisibility w (fromIntegral . fromEnum -> b) = w `opw` (`af_set_visibility` b)