Guest User

Untitled

a guest
Jan 23rd, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.62 KB | None | 0 0
  1. {-# LANGUAGE TypeFamilies, DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
  2.  
  3. import Control.Applicative {- from base -}
  4. import Data.Distributive {- from distributive -}
  5. import Data.Key {- from the keys package -}
  6. import Data.Functor.Bind {- from semigroupoids -}
  7. import Data.Functor.Representable {- from representable-functors -}
  8.  
  9. -- lets define unpacked affine 3-vectors of doubles
  10. data Vector = Vector {-# UNPACK #-} !Double {-# UNPACK #-} !Double {-# UNPACK #-} !Double deriving (Eq, Ord, Show)
  11.  
  12. -- first lets define a functor that contains eight items
  13. data Oct a = Oct !a !a !a !a !a !a !a !a deriving (Eq, Ord, Show, Functor, Foldable, Traversable)
  14.  
  15. -- we'll pretend that only ints from 0 to 7 exist to avoid making a more specific key type.
  16. type instance Key Oct = Int
  17.  
  18. -- we can tabulate a function
  19. instance Representable Oct where
  20. tabulate f = Oct (f 0) (f 1) (f 2) (f 3) (f 4) (f 5) (f 6) (f 7)
  21.  
  22. -- index into the structure
  23. instance Indexable Oct where
  24. index (Oct s _ _ _ _ _ _ _) 0 = s
  25. index (Oct _ t _ _ _ _ _ _) 1 = t
  26. index (Oct _ _ u _ _ _ _ _) 2 = u
  27. index (Oct _ _ _ v _ _ _ _) 3 = v
  28. index (Oct _ _ _ _ w _ _ _) 4 = w
  29. index (Oct _ _ _ _ _ x _ _) 5 = x
  30. index (Oct _ _ _ _ _ _ y _) 6 = y
  31. index (Oct _ _ _ _ _ _ _ z) 7 = z
  32. index _ _ = error "index out of range"
  33.  
  34. -- adjust a single slot
  35. instance Adjustable Oct where
  36. adjust f 0 (Oct s t u v w x y z) = Oct (f s) t u v w x y z
  37. adjust f 1 (Oct s t u v w x y z) = Oct s (f t) u v w x y z
  38. adjust f 2 (Oct s t u v w x y z) = Oct s t (f u) v w x y z
  39. adjust f 3 (Oct s t u v w x y z) = Oct s t u (f v) w x y z
  40. adjust f 4 (Oct s t u v w x y z) = Oct s t u v (f w) x y z
  41. adjust f 5 (Oct s t u v w x y z) = Oct s t u v w (f x) y z
  42. adjust f 6 (Oct s t u v w x y z) = Oct s t u v w x (f y) z
  43. adjust f 7 (Oct s t u v w x y z) = Oct s t u v w x y (f z)
  44.  
  45. -- and because we're representable, we can do lots of things
  46. instance Lookup Oct where
  47. lookup = lookupDefault
  48.  
  49. instance Keyed Oct where
  50. mapWithKey = mapWithKeyRep
  51.  
  52. instance Zip Oct where
  53. zipWith = zipWithRep
  54.  
  55. instance ZipWithKey Oct where
  56. zipWithKey = zipWithKeyRep
  57.  
  58. instance Bind Oct where
  59. (>>-) = bindRep
  60.  
  61. instance Apply Oct where
  62. (<.>) = apRep
  63.  
  64. instance Applicative Oct where
  65. pure = pureRep
  66. (<*>) = apRep
  67.  
  68. instance Monad Oct where
  69. return = pureRep
  70. (>>=) = bindRep
  71.  
  72. instance Distributive Oct where
  73. distribute = distributeRep
  74.  
  75. -- then we'll make a primitive octree without annotating it with AABBs
  76. data Tree a
  77. = Empty
  78. | Node {-# UNPACK #-} !(Oct (Tree a))
  79. | Tip {-# UNPACK #-} !Vector a
  80. deriving (Eq, Ord, Show, Functor, Foldable, Traversable)
  81.  
  82. -- but we'll build a wrapper around it that contains the AABB.
  83. data Octree a = Octree
  84. { lo :: {-# UNPACK #-} !Vector
  85. , hi :: {-# UNPACK #-} !Vector
  86. , tree :: !(Tree a)
  87. } deriving (Eq, Ord, Show, Functor, Foldable, Traversable)
  88.  
  89. -- given this cheesy little convenience function
  90. infix 7 ?
  91. (?) :: Bool -> Int -> Int
  92. False ? _ = 0
  93. True ? x = x
  94.  
  95. -- we can make a combinator that knows how to calculate what octant the vector is in
  96. -- and return the bounding box of that octant. If we don't use the vectors, laziness will
  97. -- save us the trouble of computing them.
  98. walk :: Vector -> Vector -> Vector -> (Int -> Vector -> Vector -> r) -> r
  99. walk (Vector xl yl zl) (Vector xh yh zh) (Vector x y z) k =
  100. k (xq ? 1 + yq ? 2 + zq ? 4) (Vector xl' yl' zl') (Vector xh' yh' zh')
  101. where xm = xl + (xh - xl) / 2
  102. ym = yl + (yh - yl) / 2
  103. zm = zl + (zh - zl) / 2
  104. xq = x <= xm
  105. yq = y <= ym
  106. zq = z <= zm
  107. (xl',xh') = if xq then (xl,xm) else (xm,xh)
  108. (yl',yh') = if yq then (yl,ym) else (ym,yh)
  109. (zl',zh') = if zq then (zl,zm) else (zm,zh)
  110.  
  111. -- Now we are able to define insertWith directly
  112. insertWith :: (a -> a -> a) -> Vector -> a -> Octree a -> Octree a
  113. insertWith f v a (Octree lo0 hi0 t0) = Octree lo0 hi0 $ go lo0 hi0 t0 where
  114. -- empty node, so just insert
  115. go _ _ Empty = Tip v a
  116. -- we've found an octree node, figure out the desired branch and descend
  117. go lo hi (Node n) = walk lo hi v $ \o lo' hi' -> Node $ adjust (go lo' hi') o n
  118. -- we're at a leaf
  119. go lo hi n@(Tip v' a')
  120. -- if we have a collision, use our combining function
  121. | v == v' = Tip v (f a' a)
  122. -- split the tip, and then continue inserting into the result
  123. | otherwise = walk lo hi v' $ \o _ _ -> go lo hi $ Node $ replace o n $ pure Empty
  124.  
  125. -- and we built insert on top of that.
  126. insert :: Vector -> a -> Octree a -> Octree a
  127. insert = insertWith const
  128.  
  129. -- we can map over the primitive octree with access to the key, but thats about it
  130. type instance Key Tree = Vector
  131.  
  132. instance Keyed Tree where
  133. mapWithKey _ Empty = Empty
  134. mapWithKey f (Node e) = Node $ mapWithKey f <$> e
  135. mapWithKey f (Tip v a) = Tip v (f v a)
  136.  
  137. -- but our wrapped octrees have a notion of a key as well, and admit more efficient operations
  138. type instance Key Octree = Vector
  139.  
  140. -- we can then piggyback some additional functionality from the types in Data.Key
  141. instance Adjustable Octree where
  142. adjust f v (Octree lo0 hi0 t0) = Octree lo0 hi0 $ go lo0 hi0 t0 where
  143. go _ _ Empty = Empty
  144. go lo hi (Node n) = walk lo hi v $ \o lo' hi' -> Node $ adjust (go lo' hi') o n
  145. go lo hi n@(Tip v' a)
  146. | v == v' = Tip v' (f a)
  147. | otherwise = Tip v' a
  148.  
  149. instance Keyed Octree where
  150. mapWithKey f (Octree lo hi t) = Octree lo hi (mapWithKey t)
  151.  
  152. instance Lookup Octree where
  153. lookup v (Octree lo0 hi0 t0) = go lo0 hi0 t0 where
  154. go _ _ Empty = Nothing
  155. go lo hi (Node n) = walk lo hi v $ \o lo' hi' -> go lo hi' (index n o)
  156. go lo hi (Tip v' a) | v == v' = Just a
  157. | otherwise = Nothing
  158.  
  159. create :: Vector -> Vector -> Octree a
  160. create lo hi = Octree lo hi Empty
Add Comment
Please, Sign In to add comment