-- 实现四叉树(遵循数学中象限的定义方式:右上角为第一象限,逆时针递进,右下角为第四象限) implement QuadTree (the order of quadrant follows mathematical coordinate system) data QuadTree = Cell Color Int | Grid QuadTree QuadTree QuadTree QuadTree deriving (Eq, Show)
一个函数 allBlack,它接受一个整数 n 并返回一个全黑的单个细胞的表示。 参数 n 代表图像“大小”,但由于任何尺寸的全黑图像看起来都相同,因此可以忽略此参数! 但是我没有忽略!!!(后续有用…)
1 2 3
-- returns a Black or White cell of a specified size allBlack :: Int -> QuadTree allBlack size = Cell Black size
一个函数 allWhite,它接受一个整数 n 并返回一个全白的单个细胞的表示。 参数 n 代表图像“大小”,同上
1 2
allWhite :: Int -> QuadTree allWhite size = Cell White size
一个顺时针函数,它采用四个四叉树并返回四叉树,其四个子树是给定输入,按顺时针顺序排列。
1 2 3
-- The first quadrant is top-right! clockwise :: QuadTree -> QuadTree -> QuadTree -> QuadTree -> QuadTree clockwise a b c d = Grid a b c d
一个逆时针函数,它采用四个四叉树并返回四叉树,其四个子树是给定输入,按逆时针顺序排列。
1 2
anticlockwise :: QuadTree -> QuadTree -> QuadTree -> QuadTree -> QuadTree anticlockwise a b c d = Grid a d c b
顺时针排序是指在a b c d顺时针方向的四叉树中,子树b位于a顺时针移动到达的象限内,c位于b顺时针移动到达的象限内,d位于c顺时针移动到达的象限内,a位于从d顺时针移动到达的象限内。反之亦然。
-- According to neighbor's weight to decide if it should reverse the color -- Current QuadTree -> (initial QuadTree, initial QuadTree size) -> (Current x, y, Current QuadTree size) -> output reverseMini :: QuadTree -> (QuadTree, Double) -> (Double, Double, Double) -> QuadTree -- for Cell reverseMini (Cell ce cellSize) (fullTree, treeSize) (x_now, y_now, _) -- more than half of its neighbours have the opposite colour, reverse its colour | ce == Black && (neighborWeight > 0) = Cell White cellSize | ce == White && (neighborWeight < 0) = Cell Black cellSize | otherwise = Cell ce cellSize where neighborWeight = getNeighbourWeight (fullTree, treeSize) (x_now, y_now, fromIntegral cellSize) -- for Grid, contiinue recursion reverseMini (Grid a b c d) (fullTree, treeSize) (x_now, y_now, fullSize) = clockwise (reverseMini a (fullTree, treeSize) (x_now + offset, y_now - offset, fullSize / 2)) (reverseMini b (fullTree, treeSize) (x_now - offset, y_now - offset, fullSize / 2)) (reverseMini c (fullTree, treeSize) (x_now - offset, y_now + offset, fullSize / 2)) (reverseMini d (fullTree, treeSize) (x_now + offset, y_now + offset, fullSize / 2)) where offset = fullSize / 4
-- detect one specified border of a certain Gird/Cell and sum its all cells values(weights) according to colors -- a Quadtree (or Nothing) -> one of the four inner-borders -> border :: Maybe QuadTree -> String -> Int -- invalid border Nothing _ = 0 -- calculate the weight of the Cell border (Just (Cell ce _)) _ | ce == White = 1 -- White cells are worth +1 | ce == Black = -1 -- black cells are worth -1 -- continue to implement recursion for Grid if cell is not arrived border (Just (Grid a b c d)) direction | direction == "up" = border (Just a) "up" + border (Just b) "up" | direction == "left" = border (Just b) "left" + border (Just c) "left" | direction == "down" = border (Just c) "down" + border (Just d) "down" | direction == "right" = border (Just a) "right" + border (Just d) "right"
-- output the size of a QuadTree by calculating the length of one side (eg. top) getTreeSize :: QuadTree -> Double getTreeSize (Cell ce size) = fromIntegral size getTreeSize (Grid a b c d) = getTreeSize a + getTreeSize b
-- detect one specified side of a certain Gird/Cell and sum its all cells values according to colors -- a Quadtree (or Nothing) -> one of the four inside-borders -> side :: Maybe QuadTree -> String -> Int -- invalid side Nothing _ = 0 -- calculate the weight of the Cell side (Just (Cell ce _)) _ | ce == White = 1 -- White cells are worth +1 | ce == Black = -1 -- black cells are worth -1 -- continue to implement recursion for Grid if cell is not arrived side (Just (Grid a b c d)) direction | direction == "top" = side (Just a) "top" + (side (Just b) "top") | direction == "bottom" = side (Just c) "bottom" + (side (Just d) "bottom") | direction == "left" = side (Just b) "left" + (side (Just c) "left") | direction == "right" = side (Just a) "right" + (side (Just d) "right")
至此,完整的代码已全部展现。
About this Post
This post is written by Rui Xu, licensed under CC BY-NC 4.0.