packages feed

PenroseKiteDart-1.0.0: src/TgraphExamples.hs

{-|
Module      : TgraphExamples
Description : Examples of tilings represented with Tgraphs and their diagrams 
Copyright   : (c) Chris Reade, 2021
License     : BSD-style
Maintainer  : chrisreade@mac.com
Stability   : experimental

-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE TypeFamilies              #-}
{-# LANGUAGE TupleSections             #-}

module TgraphExamples
  (-- * Some Layout tools
    padBorder
  , chunks
  , arrangeRowsGap
  , arrangeRows
  , labelAt
    -- *  Tgraphs for 7 vertex types
  , sunGraph 
  , jackGraph
  , kingGraph
  , queenGraph
  , aceGraph
  , deuceGraph
  , starGraph
    -- *  Further Basic Tgraphs
  , kiteGraph
  , dartGraph
  , fool
  , foolD
  , foolDminus
  , foolDs
  , sunDs
  , kiteDs
  , dartDs
  , dartD4  
  , sun3Dart 
    -- *  Some Simple Figures
  , foolFig
  , foolAndFoolD
  , figSunD3D2
    -- *  Figures for 7 vertex types
  , vertexTypesFig
  , forceVFigures
    -- * Partial Composition figures
  , pCompFig1
  , pCompFig2
  , pCompFig
    -- * Forced Tgraph figures
  , forceFoolDminus
  , forceDartD5Fig
  , forceKiteD5Fig
  , forceSunD5Fig
  , forceFig
    -- *  Removed faces (forcing and composing)
  , brokenDart
  , badlyBrokenDart
  , brokenDartFig
  , badlyBrokenDartFig
  , removeIncompletesFig
    -- *  Incorrect Tgraphs
  , mistake
  , mistake1
    -- * superForce Figure
  , superForceFig
  , superForceRocketsFig
    -- *  Tgraphs with Boundary faces
  , boundaryFDart4
  , boundaryFDart5
  , boundaryFDart4Fig
  , boundaryFDart5Fig
  , boundaryGapFDart4
  , boundaryGapFDart5
  , boundaryGap4Fig
  , boundaryGap5Fig
    -- *  Boundary coverings and empires
 , boundaryVCoveringFigs
 , boundaryECoveringFigs
 , kingECoveringFig
 , kingVCoveringFig 
 , kingEmpiresFig
 , kingEmpire1Fig
 , kingEmpire2Fig
 
  ) where

import Diagrams.Prelude
import Diagrams.TwoD.Text (Text)
-- import ChosenBackend (B)
import TileLib
import Tgraphs



-- |used for most diagrams to give border padding
-- 
--  When a specific Backend B is in scope, padBorder:: Diagram B -> Diagram B
padBorder :: Diagram2D b -> Diagram2D b
padBorder = pad 1.2 . centerXY

-- |chunks n l -  split a list l into chunks of length n (n>0)
chunks::Int -> [a] -> [[a]]
chunks n
  | n < 1 = error "chunks: argument <1\n"
  | otherwise = ch where
      ch [] = []
      ch as = take n as : ch (drop n as)

-- |arrangeRowsGap s n diags - arranges diags into n per row, centering each row horizontally,
-- with a seperation gap (horizontally and vertically) of s.
-- The result is a single diagram.
-- 
--  When a specific Backend B is in scope, arrangeRowsGap :: Double -> Int -> [Diagram B] -> Diagram B
arrangeRowsGap :: Double -> Int -> [Diagram2D b] -> Diagram2D b
arrangeRowsGap s n = centerY . vsep s . fmap (centerX . hsep s) . chunks n

-- |arrangeRows n diags - arranges diags into n per row, centering each row horizontally.
-- The result is a single diagram (seperation is 1 unit vertically and horizontally).
-- 
--  When a specific Backend B is in scope, arrangeRows :: Int -> [Diagram B] -> Diagram B
arrangeRows :: Int -> [Diagram2D b] -> Diagram2D b
arrangeRows = arrangeRowsGap 1.0

-- |add a given label at a given point offset from the centre of the given diagram.
-- 
-- When a specific Backend B is in scope, labelAt :: Point V2 Double -> String -> Diagram B -> Diagram B
labelAt :: Renderable (Text Double) b => 
           Point V2 Double -> String -> Diagram2D b -> Diagram2D b
labelAt p l d = baselineText l # fontSize (output 15) # moveTo p <> d
--labelAt p l d = baselineText l # fontSize (normalized 0.02) # moveTo p <> d


fool, foolD, foolDminus:: Tgraph
-- |fool: fool's kite - also called an ace.
fool = makeTgraph [RK (5,2,7),LK (5,6,4),RK (5,4,3),LK (5,3,2),RD (1,2,3),LD (1,3,4)]
-- fool = makeTgraph [ RD (1,2,3), LD (1,3,4), RK (6,2,5), LK (6,3,2), RK (6,4,3), LK (6,7,4)]

-- |a once decomposed fool (= foolDs!!1)
foolD = decompose fool

-- |foolDminus: 3 faces removed from foolD - still a valid Tgraph
foolDminus = removeFaces [RD (5,15,13), LD (5,16,15), RK (7,11,2)] foolD
-- foolDminus = removeFaces [RD (6,15,13), LD (6,17,15), RK (5,11,2)] foolD

-- | an infinite list of decompositions of fool
foolDs :: [Tgraph]
foolDs = decompositions fool

-- | diagram of just fool.
--
-- When a specific Backend B is in scope, foolFig :: Diagram B
foolFig :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
foolFig = padBorder $ labelSize normal drawj fool

-- |diagram of fool with foolD.
-- 
-- When a specific Backend B is in scope, foolAndFoolD :: Diagram B
foolAndFoolD :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
foolAndFoolD = padBorder $ hsep 1 [scale phi $ labelled drawj fool, labelled drawj foolD]

-- |Tgraph for a sun (sun vertex type)
sunGraph :: Tgraph
sunGraph = makeTgraph
             [ RK (1,2,11), LK (1,3,2)
             , RK (1,4,3) , LK (1,5,4)
             , RK (1,6,5) , LK (1,7,6)
             , RK (1,8,7) , LK (1,9,8)
             , RK (1,10,9), LK (1,11,10)
             ]
-- | an infinite list of decompositions of sunGraph
sunDs :: [Tgraph]
sunDs =  decompositions sunGraph

-- |Figure for a 3 times decomposed sun with a 2 times decomposed sun.
-- 
-- When a specific Backend B is in scope, figSunD3D2 :: Diagram B
figSunD3D2 :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
figSunD3D2 = padBorder $ hsep 1 [labelled drawj $ sunDs !! 3, scale phi $ labelled drawj $ sunDs !! 2]

-- |Tgraph for kite
kiteGraph :: Tgraph
kiteGraph = makeTgraph [ RK (1,2,4), LK (1,3,2)]

-- | an infinite list of decompositions of a kite
kiteDs :: [Tgraph]
kiteDs = decompositions kiteGraph

-- |Tgraph for a dart
dartGraph :: Tgraph
dartGraph =  makeTgraph [ RD (1,2,3), LD (1,3,4)]

-- | an infinite list of decompositions of a dart
dartDs :: [Tgraph]
dartDs =  decompositions dartGraph

-- |Tgraph of 4 times decomposed dartGraph (used in several examples)
dartD4 :: Tgraph
dartD4 = dartDs!!4




pCompFig1,pCompFig2,pCompFig :: Renderable (Path V2 Double) b => Diagram2D b
-- |diagram showing partial composition of a forced 3 times decomposed dart (with remainder faces in pale green).
-- 
-- When a specific Backend B is in scope, pCompFig1 :: Diagram B
pCompFig1 = lw veryThin $ hsep 5 $ rotations [1,1] [draw fd3, drawPCompose fd3]
            where fd3 = force $ dartDs!!3
-- |diagram showing partial composition of a forced 3 times decomposed kite (with remainder faces in pale green).
-- 
-- When a specific Backend B is in scope, pCompFig2 :: Diagram B
pCompFig2 = lw veryThin $ hsep 5 [draw fk3, drawPCompose fk3]
            where fk3 = force $ kiteDs!!3
-- |diagram showing two partial compositions (with remainder faces in pale green).
-- 
-- When a specific Backend B is in scope, pCompFig :: Diagram B
pCompFig = padBorder $ vsep 3 [center pCompFig1, center pCompFig2]


-- |diagram of foolDminus and the result of forcing.  
-- 
-- When a specific Backend B is in scope, forceFoolDminus :: Diagram B
forceFoolDminus :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
forceFoolDminus = padBorder $ hsep 1 $ fmap (labelled drawj) [foolDminus, force foolDminus]


forceDartD5Fig,forceKiteD5Fig,forceSunD5Fig,forceFig :: Renderable (Path V2 Double) b => Diagram2D b
-- |diagram of forced 5 times decomposed dart.
-- 
-- When a specific Backend B is in scope, forceDartD5Fig :: Diagram B
forceDartD5Fig = padBorder $ lw ultraThin $ drawForce $ dartDs !! 5
-- |diagram of forced 5 times decomposed kite.
-- 
-- When a specific Backend B is in scope, forceKiteD5Fig :: Diagram B
forceKiteD5Fig = padBorder $ lw ultraThin $ rotate (ttangle 1) $ drawForce $ kiteDs!!5
-- |diagram of forced 5 times decomposed sun.
-- 
-- When a specific Backend B is in scope, forceSunD5Fig :: Diagram B
forceSunD5Fig =  padBorder $ lw ultraThin $ drawForce $ sunDs !! 5
-- |diagram of forced 5 times decomposed dart (left) and kite (right).
-- 
-- When a specific Backend B is in scope, forceFig :: Diagram B
forceFig = hsep 1 [forceDartD5Fig,forceKiteD5Fig]

-- |brokenDart is a 4 times decomposed dart (dartD4) with 5 halftile faces removed.
-- Forcing will repair to produce the same Tgraph as force dartD4.
-- This graph can also be repeatedly composed (without forcing) to get a maximal Tgraph.
brokenDart :: Tgraph
brokenDart = removeFaces deleted dartD4 where
  deleted = [RK (2,16,33),LD (15,33,16),RK (16,66,15),LK (16,67,66),LK (5,15,66)]

{-| badlyBrokenDart has more faces removed from brokenDart.
This will also get repaired by forcing (to produce the same as force dartD4).
However it will fail to produce a valid Tgraph if composed twice without forcing. 
-}
badlyBrokenDart :: Tgraph
badlyBrokenDart = removeFaces deleted bbd where
  deleted = [RK (6,28,54)]
  bbd = removeVertices [63,37] brokenDart
--  deleted = RK(6,28,54):filter (isAtV 63) (faces brokenDart)

-- |brokenDartFig shows the faces removed from dartD4 to make brokenDart and badlyBrokenDart.
-- 
-- When a specific Backend B is in scope, brokenDartFig :: Diagram B
brokenDartFig  :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
brokenDartFig = padBorder $ lw thin $ hsep 1 $ fmap (labelled drawj) [dartD4, brokenDart, badlyBrokenDart]

-- |badlyBrokenDartFig shows badlyBrokenDart, followed by its composition, followed by the faces 
-- that would result from an unchecked second composition which are not tile-connected.
-- (Simply applying compose twice to badlyBrokenDart will raise an error).
-- 
-- When a specific Backend B is in scope, badlyBrokenDartFig :: Diagram B
badlyBrokenDartFig :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
badlyBrokenDartFig = padBorder $ lw thin $ hsep 1 $ fmap (labelled drawj) [vp, vpComp, vpFailed] where
    vp = makeVP badlyBrokenDart
    comp = compose badlyBrokenDart
    vpComp = restrictVP vp $ faces $ comp
    vpFailed  = restrictVP vp $ composedFaces comp

-- |figure showing the result of removing incomplete tiles (those that do not have their matching halftile)
-- to a 3 times decomposed sun.
-- 
-- When a specific Backend B is in scope, removeIncompletesFig :: Diagram B
removeIncompletesFig :: Renderable (Path V2 Double) b => Diagram2D b
removeIncompletesFig = padBorder $ drawj $ removeFaces (boundaryJoinFaces g) g where 
    g = sunDs !! 3


-- |mistake is a legal but incorrect Tgraph - a kite with 2 darts on its long edges
mistake:: Tgraph
mistake = makeTgraph [RK (1,2,4), LK (1,3,2), RD (3,1,5), LD (4,6,1), LD (3,5,7), RD (4,8,6)]

-- |mistake1 is a kite bordered by 2 half darts (subgraph of mistake and still incorrect)
mistake1:: Tgraph
mistake1 = makeTgraph [RK (1,2,4), LK (1,3,2), RD (3,1,5), LD (4,6,1)]

-- *  Figures for 7 vertex types

-- | vertexTypesFig is 7 vertex types in a single diagram as a row.
-- 
-- When a specific Backend B is in scope, vertexTypesFig :: Diagram B
vertexTypesFig :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
vertexTypesFig = padBorder $ hsep 1 lTypeFigs
 where
 lTypeFigs = zipWith (labelAt (p2 (0,-2.2))) ["sun","star","jack","queen","king","ace","deuce"] vTypeFigs
 vTypeFigs = zipWith drawVertex
               [sunGraph, starGraph, jackGraph, queenGraph, kingGraph, aceGraph,  deuceGraph]
               [(1,2),    (1,2),     (1,2),     (1,2),      (1,2),     (3,6),     (2,6)] -- alignments
 drawVertex g alm = alignBefore (lw thin . showOrigin . drawj) alm g

jackGraph,kingGraph,queenGraph,aceGraph,deuceGraph,starGraph::Tgraph
-- |Tgraph for vertex type jack.
jackGraph = makeTgraph
  [LK (1,9,11),RK (1,11,2),LK (7,8,1),RD (9,1,8),RK (1,3,4)
  ,LK (1,2,3),RK (7,1,5),LD (4,5,1),LD (9,8,10),RD (4,6,5)
  ] -- centre 1
-- |Tgraph for vertex type king.
kingGraph = makeTgraph
  [LD (1,2,3),RD (1,11,2),LD (1,4,5),RD (1,3,4),LD (1,10,11)
  ,RD (1,9,10),LK (9,1,7),RK (9,7,8),RK (5,7,1),LK (5,6,7)
  ] -- centre 1
-- |Tgraph for vertex type queen.
queenGraph = makeTgraph
  [LK (7,1,5),RK (3,5,1),LD (1,2,3),RK (7,9,1),LK (11,1,9)
  ,RD (1,11,2),RK (7,5,6),LK (7,8,9),LK (3,4,5),RK (11,9,10)
  ] -- centre 1
-- |Tgraph for vertex type ace (same as fool).
aceGraph = fool -- centre 3
-- |Tgraph for vertextype deuce.
deuceGraph = makeTgraph
  [LK (7,8,2),RK (7,2,6),RK (5,2,4),LK (5,6,2),LD (1,4,2)
  ,RD (1,2,8),RD (1,3,4),LD (1,8,9)
  ] -- centre 2
-- |Tgraph for vertex type star.
starGraph = makeTgraph
  [LD (1,2,3),RD (1,11,2),LD (1,10,11),RD (1,9,10),LD (1,8,9)
  ,RD (1,7,8),LD (1,6,7),RD (1,5,6),LD (1,4,5),RD (1,3,4)
  ] -- centre 1

-- |forceVFigures is a list of 7 diagrams - force of 7 vertex types.
--
-- When a specific Backend B is in scope, forceVFigures :: [Diagram B]
forceVFigures :: Renderable (Path V2 Double) b => [Diagram2D b]
forceVFigures = rotations [0,0,9,5,0,0,1] $
                fmap (center . drawForce) [sunGraph,starGraph,jackGraph,queenGraph,kingGraph,aceGraph,deuceGraph]


sun3Dart :: Tgraph
-- |A sun with 3 darts on the boundary NOT all adjacent
-- (Used in superForceRocketsFig).
sun3Dart = addHalfDart (9,10) $ addHalfDart (8,9) $ addHalfDart (5,6) $ addHalfDart (4,5) $ addHalfDart (3,4) $ addHalfDart (2,3) sunGraph
-- sun3Dart = addHalfDart (9,10) $ addHalfDart (8,9) sun2AdjDart


-- |Diagram showing superForce with initial Tgraph g (red), force g (red and black),
-- and superForce g (red and black and blue).
-- 
-- When a specific Backend B is in scope, superForceFig :: Diagram B
superForceFig :: Renderable (Path V2 Double) b => Diagram2D b
superForceFig = padBorder $ lw thin $ rotate (ttangle 1) $ drawSuperForce g where
    g = addHalfDart (220,221) $ force $ decompositions fool !!3

-- |Diagram showing 4 rockets formed by applying superForce to successive decompositions
-- of sun3Dart. The decompositions are in red with normal force additions in black and superforce additions in blue.
-- 
-- When a specific Backend B is in scope, superForceRocketsFig :: Diagram B
superForceRocketsFig :: Renderable (Path V2 Double) b => Diagram2D b
superForceRocketsFig = padBorder $ lw veryThin $ vsep 1 $ rotations [8,9,9,8] $
   fmap drawSuperForce decomps where
      decomps = take 4 $ decompositions sun3Dart


boundaryFDart4, boundaryFDart5 :: Tgraph
-- |graph of the boundary faces only of a forced graph (dartDs!!4)
boundaryFDart4 = checkedTgraph $ boundaryFaces $ force $ makeBoundaryState dartD4
-- |graph of the boundary faces only of a forced graph (dartDs!!5)
boundaryFDart5 = checkedTgraph $ boundaryFaces $ force $ makeBoundaryState (dartDs!!5)

boundaryFDart4Fig,boundaryFDart5Fig :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
-- |figure of the boundary faces only of a forced graph (dartDs!!4).
-- 
-- When a specific Backend B is in scope, boundaryFDart4Fig :: Diagram B
boundaryFDart4Fig = padBorder $ lw ultraThin $ labelSize tiny drawj boundaryFDart4
-- |figure of the boundary faces only of a forced graph (dartDs!!5).
-- 
-- When a specific Backend B is in scope, boundaryFDart5Fig :: Diagram B
boundaryFDart5Fig = padBorder $ lw ultraThin $ labelSize (normalized 0.006) drawj boundaryFDart5

boundaryGapFDart4, boundaryGapFDart5 :: Tgraph
-- |graph of the boundary faces only of a forced graph - with extra faces removed to make a gap
boundaryGapFDart4 = removeVertices [354] boundaryFDart4
    -- checkedTgraph $ filter ((/=354).originV)  (faces boundaryFDart4)
-- |graph of the boundary faces only of a forced graph - with extra faces removed to make a gap
boundaryGapFDart5 = removeVertices [1467] boundaryFDart5
    -- checkedTgraph $ filter ((/=1467).originV) (faces boundaryFDart5)

boundaryGap4Fig, boundaryGap5Fig  :: (Renderable (Path V2 Double) b, Renderable (Text Double) b) => Diagram2D b
-- |figure for the boundary gap graph boundaryGapFDart4.
-- 
-- When a specific Backend B is in scope, boundaryGap4Fig :: Diagram B
boundaryGap4Fig = padBorder $ lw ultraThin $ labelSize tiny drawj boundaryGapFDart4
-- |figure for the boundary gap graph boundaryGapFDart5.
-- 
-- When a specific Backend B is in scope, boundaryGap5Fig :: Diagram B
boundaryGap5Fig = padBorder $ lw ultraThin $ labelSize (normalized 0.006) drawj boundaryGapFDart5


-- | boundaryVCoveringFigs bd - produces a list of diagrams for the boundaryVCovering of bd 
-- (with the Tgraph represented by bd shown in red in each case).
-- 
-- When a specific Backend B is in scope, boundaryVCoveringFigs :: BoundaryState -> [Diagram B]
boundaryVCoveringFigs :: Renderable (Path V2 Double) b =>
                         BoundaryState -> [Diagram2D b]
boundaryVCoveringFigs bd =
    fmap (lw ultraThin . (redg <>) . alignBefore draw alig . recoverGraph) $ boundaryVCovering bd
      where redg = lc red $ draw g --alignBefore draw alig g
            alig = defaultAlignment g
            g = recoverGraph bd

-- | boundaryECoveringFigs bd - produces a list of diagrams for the boundaryECovering of bd  
-- (with the Tgraph represented by bd shown in red in each case).
-- 
-- When a specific Backend B is in scope, boundaryECoveringFigs :: BoundaryState -> [Diagram B]
boundaryECoveringFigs :: Renderable (Path V2 Double) b =>
                         BoundaryState -> [Diagram2D b]
boundaryECoveringFigs bd =
    fmap (lw ultraThin . (redg <>) . alignBefore draw alig . recoverGraph) $ boundaryECovering bd
      where redg = lc red $ draw g
            alig = defaultAlignment g
            g = recoverGraph bd

kingECoveringFig,kingVCoveringFig :: Renderable (Path V2 Double) b => Diagram2D b
-- | diagram showing the boundaryECovering of a forced kingGraph.
-- 
-- When a specific Backend B is in scope, kingECoveringFig :: Diagram B
kingECoveringFig = padBorder $ arrangeRows 3 $ boundaryECoveringFigs $ force $ makeBoundaryState kingGraph
-- | diagram showing the boundaryVCovering of a forced kingGraph.
-- 
-- When a specific Backend B is in scope, kingVCoveringFig :: Diagram B
kingVCoveringFig = padBorder $ arrangeRows 3 $ boundaryVCoveringFigs $ force  $ makeBoundaryState kingGraph

kingEmpiresFig, kingEmpire1Fig, kingEmpire2Fig :: Renderable (Path V2 Double) b => Diagram2D b
-- | figure showing King's empires (1 and 2).
-- 
-- When a specific Backend B is in scope, kingEmpiresFig :: Diagram B
kingEmpiresFig = padBorder $ hsep 10 [kingEmpire1Fig, kingEmpire2Fig]
-- | figure showing King's empires 1.
-- 
-- When a specific Backend B is in scope, kingEmpire1Fig :: Diagram B
kingEmpire1Fig = showEmpire1 kingGraph
-- | figure showing King's empire 2.
-- 
-- When a specific Backend B is in scope, kingEmpire2Fig :: Diagram B
kingEmpire2Fig = showEmpire2 kingGraph