How to implement a Half-edge data structure in Haskell?

For a description of the data structure, see

The half-edge data structure includes loops.

  • Is it possible to implement it in a functional language such as Haskell?
  • are mutable links (STRef) to go?

thank

+3
source share
4 answers

, HE_vert ( HE_vert_acc... HE_vert), HE_edges, HE_vert. "HE_edge *" ( ), . .

, , () . , , , HE_vert_acc , HE_edges . . , , .

- ... " haskell". , API. , , .

, , . , .

EDIT: , , .obj mesh.

, https://wiki.haskell.org/Tying_the_Knot#Migrated_from_the_old_wiki, , , , DFA .

, , 3 .

, , :

data HeVert a = HeVert {
    vcoord  :: a        -- the coordinates of the vertex
  , emedge  :: HeEdge a -- one of the half-edges emanating from the vertex
}

data HeFace a = HeFace {
  bordedge :: HeEdge a -- one of the half-edges bordering the face
}

data HeEdge a = HeEdge {
    startvert :: HeVert a          -- start-vertex of the half-edge
  , oppedge   :: Maybe (HeEdge a)  -- oppositely oriented adjacent half-edge
  , edgeface  :: HeFace a          -- face the half-edge borders
  , nextedge  :: HeEdge a          -- next half-edge around the face
}

, , "", , .obj mesh.

, :

data IndirectHeEdge = IndirectHeEdge {
    edgeindex  :: Int  -- edge index
  , svindex    :: Int  -- index of start-vertice
  , nvindex    :: Int  -- index of next-vertice
  , indexf     :: Int  -- index of face
  , offsetedge :: Int  -- offset to get the next edge
}

data IndirectHeVert = IndirectHeVert {
    emedgeindex  :: Int    -- emanating edge index (starts at 1)
  , edgelist     :: [Int]  -- index of edge that points to this vertice
}

data IndirectHeFace =
  IndirectHeFace (Int, [Int]) -- (faceIndex, [verticeindex])

, , , . "". , . , C-. "edgelist" .

, , .obj. , .

, :

v 50.0 50.0
v 250.0 50.0
v 50.0 250.0
v 250.0 250.0
v 50.0 500.0
v 250.0 500.0
f 1 2 4 3
f 3 4 6 5

:

[IndirectHeFace (0,[1,2,4,3]),IndirectHeFace (1,[3,4,6,5])]

:

[IndirectHeEdge {edgeindex = 0, svindex = 1, nvindex = 2, indexf = 0, offsetedge = 1},
IndirectHeEdge {1, 2, 4, 0, 1},
IndirectHeEdge {2, 4, 3, 0, 1},
IndirectHeEdge {3, 3, 1, 0, -3},
IndirectHeEdge {0, 3, 4, 1, 1},
IndirectHeEdge {1, 4, 6, 1, 1},
IndirectHeEdge {2, 6, 5, 1, 1},
IndirectHeEdge {3, 5, 3, 1, -3}]

:

[(1,IndirectHeVert {emedgeindex = 0, edgelist = [3]}),
(2,IndirectHeVert {1, [0]}),
(3,IndirectHeVert {4, [7,2]}),
(4,IndirectHeVert {5, [4,1]}),
(5,IndirectHeVert {7, [6]}),
(6,IndirectHeVert {6, [5]})]

, "", . , - .

( , ):

indirectToDirect :: [a]   -- parsed vertices, e.g. 2d points (Double, Double)
                 -> [IndirectHeEdge]
                 -> [IndirectHeFace]
                 -> [IndirectHeVert]
                 -> HeEdge a
indirectToDirect points edges faces vertices
  = thisEdge (head edges)
  where
    thisEdge edge
      = HeEdge (thisVert (vertices !! svindex edge) $ svindex edge)
               (thisOppEdge (svindex edge) $ indexf edge)
               (thisFace $ faces !! indexf edge)
               (thisEdge $ edges !! (edgeindex edge + offsetedge edge))
    thisFace face = HeFace $ thisEdge (edges !! (head . snd $ face))
    thisVert vertice coordindex
      = HeVert (points !! (coordindex - 1))
               (thisEdge $ points !! (emedgeindex vertice - 1))
    thisOppEdge startverticeindex faceindex
      = thisEdge
        <$>
        (headMay
          . filter ((/=) faceindex . indexf)
          . fmap (edges !!)
          . edgelist         -- getter
          $ vertices !! startverticeindex)

, "Maybe (HeEdge a)", ( ), , . NoVert/NoEdge/NoFace , "Maybe".

, . , ( ) .

Data.IntMap.Lazy, , ( , IndirectHeVert). Data.Vector .

, .

+1

, , ( ). " ", . , (, Ints). ID, Data.Map. , , , , .

, , . , Haskell .

+2

, , " " - , .

, , . , O (..) . , (, API ).

+1

. , .

, :

data Foo edge_type_t = Depot {
   edge_type :: edge_type_t,
   idxI, idxE, idxF, idxL :: !Int
} deriving (Show, Read)

loadFoo edgetypes d = d { edge_type = edgetypes ! edge_type d }
unloadFoo d = d { edge_type = edgetype_id $ edge_type d }

However, there is one serious caveat: You cannot make a type Foo (Foo (Foo( ...)))this way because Haskell must understand the type recursively. :(

0
source

Source: https://habr.com/ru/post/1771615/


All Articles