///| One uniform Loop step, using the old mesh for every stencil.
///|
/// The result owns new storage and retains the original mesh's configured limits.
pub fn Mesh::loop_step(self : Mesh) -> Mesh raise SurfaceError {
if self.limits.max_levels < 1 {
raise LimitExceeded("Loop levels")
}
let count = self.vertex_count() + self.edge_count()
if count > self.limits.max_vertices {
raise LimitExceeded("Loop vertices")
}
if self.face_count() * 4 > self.limits.max_output_faces {
raise LimitExceeded("Loop faces")
}
let boundary : Array[(Int, Int)?] = Array::make(self.vertex_count(), None)
for ring in self.boundary_loops() {
let n = ring.length()
for i, v in ring {
boundary[v] = Some((ring[(i + n - 1) % n], ring[(i + 1) % n]))
}
}
let positions : Array[Vec3] = []
for v in 0.. [(v, 0.75), (a, 0.125), (b, 0.125)]
None => {
let n = self.degrees[v]
let c = 0.375 + 0.25 * @math.cos(6.283185307179586 / n.to_double())
let beta = (0.625 - c * c) / n.to_double()
let entries = [(v, 1.0 - n.to_double() * beta)]
for other in self.neighbors(v) {
entries.push((other, beta))
}
entries
}
}
positions.push(weighted_position(self.vertices, stencil))
}
for e in 0.. Vec3 {
let mut scale = 0.0
for (v, _) in stencil {
let p = points[v]
scale = Double::max(
scale,
Double::max(abs(p.x), Double::max(abs(p.y), abs(p.z))),
)
}
if scale == 0.0 {
return { x: 0.0, y: 0.0, z: 0.0, }
}
let mut x = 0.0
let mut y = 0.0
let mut z = 0.0
for (v, weight) in stencil {
x += points[v].x / scale * weight
y += points[v].y / scale * weight
z += points[v].z / scale * weight
}
// Roundoff cannot move a convex combination beyond the input coordinate bound.
{
x: Double::max(-1.0, Double::min(1.0, x)) * scale,
y: Double::max(-1.0, Double::min(1.0, y)) * scale,
z: Double::max(-1.0, Double::min(1.0, z)) * scale,
}
}