packages feed

moonlight-triangulation-0.1.0.0: src-dcel/Moonlight/Triangulation/Handles/Iterators/DynamicIterators.hs

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}

module Moonlight.Triangulation.Handles.Iterators.DynamicIterators
  ( vertexHandles
  , directedEdgeHandles
  , undirectedEdgeHandles
  , allFaceHandles
  , innerFaceHandles
  , hullEdgeHandles
  , hullVertexHandles
  , foldVertexHandles'
  , foldDirectedEdgeHandles'
  , foldUndirectedEdgeHandles'
  , foldAllFaceHandles'
  , foldInnerFaceHandles'
  , foldHullEdgeHandles'
  , foldHullVertexHandles'
  ) where

import Moonlight.Triangulation.Handles.Dynamic
import Moonlight.Triangulation.Handles.Iterators.FixedIterators qualified as Fixed
import Moonlight.Triangulation.Handles.Iterators.HullIterator qualified as Hull
import Moonlight.Triangulation.Types

-- | Dynamic handles in fixed-index order. The list spine is lazy; use the
-- strict folds below for allocation-free traversal in hot paths.
vertexHandles
  :: Triangulation mode vertex directed undirected face
  -> [VertexHandle mode vertex directed undirected face]
vertexHandles triangulation =
  mapValid (vertexHandle triangulation) (Fixed.vertices triangulation)

directedEdgeHandles
  :: Triangulation mode vertex directed undirected face
  -> [DirectedEdgeHandle mode vertex directed undirected face]
directedEdgeHandles triangulation =
  mapValid (directedEdgeHandle triangulation) (Fixed.directedEdges triangulation)

undirectedEdgeHandles
  :: Triangulation mode vertex directed undirected face
  -> [UndirectedEdgeHandle mode vertex directed undirected face]
undirectedEdgeHandles triangulation =
  mapValid (undirectedEdgeHandle triangulation) (Fixed.undirectedEdges triangulation)

allFaceHandles
  :: Triangulation mode vertex directed undirected face
  -> [FaceHandle PossiblyOuterTag mode vertex directed undirected face]
allFaceHandles triangulation =
  mapValid (faceHandle triangulation) (Fixed.allFaces triangulation)

innerFaceHandles
  :: Triangulation mode vertex directed undirected face
  -> [FaceHandle InnerTag mode vertex directed undirected face]
innerFaceHandles triangulation =
  mapValid (innerFaceHandle triangulation) (Fixed.innerFaces triangulation)

hullEdgeHandles
  :: Triangulation mode vertex directed undirected face
  -> [DirectedEdgeHandle mode vertex directed undirected face]
hullEdgeHandles triangulation =
  mapValid (directedEdgeHandle triangulation) (Hull.hullEdges triangulation)

hullVertexHandles
  :: Triangulation mode vertex directed undirected face
  -> [VertexHandle mode vertex directed undirected face]
hullVertexHandles triangulation =
  map directedEdgeFrom (hullEdgeHandles triangulation)

foldVertexHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> VertexHandle mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldVertexHandles' triangulation step =
  Fixed.foldVertices' triangulation (applyValid (vertexHandle triangulation) step)

foldDirectedEdgeHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> DirectedEdgeHandle mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldDirectedEdgeHandles' triangulation step =
  Fixed.foldDirectedEdges' triangulation (applyValid (directedEdgeHandle triangulation) step)

foldUndirectedEdgeHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> UndirectedEdgeHandle mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldUndirectedEdgeHandles' triangulation step =
  Fixed.foldUndirectedEdges' triangulation (applyValid (undirectedEdgeHandle triangulation) step)

foldAllFaceHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> FaceHandle PossiblyOuterTag mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldAllFaceHandles' triangulation step =
  Fixed.foldAllFaces' triangulation (applyValid (faceHandle triangulation) step)

foldInnerFaceHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> FaceHandle InnerTag mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldInnerFaceHandles' triangulation step =
  Fixed.foldInnerFaces' triangulation (applyValid (innerFaceHandle triangulation) step)

foldHullEdgeHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> DirectedEdgeHandle mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldHullEdgeHandles' triangulation step =
  Hull.foldHullEdges' triangulation (applyValid (directedEdgeHandle triangulation) step)

foldHullVertexHandles'
  :: Triangulation mode vertex directed undirected face
  -> (accumulator -> VertexHandle mode vertex directed undirected face -> accumulator)
  -> accumulator
  -> accumulator
foldHullVertexHandles' triangulation step =
  foldHullEdgeHandles' triangulation (\accumulator edge -> step accumulator (directedEdgeFrom edge))

mapValid :: (fixed -> Maybe dynamic) -> [fixed] -> [dynamic]
mapValid make = foldr collect []
 where
  collect fixed rest = case make fixed of
    Just dynamic -> dynamic : rest
    Nothing -> rest

applyValid
  :: (fixed -> Maybe dynamic)
  -> (accumulator -> dynamic -> accumulator)
  -> accumulator
  -> fixed
  -> accumulator
applyValid make step !accumulator fixed = case make fixed of
  Just dynamic -> step accumulator dynamic
  Nothing -> accumulator