brush-strokes-0.1.0.0: src/cusps/bench/Bench/Types.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Bench.Types
( BrushStroke(..)
, TestCase(..)
, Point(..)
, Params(..)
, brushStrokeFunctions
) where
-- base
import Data.Coerce
( coerce )
import Data.Proxy
( Proxy(..) )
import Data.Type.Equality
( (:~:)(Refl) )
import GHC.Generics
( Generic )
import GHC.TypeNats
( sameNat )
-- containers
import Data.Sequence
( Seq )
-- brush-strokes
import Calligraphy.Brushes
import Math.Algebra.Dual
import Math.Bezier.Spline
import Math.Bezier.Stroke
import Math.Bezier.Stroke.EnvelopeEquation
import Math.Differentiable
import Math.Interval
import Math.Linear
import Math.Module
import Math.Ring
( Transcendental )
import Math.Root.Isolation
--------------------------------------------------------------------------------
data BrushStroke =
forall nbParams. ParamsCt nbParams =>
BrushStroke
{ brush :: !( Brush nbParams )
, stroke :: !( Point nbParams, Curve Open () ( Point nbParams ) )
}
data TestCase =
TestCase
{ testDescription :: String
, testBrushStroke :: BrushStroke
, testCuspOptions :: RootIsolationOptions N 3
, testStartBoxes :: [ ( Int, [ Box 2 ] ) ]
}
--------------------------------------------------------------------------------
type ParamsCt nbParams
= ( Show ( β nbParams )
, HasChainRule Double 2 ( β nbParams )
, HasChainRule π 3 ( πβ nbParams )
, Applicative ( D 2 nbParams )
, Applicative ( D 3 nbParams )
, Traversable ( D 2 nbParams )
, Traversable ( D 3 nbParams )
, Representable Double ( β nbParams )
, Representable π ( πβ nbParams )
, Module Double ( T ( β nbParams ) )
, Module π ( T ( πβ nbParams ) )
, Module ( D 2 nbParams Double ) ( D 2 nbParams ( β 2 ) )
, Module ( D 3 nbParams π ) ( D 3 nbParams ( πβ 2 ) )
, Transcendental ( D 2 nbParams Double )
, Transcendental ( D 3 nbParams π )
)
newtype Params nbParams = Params { getParams :: ( β nbParams ) }
deriving newtype instance Show ( β nbParams ) => Show ( Params nbParams )
data Point nbParams =
Point
{ pointCoords :: !( β 2 )
, pointParams :: !( Params nbParams ) }
deriving stock Generic
deriving stock instance Show ( β nbParams ) => Show ( Point nbParams )
getStrokeFunctions
:: forall nbParams
. ParamsCt nbParams
=> Brush nbParams
-- ^ brush shape
-> Point nbParams
-- ^ start point
-> Curve Open () ( Point nbParams )
-- ^ curve points
-> ( β 1 -> ( Seq ( CornerStrokeDatum 2 NonIV )
, Seq ( β 1 -> StrokeDatum 2 NonIV ) )
, πβ 1 -> ( Seq ( CornerStrokeDatum 3 IsIV )
, Seq ( πβ 1 -> StrokeDatum 3 IsIV )
)
)
getStrokeFunctions
( Brush { brushBaseShape
, brushBaseShapeI
, brushCorners
, brushCornersI
, mbRotation
} )
sp0 crv =
let
usedParams :: C 2 ( β 1 ) ( β nbParams )
path :: C 2 ( β 1 ) ( β 2 )
( path, usedParams ) =
pathAndUsedParams @2 @NonIV @nbParams coerce id id ( getParams . pointParams )
sp0 crv
usedParamsI :: C 3 ( πβ 1 ) ( πβ nbParams )
pathI :: C 3 ( πβ 1 ) ( πβ 2 )
( pathI, usedParamsI ) =
pathAndUsedParams @3 @IsIV @nbParams coerce point point ( getParams . pointParams )
sp0 crv
in ( brushStrokeData @2 @nbParams SNonIV
path usedParams
brushBaseShape
brushCorners
mbRotation
, brushStrokeData @3 @nbParams SIsIV
pathI usedParamsI
brushBaseShapeI
brushCornersI
( fmap ( \ rot -> unπβ1 . nonDecreasing ( β1 . rot ) ) mbRotation )
)
{-# INLINEABLE getStrokeFunctions #-}
{-# SPECIALISE getStrokeFunctions @0 #-}
{-# SPECIALISE getStrokeFunctions @1 #-}
{-# SPECIALISE getStrokeFunctions @2 #-}
{-# SPECIALISE getStrokeFunctions @3 #-}
{-# SPECIALISE getStrokeFunctions @4 #-}
brushStrokeFunctions
:: BrushStroke
-> ( β 1 -> ( Seq ( CornerStrokeDatum 2 NonIV )
, Seq ( β 1 -> StrokeDatum 2 NonIV ) )
, πβ 1 -> ( Seq ( CornerStrokeDatum 3 IsIV )
, Seq ( πβ 1 -> StrokeDatum 3 IsIV )
)
)
brushStrokeFunctions ( BrushStroke { stroke = ( sp0, crv ), brush = brush :: Brush nbParams } )
-- Trick for triggering specialisation... TODO improve this.
| Just Refl <- sameNat @nbParams @1 Proxy Proxy
= getStrokeFunctions @1 brush sp0 crv
| Just Refl <- sameNat @nbParams @2 Proxy Proxy
= getStrokeFunctions @2 brush sp0 crv
| Just Refl <- sameNat @nbParams @3 Proxy Proxy
= getStrokeFunctions @3 brush sp0 crv
| Just Refl <- sameNat @nbParams @4 Proxy Proxy
= getStrokeFunctions @4 brush sp0 crv
| otherwise
= getStrokeFunctions @nbParams brush sp0 crv