module Reanimate.Builtin.TernaryPlot
  ( ACoord
  , BCoord
  , CCoord
  , ternaryPlot
  
  
  , toCartesianCoords
  , toOffsetCartesianCoords
  , fromCartesianCoords
  ) where
import           Codec.Picture    (PixelRGBA8 (..), generateImage)
import           Graphics.SvgTree (Tree)
import           Reanimate.Raster (embedImage)
import           Reanimate.Svg    (flipYAxis, scaleToWidth, translate)
type ACoord = Double
type BCoord = Double
type CCoord = Double
ternaryPlot :: Int 
            -> (ACoord -> BCoord -> CCoord -> PixelRGBA8)
            
            
            
            -> Tree
ternaryPlot :: Int -> (ACoord -> ACoord -> ACoord -> PixelRGBA8) -> Tree
ternaryPlot Int
density ACoord -> ACoord -> ACoord -> PixelRGBA8
fn =
    ACoord -> Tree -> Tree
scaleToWidth ACoord
stdWidth (Tree -> Tree) -> Tree -> Tree
forall a b. (a -> b) -> a -> b
$
    ACoord -> ACoord -> Tree -> Tree
translate (-ACoord
cX) (-ACoord
cY) (Tree -> Tree) -> Tree -> Tree
forall a b. (a -> b) -> a -> b
$
    ACoord -> Tree -> Tree
scaleToWidth ACoord
1 (Tree -> Tree) -> Tree -> Tree
forall a b. (a -> b) -> a -> b
$
    Tree -> Tree
flipYAxis (Tree -> Tree) -> Tree -> Tree
forall a b. (a -> b) -> a -> b
$
    ACoord -> ACoord -> Tree -> Tree
translate (Int -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
densityACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
2) (-Int -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
heightACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
2) (Tree -> Tree) -> Tree -> Tree
forall a b. (a -> b) -> a -> b
$
    Image PixelRGBA8 -> Tree
forall a. PngSavable a => Image a -> Tree
embedImage (Image PixelRGBA8 -> Tree) -> Image PixelRGBA8 -> Tree
forall a b. (a -> b) -> a -> b
$ (Int -> Int -> PixelRGBA8) -> Int -> Int -> Image PixelRGBA8
forall px. Pixel px => (Int -> Int -> px) -> Int -> Int -> Image px
generateImage Int -> Int -> PixelRGBA8
forall a a. (Integral a, Integral a) => a -> a -> PixelRGBA8
gen Int
density Int
height
  where
    stdWidth :: ACoord
stdWidth = ACoord
5
    (ACoord
cX, ACoord
cY) = ACoord -> ACoord -> (ACoord, ACoord)
toCartesianCoords (ACoord
1ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
3) (ACoord
1ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
3)
    height :: Int
height = ACoord -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round (Int -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
density ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
* (ACoord -> ACoord
forall a. Floating a => a -> a
sqrt ACoord
3 ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ ACoord
2) :: Double)
    gen :: a -> a -> PixelRGBA8
gen a
x a
y =
      let
          x' :: ACoord
x' = (a -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
x ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ Int -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
density)
          y' :: ACoord
y' = (a -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
y ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ Int -> ACoord
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
density)
          aCoord :: ACoord
aCoord = (ACoord
x'ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
*ACoord
2ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
-ACoord
bCoord)ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
2
          bCoord :: ACoord
bCoord = ACoord
y' ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ (ACoord -> ACoord
forall a. Floating a => a -> a
sqrt ACoord
3 ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ ACoord
2)
          cCoord :: ACoord
cCoord = ACoord
1 ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
- ACoord
aCoord ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
- ACoord
bCoord
      in if ACoord
aCoord ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
+ ACoord
bCoord ACoord -> ACoord -> Bool
forall a. Ord a => a -> a -> Bool
> ACoord
1 Bool -> Bool -> Bool
|| ACoord
aCoord ACoord -> ACoord -> Bool
forall a. Ord a => a -> a -> Bool
< ACoord
0 Bool -> Bool -> Bool
|| ACoord
bCoord ACoord -> ACoord -> Bool
forall a. Ord a => a -> a -> Bool
< ACoord
0 Bool -> Bool -> Bool
|| ACoord
cCoord ACoord -> ACoord -> Bool
forall a. Ord a => a -> a -> Bool
< ACoord
0
        then Pixel8 -> Pixel8 -> Pixel8 -> Pixel8 -> PixelRGBA8
PixelRGBA8 Pixel8
0 Pixel8
0 Pixel8
0 Pixel8
0
        else ACoord -> ACoord -> ACoord -> PixelRGBA8
fn ACoord
aCoord ACoord
bCoord ACoord
cCoord
toCartesianCoords :: ACoord -> BCoord -> (Double, Double)
toCartesianCoords :: ACoord -> ACoord -> (ACoord, ACoord)
toCartesianCoords ACoord
a ACoord
b = (ACoord
x, ACoord
y)
  where
    x :: ACoord
x = (ACoord
aACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
+ACoord
2ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
*ACoord
b)ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
2
    y :: ACoord
y = (ACoord -> ACoord
forall a. Floating a => a -> a
sqrt ACoord
3 ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ ACoord
2) ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
* ACoord
a
toOffsetCartesianCoords :: ACoord -> BCoord -> (Double, Double)
toOffsetCartesianCoords :: ACoord -> ACoord -> (ACoord, ACoord)
toOffsetCartesianCoords ACoord
a ACoord
b =
    (ACoord
txACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
-ACoord
zx, ACoord
tyACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
-ACoord
zy)
  where
    (ACoord
zx,ACoord
zy) = ACoord -> ACoord -> (ACoord, ACoord)
toCartesianCoords (ACoord
1ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
3) (ACoord
1ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
3)
    (ACoord
tx,ACoord
ty) = ACoord -> ACoord -> (ACoord, ACoord)
toCartesianCoords ACoord
a ACoord
b
fromCartesianCoords :: Double -> Double -> (ACoord, BCoord, CCoord)
fromCartesianCoords :: ACoord -> ACoord -> (ACoord, ACoord, ACoord)
fromCartesianCoords ACoord
x ACoord
y = (ACoord
a,ACoord
b,ACoord
1ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
-ACoord
aACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
-ACoord
b)
  where
    a :: ACoord
a = (ACoord
xACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
*ACoord
2ACoord -> ACoord -> ACoord
forall a. Num a => a -> a -> a
-ACoord
b)ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ACoord
2
    b :: ACoord
b = ACoord
y ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ (ACoord -> ACoord
forall a. Floating a => a -> a
sqrt ACoord
3 ACoord -> ACoord -> ACoord
forall a. Fractional a => a -> a -> a
/ ACoord
2)