///|
/// New ids and the retained original edge after a local edge split.
pub(all) struct SplitReport {
vertex : Int
retained_edge : EdgeId
created_edges : Array[EdgeId]
created_faces : Array[Int]
} derive(Debug)
///|
pub extend SplitReport with @debug.Debug::{to_repr}
///| Split an edge; fraction is measured from edge_vertices().0 towards .1.
///|
/// All recoverable errors occur before mutation. Other element ids are retained.
pub fn Mesh::split_edge(
self : Mesh,
edge : EdgeId,
fraction? : Double = 0.5,
) -> SplitReport raise SurfaceError {
let (a, b) = self.edge_vertices(edge)
if !finite(fraction) || fraction <= 0.0 || fraction >= 1.0 {
raise InvalidArgument(
"split fraction must be strictly between zero and one",
)
}
let EdgeId(e) = edge
let h = if self.halfedges[2 * e].face >= 0 { 2 * e } else { 2 * e + 1 }
let t = opposite(h)
let boundary = self.halfedges[t].face < 0
let added_faces = if boundary { 1 } else { 2 }
if self.vertex_count() >= self.limits.max_vertices {
raise LimitExceeded("split vertices")
}
if self.face_count() + added_faces > self.limits.max_output_faces {
raise LimitExceeded("split faces")
}
let p = Vec3::{
x: lerp_scalar(self.vertices[a].x, self.vertices[b].x, fraction),
y: lerp_scalar(self.vertices[a].y, self.vertices[b].y, fraction),
z: lerp_scalar(self.vertices[a].z, self.vertices[b].z, fraction),
}
let u = self.halfedges[h].origin
let v = self.halfedges[t].origin
let ln = self.halfedges[h].next
let lp = self.halfedges[ln].next
let w = self.halfedges[lp].origin
if !finite(p.x) ||
!finite(p.y) ||
!finite(p.z) ||
degenerate(self.vertices[u], p, self.vertices[w]) ||
degenerate(p, self.vertices[v], self.vertices[w]) {
raise NumericalFailure("split would create degenerate geometry")
}
let rn = self.halfedges[t].next
let rp = self.halfedges[rn].next
let x = if boundary { -1 } else { self.halfedges[rp].origin }
if !boundary &&
(
degenerate(p, self.vertices[u], self.vertices[x]) ||
degenerate(self.vertices[v], p, self.vertices[x])
) {
raise NumericalFailure("split would create degenerate geometry")
}
let mut boundary_prev = -1
if boundary {
let mut current = ln
for _ in 0.. Double {
if (a >= 0.0 && b >= 0.0) || (a <= 0.0 && b <= 0.0) {
a + (b - a) * t
} else {
(1.0 - t) * a + t * b
}
}
///|
fn Mesh::append_edge(self : Mesh, a : Int, b : Int) -> Int {
let h = self.halfedges.length()
self.halfedges.push({ origin: a, next: -1, face: -1, })
self.halfedges.push({ origin: b, next: -1, face: -1, })
self.edge_lookup[edge_key(a, b)] = h / 2
h
}
///|
fn Mesh::set_triangle(
self : Mesh,
face : Int,
a : Int,
b : Int,
c : Int,
) -> Unit {
self.faces[face] = a
for (h, next) in [(a, b), (b, c), (c, a)] {
self.halfedges[h].face = face
self.halfedges[h].next = next
}
}