Skip to main content

HalfedgeMesh

Struct HalfedgeMesh 

Source
pub struct HalfedgeMesh { /* private fields */ }
Expand description

Halfedge (doubly-connected edge list) surface mesh of a 2-manifold, with or without boundary, with polygonal faces.

See the module documentation for the layout and the invariants. Navigation queries take ids of live elements; passing an id of a removed element returns stale data rather than panicking, and an id past the arrays panics like slice indexing. Edits check liveness and refuse by name.

Implementations§

Source§

impl HalfedgeMesh

Source

pub fn flip_edge(&mut self, e: EdgeId) -> Result<(), HalfedgeEditError>

Replace an edge between two triangles by the other diagonal of the quadrilateral they form. Counts, and so the Euler characteristic, are unchanged; the edge keeps its id.

§Errors

HalfedgeEditError::BoundaryEdge, HalfedgeEditError::NotATriangle, HalfedgeEditError::WouldDegenerate when the two opposite corners are one vertex, and HalfedgeEditError::EdgeExists when they are already joined.

Source

pub fn split_edge( &mut self, e: EdgeId, position: DVec3, ) -> Result<VertexId, HalfedgeEditError>

Insert a vertex at position on an edge and join it to the opposite corner of each adjacent triangle, so a triangle mesh stays a triangle mesh. A non-triangular adjacent face just gains a side. The Euler characteristic is unchanged.

The old edge keeps its id and runs from its original source to the new vertex.

§Errors

HalfedgeEditError::RemovedElement and HalfedgeEditError::TooLarge.

Source

pub fn collapse_edge( &mut self, h: HalfedgeId, ) -> Result<VertexId, HalfedgeEditError>

Collapse halfedge h by merging its source into its target, which keeps its id and position (move it with HalfedgeMesh::set_position). The incident triangles disappear and their remaining sides merge pairwise. Removes one vertex, three edges on an interior edge (two on a boundary edge) and the adjacent faces, so the Euler characteristic is unchanged.

§Errors

HalfedgeEditError::NotATriangle when a face around the removed vertex is not a triangle, HalfedgeEditError::LinkCondition when the collapse would pinch the surface, and HalfedgeEditError::WouldDegenerate for a tetrahedron, a lone triangle or a two-triangle pillow.

Source

pub fn split_face( &mut self, f: FaceId, position: DVec3, ) -> Result<VertexId, HalfedgeEditError>

Insert a vertex at position inside a face and fan the face into triangles around it, one per side. The face keeps its id as the triangle on its stored halfedge. The Euler characteristic is unchanged.

§Errors

HalfedgeEditError::RemovedElement and HalfedgeEditError::TooLarge.

Source

pub fn split_face_diagonal( &mut self, a: HalfedgeId, b: HalfedgeId, ) -> Result<HalfedgeId, HalfedgeEditError>

Split a face by a new edge from target(a) to target(b), two corners of the same face that are not already joined. Returns the new halfedge running from target(a) to target(b); it stays on the original face, which keeps a, and the other part becomes a new face. The Euler characteristic is unchanged.

This triangulates a polygon one diagonal at a time, for example a hole closed with HalfedgeMesh::fill_hole.

§Errors

HalfedgeEditError::NotSameFace (boundary halfedges included), HalfedgeEditError::AdjacentCorners, and HalfedgeEditError::EdgeExists when the corners are joined through another face.

Source

pub fn fill_hole(&mut self, h: HalfedgeId) -> Result<FaceId, HalfedgeEditError>

Close the hole bounded by boundary halfedge h with one new face. The Euler characteristic rises by one.

§Errors

HalfedgeEditError::NotBoundary when h already has a face.

Source§

impl HalfedgeMesh

Source

pub fn from_tri_mesh(mesh: &TriMesh) -> Result<HalfedgeMesh, HalfedgeBuildError>

Build from an indexed triangle mesh.

Vertex i is mesh.positions[i] and face j is triangle j. Normals and attribute channels are not carried: the halfedge mesh is connectivity plus positions.

§Errors

A ragged index buffer, an out-of-range or repeated corner, and every non-manifold or inconsistently wound configuration, each by name.

Source

pub fn from_faces<F>( positions: Vec<DVec3>, faces: &[F], ) -> Result<HalfedgeMesh, HalfedgeBuildError>
where F: AsRef<[u32]>,

Build from positions and polygonal faces, each a loop of position indices wound consistently with its neighbours.

§Errors

As HalfedgeMesh::from_tri_mesh, plus faces with fewer than three corners.

Source

pub fn to_tri_mesh(&self) -> Result<TriMesh, HalfedgeEditError>

Indexed triangle mesh of the live elements.

Live vertices keep their relative order, so a mesh that has had no vertex removed keeps its numbering; each triangle starts at its face’s stored halfedge, so building from a TriMesh and converting back reproduces its index buffer exactly.

§Errors

HalfedgeEditError::NotATriangle for the first face that is not a triangle; split it with HalfedgeMesh::split_face or HalfedgeMesh::split_face_diagonal first.

Source

pub fn vertex_count(&self) -> usize

Live vertices, including isolated ones.

Source

pub fn edge_count(&self) -> usize

Live edges.

Source

pub fn halfedge_count(&self) -> usize

Live halfedges: twice the edge count.

Source

pub fn face_count(&self) -> usize

Live faces.

Source

pub fn euler_characteristic(&self) -> i64

V - E + F over the live elements (isolated vertices count).

Source

pub fn contains_vertex(&self, v: VertexId) -> bool

Whether the vertex id names a live vertex.

Source

pub fn contains_edge(&self, e: EdgeId) -> bool

Whether the edge id names a live edge.

Source

pub fn contains_halfedge(&self, h: HalfedgeId) -> bool

Whether the halfedge id names a halfedge of a live edge.

Source

pub fn contains_face(&self, f: FaceId) -> bool

Whether the face id names a live face.

Source

pub fn vertices(&self) -> impl Iterator<Item = VertexId>

Live vertices in id order.

Source

pub fn edges(&self) -> impl Iterator<Item = EdgeId>

Live edges in id order.

Source

pub fn halfedges(&self) -> impl Iterator<Item = HalfedgeId>

Live halfedges in id order.

Source

pub fn faces(&self) -> impl Iterator<Item = FaceId>

Live faces in id order.

Source

pub fn boundary_halfedges(&self) -> impl Iterator<Item = HalfedgeId>

Live boundary halfedges in id order.

Source

pub fn boundary_loops(&self) -> Vec<HalfedgeId>

One boundary halfedge per hole, each the lowest id on its loop.

Source

pub fn position(&self, v: VertexId) -> DVec3

Position of a vertex.

Source

pub fn set_position(&mut self, v: VertexId, position: DVec3)

Move a vertex. Connectivity is untouched.

Source

pub fn positions(&self) -> &[DVec3]

The position array, indexed by vertex id (removed vertices included).

Source

pub fn next(&self, h: HalfedgeId) -> HalfedgeId

Next halfedge around the same face or hole.

Source

pub fn prev(&self, h: HalfedgeId) -> HalfedgeId

Previous halfedge around the same face or hole.

Source

pub const fn opposite(&self, h: HalfedgeId) -> HalfedgeId

The other halfedge of the same edge.

Source

pub fn target(&self, h: HalfedgeId) -> VertexId

Vertex the halfedge points to.

Source

pub fn source(&self, h: HalfedgeId) -> VertexId

Vertex the halfedge leaves.

Source

pub fn face(&self, h: HalfedgeId) -> Option<FaceId>

Face to the left of the halfedge; None on a boundary halfedge.

Source

pub const fn edge(&self, h: HalfedgeId) -> EdgeId

Edge owning the halfedge.

Source

pub fn edge_halfedge(&self, e: EdgeId, side: u32) -> HalfedgeId

One of the edge’s two halfedges: side 0 or 1.

§Panics

When side is greater than 1.

Source

pub fn edge_vertices(&self, e: EdgeId) -> [VertexId; 2]

Both endpoints of an edge, in the direction of its halfedge 2e.

Source

pub fn vertex_halfedge(&self, v: VertexId) -> Option<HalfedgeId>

Stored outgoing halfedge of a vertex; None when isolated.

For a boundary vertex it is the boundary halfedge leaving it.

Source

pub fn face_halfedge(&self, f: FaceId) -> HalfedgeId

Stored halfedge of a face’s loop.

Source

pub fn is_boundary_halfedge(&self, h: HalfedgeId) -> bool

Whether the halfedge has no face.

Source

pub fn is_boundary_edge(&self, e: EdgeId) -> bool

Whether either side of the edge is a boundary.

Source

pub fn is_boundary_vertex(&self, v: VertexId) -> bool

Whether the vertex lies on a hole. Isolated vertices are not boundary.

Source

pub fn is_isolated(&self, v: VertexId) -> bool

Whether the vertex has no incident edge.

Source

pub fn find_halfedge(&self, from: VertexId, to: VertexId) -> Option<HalfedgeId>

Halfedge from from to to, if the edge exists. O(degree).

Source

pub fn outgoing_halfedges( &self, v: VertexId, ) -> impl Iterator<Item = HalfedgeId>

Outgoing halfedges of a vertex in counter-clockwise order (seen with faces wound counter-clockwise), starting at the stored halfedge, so a boundary vertex starts at its boundary halfedge.

Source

pub fn incoming_halfedges( &self, v: VertexId, ) -> impl Iterator<Item = HalfedgeId>

Incoming halfedges of a vertex, the opposites of HalfedgeMesh::outgoing_halfedges in the same order.

Source

pub fn vertex_vertices(&self, v: VertexId) -> impl Iterator<Item = VertexId>

Neighbouring vertices in counter-clockwise order.

Source

pub fn vertex_faces(&self, v: VertexId) -> impl Iterator<Item = FaceId>

Faces around a vertex in counter-clockwise order, holes skipped.

Source

pub fn degree(&self, v: VertexId) -> usize

Number of edges at a vertex. O(degree).

Source

pub fn loop_halfedges(&self, h: HalfedgeId) -> impl Iterator<Item = HalfedgeId>

Halfedges of the loop containing h (a face or a hole), from h.

Source

pub fn face_halfedges(&self, f: FaceId) -> impl Iterator<Item = HalfedgeId>

Halfedges of a face’s loop, from its stored halfedge.

Source

pub fn face_vertices(&self, f: FaceId) -> impl Iterator<Item = VertexId>

Corners of a face in winding order, starting at the source of its stored halfedge.

Source

pub fn face_faces(&self, f: FaceId) -> impl Iterator<Item = Option<FaceId>>

Faces across each edge of a face, None across a boundary.

Source

pub fn face_degree(&self, f: FaceId) -> usize

Number of sides of a face. O(degree).

Source

pub fn compact(&mut self) -> HalfedgeRemap

Renumber live elements densely in their current order and drop the removed ones. Returns the old-to-new mapping so per-element data held by a caller can follow.

Source

pub fn validate(&self) -> Result<(), HalfedgeInvariantError>

Check every structural invariant listed in the module documentation. O(halfedges).

§Errors

The first violated invariant found.

Trait Implementations§

Source§

impl Clone for HalfedgeMesh

Source§

fn clone(&self) -> HalfedgeMesh

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for HalfedgeMesh

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for HalfedgeMesh

Source§

fn eq(&self, other: &HalfedgeMesh) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for HalfedgeMesh

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.