Graph topology
Adjacency matrix and Graph Laplacian
Get adjacencymatrix
or graphlaplacian
(aka umbrella
operator) as SparseMatrix
.
PMesh.adjacencymatrix
— FunctionA = 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
hasnv
rows and columns.- The optional argument
one
determines the type ofA::SparseMatrix{typof(one)}
. - If
boundary==true
,A
is always symmetric. Ifboundary==false
,A
is symmetric only ifmesh
has no boundary.
Use the optional boundary
argument to mimic construction of an adjacency matrix from, e.g., a facetable
See also graphlaplacian
PMesh.graphlaplacian
— MethodL = 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 vertexdegree
s $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
PMesh.umbrella
— MethodL = umbrella(mesh[; symmetric=true, typ=Float64])
Get uniform Laplacian (Leif Kobbelt's umbrella operator) either as symmetric
sparse matrix (i.e., with vertex degree
s 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}
.
See also graphlaplacian
, adjacencymatrix
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.boundaryloop
— MethodSynonym for boundaryloopccw
PMesh.boundaryloopccw
— Methodfor 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.
Expects boundary half-edge h0
(isboundary
).
See also boundayloop
PMesh.findboundaryloops
— Functionloops = 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
.
See also findboundaryloopseeds
, boundaryloopccw
PMesh.findboundaryloopseeds
— Methodseeds = findboundaryloopseeds(mesh)
Find all boundary loops and return Vector{HHnd}
of seeds, i.e., some arbitrary half-edge per loop.
See also findboundaryloops
, boundaryloopccw
PMesh.vertices
— Methoditr = vertices(boundaryloopccw(mesh, h0))
Iterate boundary vertices instead of half-edges.
See also boundaryloopccw
General utilities
# Copy mesh with inverse orientation of faces.
# (Does not copy attributes of (half-)edges!)
flipped = fliporientation(mesh)
PMesh.fliporientation
— Methodfmesh = 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.
PMesh.vertices
— Methodvs = 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.