{-# LANGUAGE FlexibleContexts #-} module GraphRewriting.Layout.SpringEmbedder where import GraphRewriting.Graph import GraphRewriting.Graph.Read import GraphRewriting.Layout.Position import GraphRewriting.Layout.PortSpec import GraphRewriting.Layout.Rotation import GraphRewriting.Layout.RotPortSpec import GraphRewriting.Layout.Force import Control.Monad import Data.Vector.Class springForce ∷ (View [Port] n, View Position n, View Rotation n, PortSpec n) ⇒ Double → Node → WithGraph n Force springForce :: forall n. (View [Port] n, View Position n, View Rotation n, PortSpec n) => Double -> Node -> WithGraph n Force springForce Double springLength Node n = ([Force] -> Force) -> ReaderT (Graph n) Identity [Force] -> ReaderT (Graph n) Identity Force forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r liftM [Force] -> Force fsum (ReaderT (Graph n) Identity [Force] -> ReaderT (Graph n) Identity Force) -> ReaderT (Graph n) Identity [Force] -> ReaderT (Graph n) Identity Force forall a b. (a -> b) -> a -> b $ (Port -> ReaderT (Graph n) Identity Force) -> [Port] -> ReaderT (Graph n) Identity [Force] forall (t :: * -> *) (m :: * -> *) a b. (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b] mapM Port -> ReaderT (Graph n) Identity Force forall {m :: * -> *} {a1}. (MonadFail m, PortSpec a1, View [Port] a1, View Position a1, View Rotation a1, MonadReader (Graph a1) m) => Port -> m Force edgeForce ([Port] -> ReaderT (Graph n) Identity [Force]) -> ReaderT (Graph n) Identity [Port] -> ReaderT (Graph n) Identity [Force] forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b =<< Node -> ReaderT (Graph n) Identity [Port] forall n (m :: * -> *). (View [Port] n, MonadReader (Graph n) m, MonadFail m) => Node -> m [Port] attachedEdges Node n where edgeForce :: Port -> m Force edgeForce Port e = do [Node] ns ← Node -> Port -> m [Node] forall n (m :: * -> *). (MonadReader (Graph n) m, MonadFail m) => Node -> Port -> m [Node] adverseNodes Node n Port e [Vector2] nTs ← Port -> Node -> m [Vector2] forall {m :: * -> *} {a1}. (PortSpec a1, View [Port] a1, View Position a1, View Rotation a1, MonadReader (Graph a1) m, MonadFail m) => Port -> Node -> m [Vector2] springTargets Port e Node n [Vector2] nsTs ← ([[Vector2]] -> [Vector2]) -> m [[Vector2]] -> m [Vector2] forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r liftM [[Vector2]] -> [Vector2] forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat (m [[Vector2]] -> m [Vector2]) -> m [[Vector2]] -> m [Vector2] forall a b. (a -> b) -> a -> b $ (Node -> m [Vector2]) -> [Node] -> m [[Vector2]] forall (t :: * -> *) (m :: * -> *) a b. (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b] mapM (Port -> Node -> m [Vector2] forall {m :: * -> *} {a1}. (PortSpec a1, View [Port] a1, View Position a1, View Rotation a1, MonadReader (Graph a1) m, MonadFail m) => Port -> Node -> m [Vector2] springTargets Port e) [Node] ns Force -> m Force forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return (Force -> m Force) -> Force -> m Force forall a b. (a -> b) -> a -> b $ [Force] -> Force fsum [Vector2 -> Vector2 -> Force attraction Vector2 nsT Vector2 nT | Vector2 nsT ← [Vector2] nsTs, Vector2 nT ← [Vector2] nTs] springTargets :: Port -> Node -> m [Vector2] springTargets Port e Node node = do [(Vector2, Vector2)] ps ← (a1 -> [(Vector2, Vector2)]) -> m a1 -> m [(Vector2, Vector2)] forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r liftM ((a1 -> [(Vector2, Vector2)]) -> Port -> a1 -> [(Vector2, Vector2)] forall n a. View [Port] n => (n -> [a]) -> Port -> n -> [a] propOfPort a1 -> [(Vector2, Vector2)] forall n. (PortSpec n, View Position n, View Rotation n) => n -> [(Vector2, Vector2)] absRotPortSpec Port e) (Node -> m a1 forall n (m :: * -> *). (MonadReader (Graph n) m, MonadFail m) => Node -> m n readNode Node node) [Vector2] -> m [Vector2] forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return ([Vector2] -> m [Vector2]) -> [Vector2] -> m [Vector2] forall a b. (a -> b) -> a -> b $ ((Vector2, Vector2) -> Vector2) -> [(Vector2, Vector2)] -> [Vector2] forall a b. (a -> b) -> [a] -> [b] map (\(Vector2 p,Vector2 dir) → Vector2 p Vector2 -> Vector2 -> Vector2 forall a. Num a => a -> a -> a + Vector2 -> Vector2 forall v. Vector v => v -> v vnormalise Vector2 dir Vector2 -> Double -> Vector2 forall v. Vector v => v -> Double -> v |* Double springLength) [(Vector2, Vector2)] ps