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 springLength n = liftM fsum $ mapM edgeForce =<< attachedEdges n where edgeForce e = do ns ← adverseNodes n e nTs ← springTargets e n nsTs ← liftM concat $ mapM (springTargets e) ns return $ fsum [attraction nsT nT | nsT ← nsTs, nT ← nTs] springTargets e node = do ps ← liftM (propOfPort absRotPortSpec e) (readNode node) return $ map (\(p,dir) → p + vnormalise dir |* springLength) ps