packages feed

moonlight-triangulation-1.4.0.5: docs/examples/Moonlight/Triangulation/Example/ActivationZigzag.hs

module Moonlight.Triangulation.Example.ActivationZigzag
  ( ActivationZigzagExampleError (..)
  , squareLoopAcrossDepths
  ) where

import Data.Bifunctor (first)
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NonEmpty
import Data.Vector qualified as Vector
import Moonlight.Homology.Chain (HomologicalDegree (..))
import Moonlight.Triangulation.Types
  ( Point (..)
  , RadiusSquaredError
  , mkRadiusSquared
  )
import Moonlight.Triangulation.Zigzag
  ( ActivationInterval
  , ActivationPoint (..)
  , ActivationSlice (..)
  , ActivationZigzagError
  , ZigzagInterval (..)
  , activationAlphaPersistence
  )

data ActivationZigzagExampleError
  = ActivationRadiusFailed !RadiusSquaredError
  | ActivationPersistenceFailed !(ActivationZigzagError Int String)
  deriving stock (Eq, Show)

-- | Observe a square before its boundary appears, while it carries one loop,
-- and after its two Delaunay faces fill that loop.  The returned interval uses
-- the expanded observation/union stages rather than pretending the slices are
-- a monotone filtration.
squareLoopAcrossDepths :: Either ActivationZigzagExampleError [ActivationInterval Int]
squareLoopAcrossDepths = do
  let depths :: NonEmpty Int
      depths = 0 :| [1, 2]
  thresholds <-
    traverse
      (first ActivationRadiusFailed . mkRadiusSquared . fromIntegral)
      depths
  intervals <-
    first ActivationPersistenceFailed
      ( activationAlphaPersistence
          ( NonEmpty.zipWith
              (\depthValue threshold -> ActivationSlice depthValue threshold squarePoints)
              depths
              thresholds
          )
      )
  pure (filter ((== HomologicalDegree 1) . zigzagIntervalDegree) intervals)

squarePoints :: Vector.Vector (ActivationPoint String)
squarePoints =
  Vector.fromList
    [ ActivationPoint "south-west" (Point (-1) (-1))
    , ActivationPoint "south-east" (Point 1 (-1))
    , ActivationPoint "north-east" (Point 1 1)
    , ActivationPoint "north-west" (Point (-1) 1)
    ]