2023-01-09 19:54:19 +00:00
|
|
|
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
|
|
|
{-# LANGUAGE QuantifiedConstraints #-}
|
|
|
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
|
|
|
{-# LANGUAGE UndecidableInstances #-}
|
2022-02-11 21:05:13 +00:00
|
|
|
|
|
|
|
|
|
module MetaBrush.Brush
|
2023-01-13 22:10:06 +00:00
|
|
|
|
( WithParams(..)
|
|
|
|
|
, Brush(..), SomeBrush(..), BrushFunction
|
2023-01-08 16:16:14 +00:00
|
|
|
|
, PointFields, provePointFields, duplicates
|
2022-02-11 21:05:13 +00:00
|
|
|
|
)
|
|
|
|
|
where
|
|
|
|
|
|
|
|
|
|
-- base
|
2023-01-08 16:16:14 +00:00
|
|
|
|
import Data.Kind
|
|
|
|
|
( Type, Constraint )
|
|
|
|
|
import Data.List
|
|
|
|
|
( nub )
|
|
|
|
|
import Data.Typeable
|
|
|
|
|
( Typeable )
|
2022-02-11 21:05:13 +00:00
|
|
|
|
import GHC.Exts
|
2023-01-08 16:16:14 +00:00
|
|
|
|
( Proxy#, proxy# )
|
|
|
|
|
import GHC.TypeLits
|
|
|
|
|
( Symbol, someSymbolVal
|
|
|
|
|
, SomeSymbol(..)
|
|
|
|
|
)
|
2022-02-11 21:05:13 +00:00
|
|
|
|
|
|
|
|
|
-- deepseq
|
|
|
|
|
import Control.DeepSeq
|
2022-12-11 01:33:34 +00:00
|
|
|
|
( NFData(..) )
|
2022-02-11 21:05:13 +00:00
|
|
|
|
|
|
|
|
|
-- hashable
|
|
|
|
|
import Data.Hashable
|
|
|
|
|
( Hashable(..) )
|
|
|
|
|
|
|
|
|
|
-- text
|
|
|
|
|
import Data.Text
|
|
|
|
|
( Text )
|
|
|
|
|
import qualified Data.Text as Text
|
|
|
|
|
( unpack )
|
|
|
|
|
|
|
|
|
|
-- MetaBrush
|
2023-01-20 15:34:04 +00:00
|
|
|
|
import Math.Algebra.Dual
|
2023-01-21 14:24:08 +00:00
|
|
|
|
( C )
|
2022-02-11 21:05:13 +00:00
|
|
|
|
import Math.Bezier.Spline
|
2023-01-13 22:10:06 +00:00
|
|
|
|
( SplineType(Closed), Spline )
|
2023-01-20 15:34:04 +00:00
|
|
|
|
import Math.Differentiable
|
2023-01-21 14:24:08 +00:00
|
|
|
|
( DiffInterp, ExtentOrder )
|
|
|
|
|
import Math.Interval
|
|
|
|
|
( type I, Extent(Point, Interval) )
|
|
|
|
|
import Math.Linear
|
2022-02-11 21:05:13 +00:00
|
|
|
|
import MetaBrush.Records
|
2023-01-13 22:10:06 +00:00
|
|
|
|
( KnownSymbols, Length, Record )
|
2023-01-08 16:16:14 +00:00
|
|
|
|
import MetaBrush.Serialisable
|
2023-01-09 19:54:19 +00:00
|
|
|
|
( Serialisable )
|
2022-02-11 21:05:13 +00:00
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2023-01-13 22:10:06 +00:00
|
|
|
|
-- | A differentiable function from a given record type,
|
|
|
|
|
-- with provided default values that can be overridden.
|
2023-01-20 15:34:04 +00:00
|
|
|
|
type WithParams :: Type -> ( Type -> Type ) -> Type
|
2023-01-13 22:10:06 +00:00
|
|
|
|
data WithParams params f =
|
|
|
|
|
WithParams
|
2023-01-20 15:34:04 +00:00
|
|
|
|
{ defaultParams :: params
|
|
|
|
|
, withParams
|
|
|
|
|
:: forall i
|
|
|
|
|
. ( DiffInterp i params )
|
|
|
|
|
=> Proxy# i
|
|
|
|
|
-> ( forall a. a -> I i a )
|
2023-01-21 14:24:08 +00:00
|
|
|
|
-> C ( ExtentOrder i ) ( I i params ) ( f ( I i ( ℝ 2 ) ) )
|
2023-01-13 22:10:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2022-12-11 01:33:34 +00:00
|
|
|
|
-- | A brush function: a function from a record of parameters to a closed spline.
|
2023-01-08 16:16:14 +00:00
|
|
|
|
type BrushFunction :: [ Symbol ] -> Type
|
2023-01-20 15:34:04 +00:00
|
|
|
|
type BrushFunction brushFields =
|
|
|
|
|
WithParams ( Record brushFields ) ( Spline Closed () )
|
2022-02-11 21:05:13 +00:00
|
|
|
|
|
2023-01-08 16:16:14 +00:00
|
|
|
|
type Brush :: [ Symbol ] -> Type
|
2022-02-11 21:05:13 +00:00
|
|
|
|
data Brush brushFields where
|
|
|
|
|
BrushData
|
|
|
|
|
:: forall brushFields
|
2023-01-13 22:10:06 +00:00
|
|
|
|
. ( KnownSymbols brushFields, Typeable brushFields
|
2023-01-20 15:34:04 +00:00
|
|
|
|
, Representable Double ( ℝ ( Length brushFields ) )
|
|
|
|
|
, DiffInterp Point ( ℝ ( Length brushFields ) )
|
|
|
|
|
, DiffInterp Interval ( ℝ ( Length brushFields ) )
|
2023-01-13 22:10:06 +00:00
|
|
|
|
)
|
2023-01-08 16:16:14 +00:00
|
|
|
|
=> { brushName :: !Text
|
|
|
|
|
, brushFunction :: BrushFunction brushFields
|
|
|
|
|
}
|
2022-02-11 21:05:13 +00:00
|
|
|
|
-> Brush brushFields
|
|
|
|
|
|
|
|
|
|
data SomeBrush where
|
|
|
|
|
SomeBrush
|
2023-01-08 16:16:14 +00:00
|
|
|
|
:: { someBrush :: !( Brush brushFields ) }
|
2022-02-11 21:05:13 +00:00
|
|
|
|
-> SomeBrush
|
|
|
|
|
|
|
|
|
|
instance Show ( Brush brushFields ) where
|
2022-12-11 01:33:34 +00:00
|
|
|
|
show ( BrushData { brushName } ) =
|
2022-02-11 21:05:13 +00:00
|
|
|
|
"BrushData\n\
|
|
|
|
|
\ { brushName = " <> Text.unpack brushName <> "\n\
|
|
|
|
|
\ }"
|
2022-12-11 01:33:34 +00:00
|
|
|
|
|
2022-02-11 21:05:13 +00:00
|
|
|
|
instance NFData ( Brush brushFields ) where
|
2022-12-11 01:33:34 +00:00
|
|
|
|
rnf ( BrushData { brushName } )
|
|
|
|
|
= rnf brushName
|
2022-02-11 21:05:13 +00:00
|
|
|
|
instance Eq ( Brush brushFields ) where
|
2022-12-11 01:33:34 +00:00
|
|
|
|
BrushData name1 _ == BrushData name2 _ = name1 == name2
|
2022-02-11 21:05:13 +00:00
|
|
|
|
instance Ord ( Brush brushFields ) where
|
2022-12-11 01:33:34 +00:00
|
|
|
|
compare ( BrushData name1 _ ) ( BrushData name2 _ ) = compare name1 name2
|
2022-02-11 21:05:13 +00:00
|
|
|
|
instance Hashable ( Brush brushFields ) where
|
2022-12-11 01:33:34 +00:00
|
|
|
|
hashWithSalt salt ( BrushData { brushName } ) =
|
|
|
|
|
hashWithSalt salt brushName
|
2022-02-11 21:05:13 +00:00
|
|
|
|
|
2023-01-08 16:16:14 +00:00
|
|
|
|
type PointFields :: [ Symbol ] -> Constraint
|
|
|
|
|
class ( KnownSymbols pointFields, Typeable pointFields
|
|
|
|
|
, Serialisable ( Record pointFields )
|
|
|
|
|
, Show ( Record pointFields )
|
|
|
|
|
, NFData ( Record pointFields )
|
2023-01-20 15:34:04 +00:00
|
|
|
|
, Representable Double ( ℝ ( Length pointFields ) )
|
|
|
|
|
, DiffInterp Point ( ℝ ( Length pointFields ) )
|
|
|
|
|
, DiffInterp Interval ( ℝ ( Length pointFields ) )
|
2022-02-11 21:05:13 +00:00
|
|
|
|
)
|
2023-01-08 16:16:14 +00:00
|
|
|
|
=> PointFields pointFields where { }
|
|
|
|
|
instance ( KnownSymbols pointFields, Typeable pointFields
|
|
|
|
|
, Serialisable ( Record pointFields )
|
|
|
|
|
, Show ( Record pointFields )
|
|
|
|
|
, NFData ( Record pointFields )
|
2023-01-20 15:34:04 +00:00
|
|
|
|
, Representable Double ( ℝ ( Length pointFields ) )
|
|
|
|
|
, DiffInterp Point ( ℝ ( Length pointFields ) )
|
|
|
|
|
, DiffInterp Interval ( ℝ ( Length pointFields ) )
|
2023-01-08 16:16:14 +00:00
|
|
|
|
)
|
|
|
|
|
=> PointFields pointFields where { }
|
|
|
|
|
|
|
|
|
|
-- | Assumes the input has no duplicates (doesn't check.)
|
2023-01-20 15:34:04 +00:00
|
|
|
|
provePointFields :: [ Text ]
|
|
|
|
|
-> ( forall pointFields. PointFields pointFields => Proxy# pointFields -> r )
|
|
|
|
|
-> r
|
2023-01-08 16:16:14 +00:00
|
|
|
|
provePointFields fieldNames k =
|
|
|
|
|
case fieldNames of
|
|
|
|
|
[]
|
|
|
|
|
-> k ( proxy# @'[] )
|
|
|
|
|
[ f1 ]
|
|
|
|
|
| SomeSymbol @f1 _ <- someSymbolVal ( Text.unpack f1 )
|
|
|
|
|
-> k ( proxy# @'[ f1 ] )
|
|
|
|
|
[ f1, f2 ]
|
|
|
|
|
| SomeSymbol @f1 _ <- someSymbolVal ( Text.unpack f1 )
|
|
|
|
|
, SomeSymbol @f2 _ <- someSymbolVal ( Text.unpack f2 )
|
|
|
|
|
-> k ( proxy# @'[ f1, f2 ] )
|
|
|
|
|
[ f1, f2, f3 ]
|
|
|
|
|
| SomeSymbol @f1 _ <- someSymbolVal ( Text.unpack f1 )
|
|
|
|
|
, SomeSymbol @f2 _ <- someSymbolVal ( Text.unpack f2 )
|
|
|
|
|
, SomeSymbol @f3 _ <- someSymbolVal ( Text.unpack f3 )
|
|
|
|
|
-> k ( proxy# @'[ f1, f2, f3 ] )
|
|
|
|
|
_ -> error $ "I haven't defined ℝ " ++ show ( length fieldNames )
|
|
|
|
|
{-# INLINE provePointFields #-}
|
|
|
|
|
|
|
|
|
|
duplicates :: [ Text ] -> [ Text ]
|
|
|
|
|
duplicates = nub . duplicatesAcc [] []
|
|
|
|
|
where
|
|
|
|
|
duplicatesAcc :: [ Text ] -> [ Text ] -> [ Text ] -> [ Text ]
|
|
|
|
|
duplicatesAcc _ dups [] = dups
|
|
|
|
|
duplicatesAcc seen dups ( k : kvs )
|
|
|
|
|
| k `elem` seen
|
|
|
|
|
= duplicatesAcc seen ( k : dups ) kvs
|
|
|
|
|
| otherwise
|
|
|
|
|
= duplicatesAcc ( k : seen ) dups kvs
|