State & basic navigation
State
Generate element handles
The vertices
, faces
, halfedges
, and edges
methods generate sequences of used mesh elements (or of a local neighborhood).
Example
# iterate over all vertices in mesh
for v in vertices(mesh)
@assert isused(mesh, v)
@show v
end
@assert count(vertices(mesh)) == nv(mesh)
@assert count(faces(mesh)) == nf(mesh)
@assert count(edges(mesh)) == ne(mesh)
# iterate over vertices spanning face f
for v in vertices(mesh, f)
@show v
end
Properties
Query isused
status of elements.
Query number of elements (nv
, nf
, nh
, ne
), degree
of vertices.
Query storage layout (iscontiguous
). Provide hints sizehint!
, free unused storage (shrink!
).
Query global and local properties of the surface mesh, e.g.,
isempty
istrianglemesh
,isquadmesh
, (maxfacedegree
)hasisolatedvertices
,isisolated
(local)ismanifold
(local/global),isclosed
,isboundary
,isinner
(local)boundaryhalfedge
Manifold surface
The semantics of PMesh
partially differ from other libraries (e.g., PMP) w.r.t. isolated vertices:
Isolated vertices are neither boundary – they are not part of a boundary loop – nor manifold – there is no 1d or 2d neigborhood, nor inner vertices. This affects the methods isboundary
, ismanifold
and isinner
.
The optional keyword argument allowisolated
changes the semantics.
isboundary => !isisolated [unless allowisolated]
isisolated => !ismanifold [unless allowisolated]
isinner => !isboundary and !isisolated (&& ismanifold) [unless allowisolated]
!isboundary && !isisolated => ismanifold
Base.isempty
— Methodisempty(mesh)
Is mesh empty, i.e., it does not contain any vertices or edges.
Base.sizehint!
— Functionsizehint!(mesh, nv[, nf=2nv])
Provide a hint on the total number of vertices nv
and faces
nf` for preallocation of storage.
PMesh.boundaryhalfedge
— Methodh = boundaryhalfedge(mesh, e)
If e
is a boundary edge, return the boundary half-edge h
, i.e., isboundary(mesh, h) == true
. Return NoH
if e
is not boundary.
See also isboundary
PMesh.degree
— Functionn = degree(mesh, f::FHnd)
n = degree(mesh, v::VHnd)
Get face degree, i.e., number of vertices spanning f
, or vertex degree, i.e., number of edges incident to v
.
The vertex degree is alternatively called valence (e.g., in the PMP library).
PMesh.details
— Method@show details(mesh)
@show mesh # prints only nv, nf
Print detailed overview of mesh
with its attributes.
PMesh.edge
— Methode = edge([mesh,] h::HHnd)
Get edge handle from half-edge handle.
PMesh.edges
— Methodfor e in edges(mesh)
...
end
Generate sequence of all edges.
PMesh.ehnds
— Method[e for e in ehnds(mesh)]
Generate sequence of all –including unused – edge handles.
PMesh.face
— MethodPMesh.faces
— Methodfor f in faces(mesh)
...
end
Generate sequence of all used faces.
PMesh.fhnds
— Method[f for f in fhnds(mesh)]
Generate sequence of all –including unused – face handles.
PMesh.halfedge
— Functionh = halfedge([mesh,] e::EHnd, i)
Get first (i==1
) or second (i==2
) half-edge of edge e
.
PMesh.halfedge
— Methodh = halfedge(mesh, f::FHnd)
Get some half-edge in the sequence of half-edges that span the face f
.
PMesh.halfedge
— Methodh = halfedge(mesh, v::VHnd)
Get some outgoing half-edge of vertex v
.
Returns h == NoH
if there is such half-edge. In this case v
is an isolated vertex.
If v
is a boundary vertex, h
is guaranteed to be a boundary half-egde, i.e., its opposite
half-edge equals NoH
.
If v
is a boundary vertex, there may exist multiple outgoing boundary half-edges. If so, v
is not a manifold vertex.
See also isisolated
, isboundary
, ismanifold
PMesh.halfedges
— Functionh0, h1 = halfedges([mesh,] e::EHnd)
Get ordered pair of half-edges h0, h1
such that Int(h0) + 1 == Int(h1)
.
h0, h1 = halfedges([mesh,] h::HHnd)
Get ordered pair of half-edges h0, h1
such that additionally h0 == h || h1 == h
and
PMesh.halfedges
— Methodfor (h1, h2) in halfedges(mesh)
...
end
Generate sequence all pairs of used half-edges.
PMesh.hasisolatedvertices
— MethodPMesh.hhnds
— Method[h for h in hhnds(mesh)]
Generate sequence of all –including unused – half-edge handles.
PMesh.isboundary
— Functionisboundary(mesh, v::VHnd)
isboundary(mesh, f::FHnd)
isboundary(mesh, h::HHnd)
isboundary(mesh, e::EHnd)
Is element a boundary element? (A face is a boundary face if any of its edges is boundary.)
PMesh.isclosed
— Methodisclosed(mesh; [allowisolated=false])
Is mesh
a closed surface without boundary loops or isolated vertices? Optionally ignore isolated vertices.
See also isboundary
, isisolated
PMesh.isfirsthalfedge
— Functionisfirsthalfedge([mesh,] h)
Helper to decide if
h == edge(h, 1)
or equivalently
h == first(halfedges(h))
PMesh.isinner
— Method isinner(mesh, v::VHnd[; allowisolated=false)
Is v
an interior vertex, i.e., neither an isolated vertex nor a boundary vertex. Optionally return true
also for isolated vertices.
See also isboundary
, isisolated
, ismanifold
PMesh.isisolated
— Methodisisolated(mesh, v)
Is vertex v
an isolated vertex, i.e., degree(mesh, v) == 0
or equivalently halfedge(mesh, v) == NoH
.
See also degree
PMesh.ismanifold
— Functionismanifold(mesh, v::VHnd)
ismanifold(mesh[; allowisolated=false)
Is mesh
locally manifold near vertex v
or globally a manifold surface mesh? Optionally ignore isolated vertices.
An isolated vertex is non-manifold. Meshes that contain isolated vertices are non-manifold. – The option allowisolated==true
ignores any manifold vertices.
These semantics differ from PMP!
See also hasisolatedvertices
PMesh.isquadmesh
— MethodPMesh.istrianglemesh
— Methodistrianglemesh(mesh)
Is the polygonal mesh
a triangle mesh, i.e., all faces have degree 3?
See also degree
PMesh.maxfacedegree
— Methodn = maxfacedegree(mesh)
Get maximum face degree, e.g., for n=4
the mesh consists of triangles and quads.
See also degree
, istrianglemesh
, isquadmesh
PMesh.ne
— Methodn = ne(mesh)
Get number of edges in mesh
.
PMesh.nf
— Methodn = nf(mesh)
Get number of faces in mesh
.
PMesh.nh
— Methodn = nh(mesh)
Get number of half-edges in mesh
.
PMesh.nv
— Methodn = nv(mesh)
Get number of vertices in mesh
.
PMesh.shrink!
— MethodSynonym for shrinkdisabled!
PMesh.vertices
— Methodfor v in vertices(mesh)
...
end
Generate sequence of all used vertices.
PMesh.vhnds
— Method[v for v in vhnds(mesh)]
Generate sequence of all – including unused – vertex handles.
PMeshAttributes.iscontiguous
— Functioniscontiguous(mesh, VHnd)
iscontiguous(mesh, FHnd)
iscontiguous(mesh, EHnd)
iscontiguous(mesh)
Are elements stored contiguously (i.e., number if used elements equals their total number)? The handle type restricts query to vertices, faces, edges or all elements. (Half-edges are stored contiguously iff edges are stored contiguously.)
See also Compact Storage
PMeshAttributes.isused
— Functionisused(mesh, v::VHnd)
isused(mesh, f::FHnd)
isused(mesh, h::HHnd)
isused(mesh, e::EHnd)
Determine if mesh element is used.
PMeshAttributes.shrinkdisabled!
— Method shrinkdisabled!(mesh)
Shrink arrary for disabled attributes to zero size.
Navigation
The basic navigation is provided by the half-edge data structure.
- map half-edge to
opposite
,next
orprev
ious in facenextinstar
or turncw
,previnstar
or turnccw
- get
face
from half-edge - get
source
anddestination
vertex from half-edge - find
halfedge
oredge
spanned by two vertices
PMesh.ccw
— MethodSynonym for previnstar
: turn counter-clockwise
PMesh.cw
— MethodSynonym for nextinstar
: turn clockwise
PMesh.destination
— Methodv = destination(mesh, h::HHnd)
Get destination vertex of h
: half-edge is incident to v
.
See also source
PMesh.edge
— Functione = edge(mesh, (v0, v1))
e = edge(mesh, v0, v1)
Find edge spanned by vertices v0
and v1
or return NoE
if there is no such edge.
See also halfedge
PMesh.face
— Methodf = face(mesh, h::HHnd)
Get face spanned by half-edge h
or NoH
if h
is boundary.
PMesh.halfedge
— Functionh = halfedge(mesh, (v0, v1))
h = halfedge(mesh, v0, v1)
Find half-edge from vertex v0
to vertex v1
or return NoH
if there is no such half-edge.
See also edge
PMesh.next
— Functionnh = next(mesh, h::HHnd[,:ccw]) # next
ph = next(mesh, h::Hnd, :cw) # previous
Get next half-edge within face in counter-clockwise (:ccw
) order. The next edge in clockwise order (cw
) equals is the previous edge.
See also prev
PMesh.nextinstar
— Functionnh = nextinstar(mesh[, :cw], h)
np = nextinstar(mesh, :ccw, h) # previnstar
Get next edge in star turning clockwise (:cw
) around source(h)
. The next edge when turning in counter-clockwise orientation (:ccw
) is equal to the previous edge previnstar
.
See also cw
, previnstar
PMesh.opposite
— Functionho = opposite(mesh, h::HHnd)
Get half-edge "opposite" to h
, i.e., with inverse orientation.
PMesh.prev
— Methodph = prev(mesh, h::HHnd)
Get previous half-edge within face (in counter-clockwise order).
See also next
PMesh.previnstar
— MethodPMesh.source
— Method