-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Simple force-directed layout -- -- Simulation engine for doing simple force-based layout, e.g. for -- trees or graphs. See the diagrams-contrib package for usage examples. @package force-layout @version 0.4.0.4 -- | A simple, Haskell-native simulator for doing force-directed layout, -- e.g. of trees or graphs. -- -- To use, just create an Ensemble like so: -- --
--   import           Control.Lens        ((&), (.~))
--   import           Data.Default.Class  (def)
--   import qualified Data.Map            as M
--   import           Linear.Affine
--   import           Linear.V2
--   import           Physics.ForceLayout
--   
--   e :: Ensemble V2 Double
--   e = Ensemble [ (edges,    hookeForce 0.05 4)
--                , (allPairs, coulombForce 1)
--                ]
--                particleMap
--     where edges       = [(1,2), (2,3), (2,5), (3,5), (3,4), (4,5)]
--           allPairs    = [(x,y) | x <- [1..4], y <- [x+1..5]]
--           particleMap = M.fromList . zip [1..]
--                       . map (initParticle . P . uncurry V2)
--                       $ [ (2.0, 3.1), (6.3, 7.2)
--                         , (0.3, 4.2), (1.6, -1.1)
--                         , (4.8, 2.9)
--                         ]
--   
-- -- Then run a simulation using either simulate (to get the list of -- all intermediate states) or forceLayout (to get only the ending -- state): -- --
--   e' :: Ensemble V2 Double
--   e' = forceLayout (def & damping     .~ 0.8
--                         & energyLimit .~ Just 0.001
--                         & stepLimit   .~ Nothing
--                    )
--                    e
--   
-- -- See the diagrams-contrib package -- (http://github.com/diagrams/diagrams-contrib/) for more -- examples. module Physics.ForceLayout -- | A particle has a current position, current velocity, and current force -- acting on it. data Particle v n Particle :: Point v n -> v n -> v n -> Particle v n [_pos] :: Particle v n -> Point v n [_vel] :: Particle v n -> v n [_force] :: Particle v n -> v n pos :: forall v_aiuX n_aiuY. Lens' (Particle v_aiuX n_aiuY) (Point v_aiuX n_aiuY) vel :: forall v_aiuX n_aiuY. Lens' (Particle v_aiuX n_aiuY) (v_aiuX n_aiuY) force :: forall v_aiuX n_aiuY. Lens' (Particle v_aiuX n_aiuY) (v_aiuX n_aiuY) -- | Create an initial particle at rest at a particular location. initParticle :: (Additive v, Num n) => Point v n -> Particle v n -- | Used to uniquely identify particles. type PID = Int -- | An edge is a pair of particle identifiers. type Edge = (PID, PID) -- | An Ensemble is a physical configuration of particles. It -- consists of a mapping from particle IDs (unique integers) to -- particles, and a list of forces that are operative. Each force has a -- list of edges to which it applies, and is represented by a function -- giving the force between any two points. data Ensemble v n Ensemble :: [([Edge], Point v n -> Point v n -> v n)] -> Map PID (Particle v n) -> Ensemble v n [_forces] :: Ensemble v n -> [([Edge], Point v n -> Point v n -> v n)] [_particles] :: Ensemble v n -> Map PID (Particle v n) forces :: forall v_akgf n_akgg. Lens' (Ensemble v_akgf n_akgg) [([Edge], Point v_akgf n_akgg -> Point v_akgf n_akgg -> v_akgf n_akgg)] particles :: forall v_akgf n_akgg. Lens' (Ensemble v_akgf n_akgg) (Map PID (Particle v_akgf n_akgg)) -- | hookeForce k l p1 p2 computes the force on p1, -- assuming that p1 and p2 are connected by a spring -- with equilibrium length l and spring constant k. hookeForce :: (Metric v, Floating n) => n -> n -> Point v n -> Point v n -> v n -- | coulombForce k computes the electrostatic repulsive force -- between two charged particles, with constant of proportionality -- k. coulombForce :: (Metric v, Floating n) => n -> Point v n -> Point v n -> v n -- | distForce f p1 p2 computes the force between two points as a -- multiple of the unit vector in the direction from p1 to -- p2, given a function f which computes the force's -- magnitude as a function of the distance between the points. distForce :: (Metric v, Floating n) => (n -> n) -> Point v n -> Point v n -> v n -- | Options for customizing a simulation. data ForceLayoutOpts n FLOpts :: n -> Maybe n -> Maybe Int -> ForceLayoutOpts n -- | Damping factor to be applied at each step. Should be between 0 and 1. -- The default is 0.8. [_damping] :: ForceLayoutOpts n -> n -- | Kinetic energy below which simulation should stop. If -- Nothing, pay no attention to kinetic energy. The default is -- Just 0.001. [_energyLimit] :: ForceLayoutOpts n -> Maybe n -- | Maximum number of simulation steps. If Nothing, pay no -- attention to the number of steps. The default is Just 1000. [_stepLimit] :: ForceLayoutOpts n -> Maybe Int damping :: forall n_aklI. Lens' (ForceLayoutOpts n_aklI) n_aklI energyLimit :: forall n_aklI. Lens' (ForceLayoutOpts n_aklI) (Maybe n_aklI) stepLimit :: forall n_aklI. Lens' (ForceLayoutOpts n_aklI) (Maybe Int) -- | Simulate a starting ensemble according to the given options, producing -- a list of all the intermediate ensembles. Useful for, e.g., -- making an animation. Note that the resulting list could be infinite, -- if a stepLimit is not specified and either the kinetic energy -- never falls below the specified threshold, or no energy threshold is -- specified. simulate :: (Metric v, Num n, Ord n) => ForceLayoutOpts n -> Ensemble v n -> [Ensemble v n] -- | Run a simluation from a starting ensemble, yielding either the first -- ensemble to have kinetic energy below the energyLimit (if -- given), or the ensemble that results after a number of steps equal to -- the stepLimit (if given), whichever comes first. Otherwise -- forceLayout will not terminate. forceLayout :: (Metric v, Num n, Ord n) => ForceLayoutOpts n -> Ensemble v n -> Ensemble v n -- | Simulate one time step for an entire ensemble, with the given damping -- factor. ensembleStep :: (Additive v, Num n) => n -> Ensemble v n -> Ensemble v n -- | Simulate one time step for a particle (assuming the force acting on it -- has already been computed), with the given damping factor. particleStep :: (Additive v, Num n) => n -> Particle v n -> Particle v n -- | Recalculate all the forces acting in the next time step of an -- ensemble. recalcForces :: (Additive v, Num n) => Ensemble v n -> Ensemble v n -- | Compute the total kinetic energy of an ensemble. kineticEnergy :: (Metric v, Num n) => Ensemble v n -> n instance GHC.Real.Fractional n => Data.Default.Class.Default (Physics.ForceLayout.ForceLayoutOpts n) instance GHC.Classes.Eq (v n) => GHC.Classes.Eq (Physics.ForceLayout.Particle v n)