packages feed

twentefp-rosetree (empty) → 0.1.0.0

raw patch · 4 files changed

+268/−0 lines, 4 filesdep +basedep +twentefp-eventloop-graphicsdep +twentefp-numbersetup-changed

Dependencies added: base, twentefp-eventloop-graphics, twentefp-number

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Sebastiaan la Fleur
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Sebastiaan la Fleur nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple
+main = defaultMain
+ src/RoseTree.hs view
@@ -0,0 +1,216 @@+module RoseTree(RoseTree(..), showTree, showTreeList) where
+
+import FPPrac
+import EventLoop.Output.Single (outSingle)
+import EventLoop.Output
+import EventLoop.CommonTypes
+
+data RoseTree = RoseNode String [RoseTree]
+                deriving (Show, Eq)
+
+marginBetweenTrees = 10 :: Number
+
+showTree :: RoseTree -> IO ()
+showTree t = showTreeList [t]
+
+showTreeList :: [RoseTree] -> IO ()
+showTreeList list = outSingle (OutGraphical (Draw (showTreeList' 0 0 0 0 list) "trees"))
+
+showTreeList' :: Number -> Number -> Number -> Number -> [RoseTree] -> GObject
+showTreeList' _ _ _ _ [] = Container []
+showTreeList' left top maxBottom i (x:xs) | right <= 1024 = Container (text:gtree:gtrees)
+                                          | width > 1024  = Container (text:gtree:gtrees)
+                                          | otherwise     = showTreeList' 0 maxBottom' maxBottom' i (x:xs)
+                                        where
+                                            maxBottom' = max maxBottom bottom
+                                            (ltree, right, bottom) = layoutTree left top x
+                                            gtree = printTree ltree
+                                            Container gtrees = showTreeList' (right + marginBetweenTrees) top maxBottom' i' xs
+                                            i' = i + 1
+                                            text = treeIndex i (left, top)
+                                            width = right - left
+
+treeIndex :: Number -> Pos -> GObject
+treeIndex i pos = GObject "treeIndex" (Text (255, 125, 125) 0 (255,75,75) pos 20 "Courier" (show i) False)  []
+
+
+
+data LayoutTree = LNode LayoutText Pos [LayoutTree] deriving (Show)
+                
+type LayoutText = (Pos, [Char])
+          
+radiusNode = 10 :: Number
+sizeOfText = 16 :: Number
+marginLine = 5 :: Number
+marginBetweenRows = 10 :: Number
+marginBetweenNodes = 20 :: Number
+                   
+testTree = (RoseNode "h" [(RoseNode "a" []), (RoseNode "a" [(RoseNode "a" [(RoseNode "a" []), (RoseNode "a" [])])]), (RoseNode "a" [])])
+ 
+exampleTree = RoseNode "z"
+                        [ RoseNode "aaa"
+                                    [ RoseNode "bbb"
+                                                [ RoseNode "ccc" [],
+                                                  RoseNode "ddd" []
+                                                ],
+                                      RoseNode ""
+                                                [RoseNode "fff" [],
+                                                 RoseNode "ggg" [],
+                                                 RoseNode "hhh" []
+                                                ],
+                                      RoseNode "iii"
+                                                [RoseNode "" []
+                                                ]
+                                    ],
+                          RoseNode "kkk"
+                                    [RoseNode "lll" [],
+                                     RoseNode "mmm"
+                                               [RoseNode "nnn"
+                                                          [RoseNode "q" [],
+                                                           RoseNode "r" []
+                                                          ],
+                                                RoseNode "ooo" [],
+                                                RoseNode "ppp" []
+                                               ]
+                                    ]
+                        ]
+ 
+
+layoutTree :: Number -> Number -> RoseTree -> (LayoutTree, Number, Number)
+layoutTree leftBorder topBorder (RoseNode str []) = (lNode, rightBorder, bottom)
+                                                    where
+                                                        lNode = LNode lText (x, yNode) []
+                                                        lText = layoutText (x, yText) str
+                                                        (widthText, heightText) = textSize str
+                                                        (widthNode, heightNode) = (2 * radiusNode, 2 * radiusNode)
+                                                        totalHeight = heightNode + heightText
+                                                        totalWidth  = max widthNode widthText
+                                                        rightBorder = leftBorder + totalWidth
+                                                        bottom = topBorder' + totalHeight
+                                                        middleLine = (rightBorder - leftBorder) / 2 + leftBorder
+                                                        x = middleLine
+                                                        topBorder' = topBorder + marginBetweenRows
+                                                        yNode = topBorder' + radiusNode
+                                                        yText = topBorder' + heightNode + 0.5 * heightText
+
+layoutTree leftBorder topBorder (RoseNode str children) = ((LNode ((x', yText), str) (x', yNode) lChildren), rightBorder', bottom)
+                                                    where
+                                                        ((LNode ((_, yText), _) (_, yNode) _), _, _) = layoutTree leftBorder topBorder (RoseNode str [])
+                                                        (lChildren, rightBorder, bottom) = layoutChildren leftBorder (topBorder' + totalHeight) children
+                                                        topBorder' = topBorder + marginBetweenRows
+                                                        (widthText, heightText) = textSize str
+                                                        (widthNode, heightNode) = (2 * radiusNode, 2 * radiusNode)
+                                                        totalHeight = heightNode + heightText
+                                                        totalWidth  = max widthNode widthText
+                                                        middleLine = (rightBorder - leftBorder) / 2 + leftBorder
+                                                        x' = middleLine
+                                                        rightBorder' = max rightBorder (leftBorder + totalWidth)
+                                                        
+layoutChildren :: Number -> Number -> [RoseTree] -> ([LayoutTree], Number, Number)
+layoutChildren leftBorder topBorder (n:[]) = ([lTree], rightBorder, bottom)
+                                            where
+                                                (lTree, rightBorder, bottom) = layoutTree leftBorder topBorder n
+                                                
+layoutChildren leftBorder topBorder (n:ns) = ((lTree:ns'), rightestBorder, bottom')
+                                            where
+                                                (lTree, rightBorder, bottom1) = layoutTree leftBorder topBorder n
+                                                (ns', rightestBorder, bottom2) = layoutChildren (rightBorder + marginBetweenNodes) topBorder ns
+                                                bottom' = max bottom1 bottom2
+
+layoutText :: Pos -> [Char] -> LayoutText
+layoutText pos str = (pos, str)
+
+printTree :: LayoutTree -> GObject
+printTree (LNode (strPos, str) nPos children) = Container (gChildren ++ gLines ++ [gNode, gText])
+                                                where
+                                                    gChildren = map printTree children 
+                                                    gNode  = printNode nPos
+                                                    gText  = printText strPos str
+                                                    gLines = printLines nPos children
+
+printLines :: Pos -> [LayoutTree] -> [GObject]
+printLines _ [] = []
+printLines pos ((LNode _ nPos _):ns) = gLine:(printLines pos ns)
+                                    where
+                                        gLine = printLine start end
+                                        start = marginizePosition (marginLine + radiusNode) pos nPos
+                                        end   = marginizePosition (marginLine + radiusNode) nPos pos
+         
+marginizePosition :: Number -> Pos -> Pos -> Pos
+marginizePosition margin (xStart, yStart) (xEnd, yEnd) = (xStart', yStart')
+                            where
+                                xStart'  = xStart + fraction * xSize
+                                yStart'  = yStart + fraction * ySize
+                                fraction = margin / size
+                                size     = sqrt (xSize^2 + ySize^2)
+                                xSize    = xEnd - xStart
+                                ySize    = yEnd - yStart
+
+         
+printLine :: Pos -> Pos -> GObject
+printLine start end = GObject "Line" lineP []
+                    where
+                        lineP = Line (0,0,0) 1 [start, end]
+                                                    
+printNode :: Pos -> GObject
+printNode pos = GObject "Node" nodeOutputP []
+            where
+                nodeOutputP = Arc (0, 0, 0) 0 (0, 0, 0) pos (round radiusNode) 0 360
+                                                    
+printText :: Pos -> [Char] -> GObject
+printText pos str = GObject "Node Text" textOutputP []
+                where
+                    textOutputP = Text (75, 75, 255) 0 (75, 75, 255) pos sizeOfText "Courier" str True                                                   
+                                                    
+-- (width, height)                        
+textSize :: [Char] -> (Number, Number)
+textSize str = (textWidth, sizeOfText)
+             where
+                textWidth = charWidth * (FPPrac.length str)
+
+-- Courier 16px                
+charWidth :: Number
+charWidth = 10      
+                
+{- Calibri height 16px            
+charWidth :: Char -> Number
+charWidth c = case c of
+                'a' -> 7.509259481
+                'b' -> 7.509259481
+                'c' -> 7.509259481
+                'd' -> 7.509259481
+                'e' -> 7.509259481
+                'f' -> 5.65740763
+                'g' -> 8.435185407
+                'h' -> 7.509259481
+                'i' -> 3.805555778
+                'j' -> 5.65740763
+                'k' -> 7.509259481
+                'l' -> 3.342592815
+                'm' -> 12.13888911
+                'n' -> 7.509259481
+                'o' -> 7.509259481
+                'p' -> 7.509259481
+                'q' -> 7.509259481
+                'r' -> 5.65740763
+                's' -> 6.583333556
+                't' -> 6.583333556
+                'u' -> 7.509259481
+                'v' -> 8.435185407
+                'w' -> 12.13888911
+                'x' -> 7.509259481
+                'y' -> 8.435185407
+                'z' -> 6.583333556
+                '0' -> 7.509259481
+                '1' -> 7.509259481
+                '2' -> 7.509259481
+                '3' -> 7.509259481
+                '4' -> 9.361111333
+                '5' -> 7.509259481
+                '6' -> 7.509259481
+                '7' -> 8.435185407
+                '8' -> 8.435185407
+                '9' -> 7.509259481
+                ' ' -> 5.65740763              
+                _   -> 7.509259481
+-}                
+ twentefp-rosetree.cabal view
@@ -0,0 +1,20 @@+name:                twentefp-rosetree
+version:             0.1.0.0
+synopsis:            RoseTree type and show functions for lab assignment of University of Twente.        
+license:             BSD3
+license-file:        LICENSE
+author:              Sebastiaan la Fleur
+maintainer:          sebastiaan.la.fleur@gmail.com          
+build-type:          Simple 
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     RoseTree
+   
+  build-depends:       
+        base >=4.7 && <4.8, 
+        twentefp-number >= 0.1.0.1, 
+        twentefp-eventloop-graphics == 0.1.0.0
+        
+  hs-source-dirs:      src
+  default-language:    Haskell2010