```module GraphRewriting.Layout.RotPortSpec
(module GraphRewriting.Layout.RotPortSpec,
module GraphRewriting.Layout.Position,
module GraphRewriting.Layout.Rotation,
module GraphRewriting.Layout.PortSpec,
module GraphRewriting.Layout.Geometry,
module Data.Vector.V2,
module Data.View)
where

import GraphRewriting.Graph
import GraphRewriting.Layout.Position
import GraphRewriting.Layout.Rotation
import GraphRewriting.Layout.PortSpec
import GraphRewriting.Layout.Geometry
import Data.Vector.V2
import Data.View

rotPortSpec ∷ (PortSpec n, View Rotation n) ⇒ n → [(Vector2, Vector2)]
rotPortSpec n = map (\(v, u) → (rot v, rot u)) (portSpec n)
where rot = rotate (examine rotation n)

relRotPortPos ∷ (PortSpec n, View Rotation n) ⇒ n → [Vector2]
relRotPortPos = map fst . rotPortSpec

absRotPortSpec ∷ (PortSpec n, View Position n, View Rotation n) ⇒ n → [(Vector2, Vector2)]
absRotPortSpec n = map (\(p,d) → (examine position n + p, d)) \$ rotPortSpec n

absRotPortPos ∷ (PortSpec n, View Position n, View Rotation n) ⇒ n → [Vector2]
absRotPortPos = map fst . absRotPortSpec

angularMomentum ∷ (View Position n, PortSpec n, View Rotation n, View [Port] n) ⇒ Node → WithGraph n Momentum
angularMomentum n = do
nv ← readNode n
let npos = examine position nv
let edgePortions e = do
let nps = propOfPort portDir e nv
ns ← mapM readNode =<< adverseNodes n e
let nsps = concatMap (propOfPort absRotPortPos e) ns
let angles = [angle np (nsp - npos) | np ← nps, nsp ← nsps]
return \$ map (approach . Rotation) angles
liftM (momSum . concat) (mapM edgePortions =<< attachedEdges n)
```