2023-01-09 03:27:08 +00:00
|
|
|
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2020-08-29 17:41:07 +00:00
|
|
|
|
|
2020-11-12 17:34:46 +00:00
|
|
|
|
module MetaBrush.Asset.Brushes where
|
|
|
|
|
|
2022-12-11 01:33:34 +00:00
|
|
|
|
-- containers
|
|
|
|
|
import qualified Data.Sequence as Seq
|
|
|
|
|
( fromList )
|
2021-04-25 23:17:27 +00:00
|
|
|
|
|
2020-11-12 17:34:46 +00:00
|
|
|
|
-- text
|
|
|
|
|
import Data.Text
|
|
|
|
|
( Text )
|
2022-12-11 01:33:34 +00:00
|
|
|
|
|
|
|
|
|
-- unordered-containers
|
|
|
|
|
import Data.HashMap.Strict
|
|
|
|
|
( HashMap )
|
|
|
|
|
import qualified Data.HashMap.Strict as HashMap
|
|
|
|
|
( fromList, lookup )
|
2020-08-29 17:41:07 +00:00
|
|
|
|
|
|
|
|
|
-- MetaBrush
|
2022-12-11 01:33:34 +00:00
|
|
|
|
import Math.Bezier.Spline
|
2023-01-08 16:16:14 +00:00
|
|
|
|
import Math.Linear
|
2023-01-09 19:54:19 +00:00
|
|
|
|
( ℝ(..), Fin(..) )
|
2023-01-08 16:16:14 +00:00
|
|
|
|
import Math.Linear.Dual
|
2023-01-09 19:54:19 +00:00
|
|
|
|
( D, type (~>)(..), var, konst )
|
2023-01-08 16:16:14 +00:00
|
|
|
|
import Math.Module
|
|
|
|
|
( Module((^+^), (*^)) )
|
2020-11-14 22:32:23 +00:00
|
|
|
|
import MetaBrush.Brush
|
2022-12-11 01:33:34 +00:00
|
|
|
|
( Brush(..), SomeBrush(..) )
|
|
|
|
|
import MetaBrush.Records
|
2020-08-29 17:41:07 +00:00
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2022-12-11 01:33:34 +00:00
|
|
|
|
lookupBrush :: Text -> Maybe SomeBrush
|
|
|
|
|
lookupBrush nm = HashMap.lookup nm brushes
|
2020-08-29 17:41:07 +00:00
|
|
|
|
|
2022-12-11 01:33:34 +00:00
|
|
|
|
-- | All brushes supported by this application.
|
|
|
|
|
brushes :: HashMap Text SomeBrush
|
|
|
|
|
brushes = HashMap.fromList
|
|
|
|
|
[ ( nm, b )
|
|
|
|
|
| b@( SomeBrush ( BrushData { brushName = nm } ) )
|
|
|
|
|
<- [ SomeBrush circle, SomeBrush ellipse ]
|
|
|
|
|
]
|
2021-05-13 20:07:49 +00:00
|
|
|
|
|
2022-12-11 01:33:34 +00:00
|
|
|
|
-- | Root of @(Sqrt[2] (4 + 3 κ) - 16) (2 - 3 κ)^2 - 8 (1 - 3 κ) Sqrt[8 - 24 κ + 12 κ^2 + 8 κ^3 + 3 κ^4]@.
|
|
|
|
|
--
|
|
|
|
|
-- Used to approximate circles and ellipses with Bézier curves.
|
2023-01-08 16:16:14 +00:00
|
|
|
|
κ :: Double
|
|
|
|
|
κ = 0.5519150244935105707435627227925
|
2021-05-25 11:45:21 +00:00
|
|
|
|
|
2023-01-09 03:27:08 +00:00
|
|
|
|
type CircleBrushFields = '[ "r" ]
|
2022-12-11 01:33:34 +00:00
|
|
|
|
circle :: Brush CircleBrushFields
|
2023-01-09 03:27:08 +00:00
|
|
|
|
circle = BrushData "circle" ( WithParams deflts circleBrush )
|
2020-08-29 17:41:07 +00:00
|
|
|
|
where
|
2023-01-08 16:16:14 +00:00
|
|
|
|
deflts :: Record CircleBrushFields
|
|
|
|
|
deflts = MkR ( ℝ1 1 )
|
2020-08-29 17:41:07 +00:00
|
|
|
|
|
2023-01-08 16:16:14 +00:00
|
|
|
|
type EllipseBrushFields = '[ "a", "b", "phi" ]
|
2022-12-11 01:33:34 +00:00
|
|
|
|
ellipse :: Brush EllipseBrushFields
|
2023-01-09 03:27:08 +00:00
|
|
|
|
ellipse = BrushData "ellipse" ( WithParams deflts ellipseBrush )
|
2022-12-11 01:33:34 +00:00
|
|
|
|
where
|
2023-01-08 16:16:14 +00:00
|
|
|
|
deflts :: Record EllipseBrushFields
|
|
|
|
|
deflts = MkR ( ℝ3 1 1 0 )
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
-- Differentiable brushes.
|
|
|
|
|
|
2023-01-09 03:27:08 +00:00
|
|
|
|
circleSpline :: Applicative ( D u ) => ( Double -> Double -> D u v ) -> D u ( Spline 'Closed () v )
|
|
|
|
|
circleSpline p = sequenceA $
|
2023-01-08 16:16:14 +00:00
|
|
|
|
Spline { splineStart = p 1 0
|
|
|
|
|
, splineCurves = ClosedCurves crvs lastCrv }
|
|
|
|
|
where
|
|
|
|
|
crvs = Seq.fromList
|
|
|
|
|
[ Bezier3To (p 1 κ) (p κ 1) (NextPoint (p 0 1)) ()
|
|
|
|
|
, Bezier3To (p -κ 1) (p -1 κ) (NextPoint (p -1 0)) ()
|
|
|
|
|
, Bezier3To (p -1 -κ) (p -κ -1) (NextPoint (p 0 -1)) ()
|
|
|
|
|
]
|
|
|
|
|
lastCrv =
|
|
|
|
|
Bezier3To (p κ -1) (p 1 -κ) BackToStart ()
|
|
|
|
|
|
2023-01-09 03:27:08 +00:00
|
|
|
|
circleBrush :: Record CircleBrushFields ~> Spline 'Closed () ( ℝ 2 )
|
|
|
|
|
circleBrush =
|
|
|
|
|
D \ params ->
|
|
|
|
|
let r :: D ( Record CircleBrushFields ) Double
|
2023-01-09 19:54:19 +00:00
|
|
|
|
r = runD ( var ( Fin 1## ) ) params
|
2023-01-09 03:27:08 +00:00
|
|
|
|
mkPt :: Double -> Double -> D ( Record CircleBrushFields ) ( ℝ 2 )
|
|
|
|
|
mkPt ( kon -> x ) ( kon -> y )
|
2023-01-09 19:54:19 +00:00
|
|
|
|
= ( x * r ) *^ e_x
|
2023-01-09 03:27:08 +00:00
|
|
|
|
^+^ ( y * r ) *^ e_y
|
|
|
|
|
in circleSpline @( Record CircleBrushFields ) mkPt
|
|
|
|
|
where
|
2023-01-09 19:54:19 +00:00
|
|
|
|
e_x, e_y :: D ( Record CircleBrushFields ) ( ℝ 2 )
|
|
|
|
|
e_x = pure $ ℝ2 1 0
|
|
|
|
|
e_y = pure $ ℝ2 0 1
|
2023-01-09 03:27:08 +00:00
|
|
|
|
|
|
|
|
|
kon = konst @( Record CircleBrushFields )
|
|
|
|
|
|
|
|
|
|
ellipseBrush :: Record EllipseBrushFields ~> Spline 'Closed () ( ℝ 2 )
|
2023-01-08 16:16:14 +00:00
|
|
|
|
ellipseBrush =
|
|
|
|
|
D \ params ->
|
2023-01-09 03:27:08 +00:00
|
|
|
|
let a, b, phi :: D ( Record EllipseBrushFields ) Double
|
2023-01-09 19:54:19 +00:00
|
|
|
|
a = runD ( var ( Fin 1## ) ) params
|
|
|
|
|
b = runD ( var ( Fin 2## ) ) params
|
|
|
|
|
phi = runD ( var ( Fin 3## ) ) params
|
2023-01-09 03:27:08 +00:00
|
|
|
|
mkPt :: Double -> Double -> D ( Record EllipseBrushFields ) ( ℝ 2 )
|
|
|
|
|
mkPt ( kon -> x ) ( kon -> y )
|
2023-01-09 19:54:19 +00:00
|
|
|
|
= ( x * a * cos phi - y * b * sin phi ) *^ e_x
|
2023-01-08 16:16:14 +00:00
|
|
|
|
^+^ ( y * b * cos phi + x * a * sin phi ) *^ e_y
|
2023-01-09 03:27:08 +00:00
|
|
|
|
in circleSpline @( Record EllipseBrushFields ) mkPt
|
2023-01-08 16:16:14 +00:00
|
|
|
|
where
|
2023-01-09 19:54:19 +00:00
|
|
|
|
e_x, e_y :: D ( Record EllipseBrushFields ) ( ℝ 2 )
|
|
|
|
|
e_x = pure $ ℝ2 1 0
|
|
|
|
|
e_y = pure $ ℝ2 0 1
|
2023-01-08 16:16:14 +00:00
|
|
|
|
|
2023-01-09 03:27:08 +00:00
|
|
|
|
kon = konst @( Record EllipseBrushFields )
|