diff --git a/Data/CG/Minus.hs b/Data/CG/Minus.hs
--- a/Data/CG/Minus.hs
+++ b/Data/CG/Minus.hs
@@ -261,6 +261,9 @@
         c = cos a
     in Pt (x * c - y * s) (y * c + x * s)
 
+pt_rotate_about :: Floating a => a -> Pt a -> Pt a -> Pt a
+pt_rotate_about r p0 p1 = pt_rotate r (p1 - p0) + p0
+
 -- * Vc functions
 
 -- | Unary operator at 'Vc', ie. basis for 'Num' instances.
@@ -578,11 +581,11 @@
 -- * Ln sets
 
 -- | 'pt_minmax' for set of 'Ln'.
-lns_minmax :: [Ln R] -> (Pt R,Pt R)
+lns_minmax :: Ord n => [Ln n] -> (Pt n,Pt n)
 lns_minmax = ls_minmax . concatMap (\(Ln l r) -> [l,r])
 
 -- | Normalise to (0,m).
-lns_normalise :: R -> [Ln R] -> [Ln R]
+lns_normalise :: (Fractional n,Ord n) => n -> [Ln n] -> [Ln n]
 lns_normalise m l =
     let w = wn_from_extent (lns_minmax l)
     in map (ln_scale m . ln_normalise_w w) l
@@ -671,6 +674,21 @@
 ls_xy :: Ls a -> [a]
 ls_xy = concatMap (\(Pt x y) -> [x,y])
 
+-- | 'Ls' average.
+ls_centroid :: Fractional t => Ls t -> Pt t
+ls_centroid l =
+    let (x,y) = unzip (map pt_xy l)
+        length' = fromIntegral . length
+    in Pt (sum x / length' x) (sum y / length' y)
+
+-- | 'map' of 'pt_rotate_about'.
+ls_rotate_about :: Floating t => t -> Pt t -> Ls t -> Ls t
+ls_rotate_about r c = map (pt_rotate_about r c)
+
+-- | 'ls_rotate_about' of 'ls_centroid'.
+ls_rotate_about_centroid :: Floating t => t -> Ls t -> Ls t
+ls_rotate_about_centroid r l = ls_rotate_about r (ls_centroid l) l
+
 -- * Window
 
 -- | Variant 'Wn' constructor.
@@ -691,6 +709,10 @@
     let fs = printf "((%%.%df,%%.%df),(%%.%df,%%.%df))" n n n n
     in printf fs x0 y0 dx dy
 
+-- | Unit window at origin.
+wn_unit :: Num n => Wn n
+wn_unit = Wn pt_origin (Vc 1 1)
+
 -- | Is 'Pt' within 'Wn' exclusive of edge.
 --
 -- > map (pt_in_window (wn' (0,0) (1,1))) [Pt 0.5 0.5,Pt 1 1] == [True,False]
@@ -746,20 +768,31 @@
     in filter (not . null) . g
 
 -- | Normalisation function for 'Wn', ie. map 'Pt' to lie within (0,1).
-wn_normalise_f :: Wn R -> Pt R -> Pt R
+wn_normalise_f :: (Ord n,Fractional n) => Wn n -> Pt n -> Pt n
 wn_normalise_f (Wn (Pt x0 y0) (Vc dx dy)) (Pt x y) =
     let z = max dx dy
     in Pt ((x - x0) / z) ((y - y0) / z)
 
 -- | Given 'Wn' normalise the 'Ls'.
-ls_normalise_w :: Wn R -> Ls R -> Ls R
+ls_normalise_w :: (Ord n,Fractional n) => Wn n -> Ls n -> Ls n
 ls_normalise_w w = map (wn_normalise_f w)
 
 -- | Given 'Wn' normalise 'Ln'.
-ln_normalise_w :: Wn R -> Ln R -> Ln R
+ln_normalise_w :: (Ord n,Fractional n) => Wn n -> Ln n -> Ln n
 ln_normalise_w w (Ln p q) =
     let f = wn_normalise_f w
     in Ln (f p) (f q)
+
+-- | Variant of 'ls_normalise_w', the window is determined by the
+-- extent of the 'Ls'.
+ls_normalise :: (Ord n,Fractional n) => Ls n -> Ls n
+ls_normalise l = ls_normalise_w (wn_from_extent (ls_minmax l)) l
+
+-- | Normalise a set of line segments using composite window.
+ls_normalise_set :: (Ord n,Fractional n) => [Ls n] -> [Ls n]
+ls_normalise_set l =
+    let w = wn_from_extent (ls_minmax (concat l))
+    in map (ls_normalise_w w) l
 
 -- | Shift lower left 'Pt' of 'Wn' by indicated 'Pt'.
 pt_shift_w :: Num a => Pt a -> Wn a -> Wn a
diff --git a/README b/README
--- a/README
+++ b/README
@@ -5,7 +5,7 @@
 
 [hs]: http://haskell.org/
 
-© [rohan drape][rd], 2009-2013, [gpl]
+© [rohan drape][rd], 2009-2014, [gpl]
 
 [rd]: http://rd.slavepianos.org/
 [gpl]: http://gnu.org/copyleft/
diff --git a/hcg-minus.cabal b/hcg-minus.cabal
--- a/hcg-minus.cabal
+++ b/hcg-minus.cabal
@@ -1,22 +1,23 @@
 name:              hcg-minus
-version:           0.14
+version:           0.15
 synopsis:          haskell cg (minus)
 description:       cg (minus) library
 license:           BSD3
 category:          Math
-copyright:         (c) rohan drape, 2011-2013
+copyright:         (c) rohan drape, 2011-2014
 author:            Rohan Drape
 maintainer:        rd@slavepianos.org
 stability:         Experimental
-homepage:          http://rd.slavepianos.org/?t=hcg-minus
-tested-with:       GHC==7.6.1
+homepage:          http://rd.slavepianos.org/t/hcg-minus
+tested-with:       GHC == 7.8.2
 build-type:        Simple
 cabal-version:     >= 1.8
 
 data-files:        README
 
 library
-  build-depends:   base==4.*,colour
+  build-depends:   base == 4.*,
+                   colour
   ghc-options:     -Wall -fwarn-tabs
   exposed-modules: Data.CG.Minus
                    Data.CG.Minus.Arrow
