module Diagrams.Parametric.Adjust
( adjust
, AdjustOpts(_adjMethod, _adjSide, _adjEps)
, adjMethod, adjSide, adjEps
, AdjustMethod(..), AdjustSide(..)
) where
import Control.Lens (makeLensesWith, lensRules, lensField, generateSignatures, (^.), (&), (.~), Lens')
import Data.Proxy
import Data.Default.Class
import Data.VectorSpace
import Diagrams.Core.V
import Diagrams.Parametric
data AdjustMethod v = ByParam (Scalar v)
| ByAbsolute (Scalar v)
| ToAbsolute (Scalar v)
data AdjustSide = Start
| End
| Both
deriving (Show, Read, Eq, Ord, Bounded, Enum)
data AdjustOpts v = AO { _adjMethod :: AdjustMethod v
, _adjSide :: AdjustSide
, _adjEps :: Scalar v
, _adjOptsvProxy__ :: Proxy v
}
makeLensesWith
( lensRules
& lensField .~ (\label ->
case label of
"_adjOptsvProxy__" -> Nothing
_ -> Just (drop 1 label)
)
& generateSignatures .~ False
)
''AdjustOpts
adjMethod :: Lens' (AdjustOpts v) (AdjustMethod v)
adjSide :: Lens' (AdjustOpts v) AdjustSide
adjEps :: Lens' (AdjustOpts v) (Scalar v)
instance Fractional (Scalar v) => Default (AdjustMethod v) where
def = ByParam 0.2
instance Default AdjustSide where
def = Both
instance Fractional (Scalar v) => Default (AdjustOpts v) where
def = AO def def stdTolerance Proxy
adjust :: (DomainBounds a, Sectionable a, HasArcLength a, Fractional (Scalar (V a)))
=> a -> AdjustOpts (V a) -> a
adjust s opts = section s
(if opts^.adjSide == End then domainLower s else getParam s)
(if opts^.adjSide == Start then domainUpper s else domainUpper s getParam (reverseDomain s))
where
getParam seg = case opts^.adjMethod of
ByParam p -> p * bothCoef
ByAbsolute len -> param (len * bothCoef)
ToAbsolute len -> param (absDelta len * bothCoef)
where
param = arcLengthToParam eps seg
absDelta len = arcLength eps s len
bothCoef = if opts^.adjSide == Both then 0.5 else 1
eps = opts^.adjEps