module Algorithms.Geometry.DelaunayTriangulation.Naive where
import Algorithms.Geometry.DelaunayTriangulation.Types
import Control.Lens
import Control.Monad (forM_)
import qualified Data.CircularList as C
import Data.Ext
import qualified Data.Foldable as F
import Data.Function (on)
import Data.Geometry
import Data.Geometry.Ball (disk, insideBall)
import qualified Data.List as L
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Map as M
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
delaunayTriangulation :: (Ord r, Fractional r)
=> NonEmpty.NonEmpty (Point 2 r :+ p) -> Triangulation p r
delaunayTriangulation pts = Triangulation ptIds ptsV adjV
where
ptsV = V.fromList . F.toList . NonEmpty.nubBy ((==) `on` (^.core)) $ pts
ptIds = M.fromList $ zip (map (^.core) . V.toList $ ptsV) [0..]
adjV = toAdjLists (ptIds,ptsV) . extractEdges $ fs
n = V.length ptsV - 1
fs = [ (p,q,r)
| p <- [0..n], q <- [p..n], r <- [q..n], isDelaunay (ptIds,ptsV) p q r
]
toAdjLists :: (Num r, Ord r) => Mapping p r -> [(VertexID,VertexID)]
-> V.Vector (C.CList VertexID)
toAdjLists m@(_,ptsV) es = V.imap toCList $ V.create $ do
v <- MV.replicate (V.length ptsV) []
forM_ es $ \(i,j) -> do
addAt v i j
addAt v j i
pure v
where
updateAt v i f = MV.read v i >>= \x -> MV.write v i (f x)
addAt v i j = updateAt v i (j:)
toCList u = C.fromList . sortAround' m u
sortAround' :: (Num r, Ord r)
=> Mapping p r -> VertexID -> [VertexID] -> [VertexID]
sortAround' (_,ptsV) u vs = reverse . map (^.extra) $ sortAround (f u) (map f vs)
where
f v = (ptsV V.! v)&extra .~ v
extractEdges :: [(VertexID,VertexID,VertexID)] -> [(VertexID,VertexID)]
extractEdges = map L.head . L.group . L.sort
. concatMap (\(p,q,r) -> [(p,q), (q,r), (p,r)])
isDelaunay :: (Fractional r, Ord r)
=> Mapping p r -> VertexID -> VertexID -> VertexID -> Bool
isDelaunay (_,ptsV) p q r = case disk (pt p) (pt q) (pt r) of
Nothing -> False
Just d -> not $ any (`insideBall` d)
[pt i | i <- [0..(V.length ptsV - 1)], i /= p, i /= q, i /= r]
where
pt i = (ptsV V.! i)^.core