LCOV - code coverage report
Current view: top level - src - split.jl (source / functions) Hit Total Coverage
Test: on branch nothing Lines: 92 95 96.8 %
Date: 2025-07-10 13:12:25 Functions: 0 0 -

          Line data    Source code
       1             : """
       2             :     vcenter = split!(mesh, f::FHnd[, v::VHnd = NoV])
       3             : 
       4             : Split **face** `f` by adding vertex `v` and connecting each of its
       5             : edges to `v`. The face `f` remains valid and becomes a triangle, and
       6             : `degree(mesh, f)-1` new triangles are created. If `f` is a triangle,
       7             : this is a 1:3-split. The method returns the vertex `vcenter` at which
       8             : `f` or `e` is split.
       9             : 
      10             : - If `v == NoV`, a new vertex `vcenter` is created.
      11             : - If `!isused(mesh, v)`, the vertex `v` is "reused", i.e., `vcenter == v`.
      12             : - Otherwise `v` must be an *isolated* vertex, and `vcenter == v`.
      13             : """
      14           3 : function split!(mesh::Mesh, f::FHnd, v::VHnd = NoV) :: VHnd
      15           3 :     @massert isused(mesh, f)
      16             : 
      17           3 :     isused(mesh, v) || (v = addvertex!(mesh, v))
      18           2 :     @massert isisolated(mesh, v)
      19             : 
      20           2 :     hend = halfedge(mesh, f)
      21           2 :     h = next(mesh, hend)
      22             : 
      23           2 :     hold = _create_edge(mesh, destination(mesh, hend), v)
      24             : 
      25           2 :     _setnexthalfedge!(mesh, hend, hold)
      26           2 :     _setface!(mesh, hold, f)
      27             : 
      28           2 :     hold = opposite(mesh, hold)
      29             : 
      30           6 :     while h != hend
      31           4 :         hnext = next(mesh, h)
      32             : 
      33           4 :         fnew = _create_face(mesh, h)
      34           4 :         hnew = _create_edge(mesh, destination(mesh, h), v)
      35             : 
      36           4 :         _setnexthalfedge!(mesh, hnew, hold)
      37           4 :         _setnexthalfedge!(mesh, hold, h)
      38           4 :         _setnexthalfedge!(mesh, h, hnew)
      39             : 
      40           4 :         _setface!(mesh, hnew, fnew)
      41           4 :         _setface!(mesh, hold, fnew)
      42           4 :         _setface!(mesh, h, fnew)
      43             : 
      44           4 :         hold = opposite(mesh, hnew)
      45           4 :         h = hnext
      46           4 :     end
      47             : 
      48           2 :     _setnexthalfedge!(mesh, hold, hend)
      49           2 :     _setnexthalfedge!(mesh, next(mesh, hend), hold)
      50             : 
      51           2 :     _setface!(mesh, hold, f)
      52           2 :     _sethalfedge!(mesh, v, hold)
      53             : 
      54           2 :     v
      55             : end
      56             : 
      57             : """
      58             :     hs, vs  = split!(mesh, e::EHnd[, v::VHnd = NoV])
      59             : 
      60             : Split **edge** `e` adding vertex `v`.
      61             : 
      62             : !!! warning "Procondition"
      63             :     This method **requires a triangle mesh**!
      64             : 
      65             : The method returns the new half-edge `hs` and vertex `vs` at which the
      66             : edge was split.
      67             : 
      68             : - If `v == NoV`, a new vertex `vs` is created.
      69             : - If `!isused(mesh, v)`, the vertex `v` is "reused", i.e., `vs == v`.
      70             : - Otherwise `v` must be an *isolated* vertex, and `vs == v`.
      71             : """
      72           4 : function split!(mesh::Mesh, e::EHnd, v::VHnd = NoV) :: Tuple{HHnd, VHnd}
      73           4 :     @massert isused(mesh, e)
      74             : 
      75           5 :     isused(mesh, v) || (v = addvertex!(mesh, v))
      76           3 :     @massert isisolated(mesh, v)
      77             : 
      78           3 :     h0, o0 = halfedges(mesh, e)
      79             : 
      80           3 :     v2 = destination(mesh, o0)
      81             : 
      82           3 :     e1 = _create_edge(mesh, v, v2)
      83           3 :     t1 = opposite(mesh, e1)
      84             : 
      85           3 :     f0 = face(mesh, h0)
      86           3 :     f3 = face(mesh, o0)
      87             : 
      88           3 :     _sethalfedge!(mesh, v, h0)
      89           3 :     _setvertex!(mesh, o0, v)
      90             : 
      91           3 :     if f0 != NoF
      92           3 :         @massert !isboundary(mesh, h0)
      93           3 :         @massert istriangle(mesh, f0)
      94             : 
      95           3 :         h1 = next(mesh, h0)
      96           3 :         h2 = next(mesh, h1)
      97             : 
      98           3 :         v1 = destination(mesh, h1)
      99             : 
     100           3 :         e0 = _create_edge(mesh, v, v1)
     101           3 :         t0 = opposite(mesh, e0)
     102             : 
     103           3 :         _sethalfedge!(mesh, f0, h0)
     104           3 :         f1 = _create_face(mesh, h2)
     105             : 
     106           3 :         _setface!(mesh, h1, f0)
     107           3 :         _setface!(mesh, t0, f0)
     108           3 :         _setface!(mesh, h0, f0)
     109             : 
     110           3 :         _setface!(mesh, h2, f1)
     111           3 :         _setface!(mesh, t1, f1)
     112           3 :         _setface!(mesh, e0, f1)
     113             : 
     114           3 :         _setnexthalfedge!(mesh, h0, h1)
     115           3 :         _setnexthalfedge!(mesh, h1, t0)
     116           3 :         _setnexthalfedge!(mesh, t0, h0)
     117             : 
     118           3 :         _setnexthalfedge!(mesh, e0, h2)
     119           3 :         _setnexthalfedge!(mesh, h2, t1)
     120           3 :         _setnexthalfedge!(mesh, t1, e0)
     121             :     else
     122           0 :         _setnexthalfedge!(mesh, prev(mesh, h0), t1)
     123           0 :         _setnexthalfedge!(mesh, t1, h0)
     124             :         # @massert halfedge(mesh, vh) == h0
     125             :     end
     126             : 
     127           3 :     if f3 != NoF
     128           1 :         @massert !isboundary(mesh, o0)
     129           1 :         @massert istriangle(mesh, f3)
     130             : 
     131           1 :         o1 = next(mesh, o0)
     132           1 :         o2 = next(mesh, o1)
     133             : 
     134           1 :         v3 = destination(mesh, o1)
     135             : 
     136           1 :         e2 = _create_edge(mesh, v, v3)
     137           1 :         t2 = opposite(mesh, e2)
     138             : 
     139           1 :         _sethalfedge!(mesh, f3, o0)
     140           1 :         f2 = _create_face(mesh, o1)
     141             : 
     142           1 :         _setface!(mesh, o1, f2)
     143           1 :         _setface!(mesh, t2, f2)
     144           1 :         _setface!(mesh, e1, f2)
     145             : 
     146           1 :         _setface!(mesh, o2, f3)
     147           1 :         _setface!(mesh, o0, f3)
     148           1 :         _setface!(mesh, e2, f3)
     149             : 
     150           1 :         _setnexthalfedge!(mesh, e1, o1)
     151           1 :         _setnexthalfedge!(mesh, o1, t2)
     152           1 :         _setnexthalfedge!(mesh, t2, e1)
     153             : 
     154           1 :         _setnexthalfedge!(mesh, o0, e2)
     155           1 :         _setnexthalfedge!(mesh, e2, o2)
     156           1 :         _setnexthalfedge!(mesh, o2, o0)
     157             :     else
     158           2 :         _setnexthalfedge!(mesh, e1, next(mesh, o0))
     159           2 :         _setnexthalfedge!(mesh, o0, e1)
     160           2 :         _sethalfedge!(mesh, v, e1)
     161             :     end
     162             : 
     163           3 :     (halfedge(mesh, v2) == h0) && _sethalfedge!(mesh, v2, t1)
     164             : 
     165           3 :     t1, v
     166             : end
     167             : 
     168             : """
     169             :     hs, vs  = split!(mesh, h::HHnd[, v::VHnd = NoV])
     170             : 
     171             : Split [`edge`](@ref) given by `h`, similar to
     172             : 
     173             :     split!(mesh, edge(mesh, h), v)
     174             : 
     175             : but return as `hs` the half-edge with the same orientation as
     176             : `h`. This makes a difference if `h != first(halfedges(e))`
     177             : 
     178             : See also [`halfedges`](@ref)
     179             : """
     180           2 : function split!(mesh::Mesh, h::HHnd, v::VHnd = NoV)
     181           2 :     hs, vs = split!(mesh, edge(mesh, h), v)
     182             : 
     183           1 :     isfirsthalfedge(h) && return hs, vs
     184             : 
     185           0 :     opposite(hs), vs
     186             : end

Generated by: LCOV version 1.16