Graph topology

Adjacency matrix and Graph Laplacian

Get adjacencymatrix or graphlaplacian (aka umbrella operator) as SparseMatrix.

PMesh.adjacencymatrixFunction
A = adjacencymatrix(mesh[; one=1, boundary=true])

Get sparse adjacency matrix with A[i, j] == one if halfedge (i, j) exists and either boundary==true or (i, j) is not a boundary half-edge.

  • A has nv rows and columns.
  • The optional argument one determines the type of A::SparseMatrix{typof(one)}.
  • If boundary==true, A is always symmetric. If boundary==false, A is symmetric only if mesh has no boundary.
Note

Use the optional boundary argument to mimic construction of an adjacency matrix from, e.g., a facetable

See also graphlaplacian

source
PMesh.graphlaplacianMethod
L = graphlaplacian(mesh[; edges = Undirected(),
                          mode = Plain(),
                          typ=Float64)

Get Graph Laplacian L with

  • edges = Undirected(): ignore edge orientation,
  • edged ∈ [InEdges(), OutEdges()]: consider only given orientation.

and

  • mode = Plain() graph Laplacian $D - A$ (for adjacency matrix $A$ and diagonal matrix with vertex degrees $D$, equals -umbrella(mesh; symmetric=true)),
  • mode = Normalized() normalized graph Laplacian $D^{-1}\,(D-A)$ (equals -umbrella(mesh; symmetric=false)),
  • mode = NormalizedSymmetric() symmetrically normalized graph Laplacian $I\,-\,D^{-\tfrac{1}{2}}\,(D-A)\,D^{-\tfrac{1}{2}}$.

See also umbrella, adjacencymatrix

source
PMesh.umbrellaMethod
L = umbrella(mesh[; symmetric=true, typ=Float64])

Get uniform Laplacian (Leif Kobbelt's umbrella operator) either as symmetric sparse matrix (i.e., with vertex degrees on matrix diagonal) or with row weighting by inverse vertex degrees (i.e., with unit-diagonal). The optional keyword argument typ determines the SparseMatrix{typ}.

Note

This implementation does not treat the boundary as a univariate polygon.

See also graphlaplacian, adjacencymatrix

source

Boundary loops

Iterate boundary loops starting from boundary half-edge h0: boundaryloopccw aka boundaryloop.

# iterate half-edges

for h in boundaryloop(mesh, h0)
    # ...
end

collect(boundaryloop(mesh, h0))


# iterate vertices

for v in vertices(boundaryloop(mesh, h0))
    # ...
end

collect(vertices(boundaryloop(mesh, h0)))

Find all boundary loops: findboundaryloopseeds and findboundaryloops.

seeds = findboundaryloopseeds(mesh)

for h0 in seeds, h in boundaryloop(mesh, h0)
    # ...
end

loops = findboundaryloops(mesh)

for loop in loops, h in loop
    # ...
end
PMesh.boundaryloopccwMethod
for h in boundaryloop(mesh, h0)
    # ...
end

for v in vertices(boundaryloop(mesh, h0))
    # ...
end

Iterate boundary loop half-edges or vertices starting with boundary hald-edge h0 counter-clockwise.

precondition

Expects boundary half-edge h0 (isboundary).

precondition

The iteration is undefined if mesh is non-manifold.

See also boundayloop

source
PMesh.findboundaryloopsFunction
loops = findboundaryloops(mesh)

for loop in loops, h in loop
    # ...
end

Find boundary loops and return array of loops, where each loop is encoded as an array of HHnd.

findboundaryloops(mesh) do h0, h
    if h == h0
          # new loop with seed h0
    end

    # process h as part of loop
end

Find boundary loops and evaluate callback for every boundary half-edfe with arguments h0 (seed) and h current boundary half-edge: a new boundary loop is found whenever h0 == h. This method returns nothing.

precondition

The result is undefined if mesh is non-manifold.

See also findboundaryloopseeds, boundaryloopccw

source

General utilities

# Copy mesh with inverse orientation of faces.
# (Does not copy attributes of (half-)edges!)

flipped = fliporientation(mesh)
PMesh.fliporientationMethod
fmesh = fliporientation(mesh)

Get new mesh with inverse orientation of faces. Vertex handles and face handles are preserved if iscontiguous(mesh). There is no mapping for attributes of (half-)edges.

Warning

fliporientation(mesh) copies only user-defined vertex and face attributes!

source
PMesh.verticesMethod
vs = vertices(mesh, hs::Vector{HHnd})

Get Vector of vertices vs from Vector of half-edges hs. If hs represents a closed edge loops, the first vertex is not repeated.

source