qhull-0.1.0.1: src/Voronoi/Voronoi.hs
module Voronoi.Voronoi
where
import qualified Data.IntMap.Strict as IM
import qualified Data.IntSet as IS
import Data.Maybe
import Delaunay.Delaunay (vertexNeighborFacets)
import Delaunay.Types
import Qhull.Shared
import Qhull.Types
type Point = [Double]
type Vector = [Double]
data Edge = Edge (Point, Point) | IEdge (Point, Vector)
deriving Show
type Cell = [Edge]
-- factor2 :: (Double,Double,Double,Double) -> (Double,Double) -> (Double,Double) -> Double
-- factor2 box@(xmin, xmax, ymin, ymax) p@(p1,p2) (v1,v2)
-- | v1==0 = if v2>0 then (ymax-p2)/v2 else (ymin-p2)/v2
-- | v2==0 = if v1>0 then (xmax-p1)/v1 else (xmin-p1)/v1
-- | otherwise = min (factor2 box p (v1,0)) (factor2 box p (0,v2))
-- -- | v1>0 && v2>0 = min ((r-p1)/v1) ((t-p2)/v2)
-- -- | v1>0 && v2<0 = min ((r-p1)/v1) ((b-p2)/v2)
-- -- | v1<0 && v2>0 = min ((l-p1)/v1) ((t-p2)/v2)
-- -- | v1<0 && v2<0 = min ((l-p1)/v1) ((b-p2)/v2)
-- approx :: RealFrac a => Int -> a -> a
-- approx n x = fromInteger (round $ x * (10^n)) / (10.0^^n)
edgesFromTileFacet :: Tesselation -> TileFacet -> Maybe Edge
edgesFromTileFacet tess tilefacet
| length tileindices == 1 = Just $ IEdge (c1, _normal tilefacet)
| sameFamily (_family tile1) (_family tile2) || c1 == c2 = Nothing
| otherwise = Just $ Edge (c1, c2)
where
tileindices = (IS.toList . _facetOf) tilefacet
tiles = _tiles tess
tile1 = tiles IM.! head tileindices
tile2 = tiles IM.! last tileindices
c1 = _center tile1
c2 = _center tile2
voronoiCell :: ([TileFacet] -> [TileFacet]) -> (Edge -> a) -> Tesselation
-> Index -> [a]
voronoiCell facetsQuotienter edgeTransformer tess i =
let tilefacets = facetsQuotienter $ IM.elems (vertexNeighborFacets tess i) in
map (edgeTransformer . fromJust) $
filter isJust $ map (edgesFromTileFacet tess) tilefacets
voronoi :: (Tesselation -> Index -> a) -> Tesselation -> [([Double], a)]
voronoi cellGetter tess =
let sites = IM.elems $ _vertices tess in
zip sites (map (cellGetter tess) [0 .. length sites -1])
voronoi' :: Tesselation -> [([Double], Cell)]
voronoi' = voronoi (voronoiCell id id)
-- | whether a Voronoi cell is bounded
boundedCell :: Cell -> Bool
boundedCell = all isFiniteEdge
where
isFiniteEdge (Edge _) = True
isFiniteEdge _ = False