use crate::{Adjacency, KernelError, LineageMaps, Mesh, SchemeOptions, StencilTable, VertexOrigin};
use crate::sharpness::decay_sharpness;
use super::super::topology::{build_topology, edge_key};
use super::level::{Sqrt3LevelData, compute_effective_edge_creases};
use super::points::vertex_point_stencil;
use super::sparse::{Sparse, pack};
pub(crate) fn refine_topology_once(
parent: &Sqrt3LevelData,
options: &SchemeOptions,
selection_boundary_crease: f32,
) -> Result<Sqrt3LevelData, KernelError> {
let topology = &parent.topo;
let face_selected = &parent.face_selected;
let effective_edge_creases = &parent.effective_edge_creases;
let topo_mesh = &parent.mesh;
let vertex_count = topo_mesh.vertex_count as usize;
let edge_count = topology.edge_vertices.len();
let face_count = topology.faces.len();
let cp_idx = |fi: usize| fi as u32;
let vp_idx = |vi: usize| (face_count + vi) as u32;
let mut new_faces: Vec<Vec<u32>> = Vec::new();
let mut face_parent: Vec<u32> = Vec::new();
let mut new_face_selected: Vec<bool> = Vec::new();
let mut parent_edge_children: Vec<Vec<(usize, usize)>> = vec![Vec::new(); edge_count];
(0..face_count).for_each(|fi| {
let fv = topology.faces.row(fi);
if face_selected[fi] {
(0..3).for_each(|i| {
let child_fi = new_faces.len();
let v_cur = fv[i];
let v_next = fv[(i + 1) % 3];
new_faces.push(vec![
cp_idx(fi),
vp_idx(v_cur as usize),
vp_idx(v_next as usize),
]);
face_parent.push(fi as u32);
new_face_selected.push(true);
let fe_i = topology.face_edges.get(fi, i) as usize;
parent_edge_children[fe_i].push((child_fi, 1));
});
} else {
new_faces.push(fv.iter().map(|&v| vp_idx(v as usize)).collect());
face_parent.push(fi as u32);
new_face_selected.push(false);
}
});
(0..edge_count).for_each(|ei| {
if topology.edge_is_boundary[ei] || effective_edge_creases[ei] >= 1.0 {
return;
}
let ef = topology.edge_faces.row(ei);
if ef.len() < 2 || !face_selected[ef[0] as usize] || !face_selected[ef[1] as usize] {
return;
}
let children = &parent_edge_children[ei];
if children.len() != 2 {
return;
}
let (cf0, _edge_pos_0) = children[0];
let (cf1, _edge_pos_1) = children[1];
let [v0, v1] = topology.edge_vertices[ei];
let vp0 = vp_idx(v0 as usize);
let vp1 = vp_idx(v1 as usize);
let centroid_0 = new_faces[cf0]
.iter()
.find(|&&v| v != vp0 && v != vp1)
.copied();
let centroid_1 = new_faces[cf1]
.iter()
.find(|&&v| v != vp0 && v != vp1)
.copied();
if let (Some(c0), Some(c1)) = (centroid_0, centroid_1) {
new_faces[cf0] = vec![c0, c1, vp0];
new_faces[cf1] = vec![c0, vp1, c1];
}
});
let total_verts = (face_count + vertex_count) as u32;
let mut fvc = Vec::with_capacity(new_faces.len());
let mut fvi = Vec::new();
new_faces.iter().for_each(|f| {
fvc.push(f.len() as u32);
fvi.extend(f.iter().copied());
});
let post_flip_topo = Mesh {
vertex_count: total_verts,
face_vertex_counts: fvc.clone(),
face_vertex_indices: fvi.clone(),
edge_vertices: Vec::new(),
edge_creases: Vec::new(),
vertex_corners: vec![0.0; total_verts as usize],
};
let post_flip_analysis = build_topology(&post_flip_topo)?;
let mut refined_creases = vec![0.0f32; post_flip_analysis.edge_vertices.len()];
let mut edge_parent_map = vec![u32::MAX; post_flip_analysis.edge_vertices.len()];
topology
.edge_vertices
.iter()
.copied()
.enumerate()
.filter(|(ei, _)| effective_edge_creases[*ei] > 0.0)
.for_each(|(ei, [v0, v1])| {
let child_crease = if options.crease_normalize {
effective_edge_creases[ei]
} else {
decay_sharpness(effective_edge_creases[ei])
};
if child_crease <= 0.0 {
return;
}
let key = edge_key(vp_idx(v0 as usize), vp_idx(v1 as usize));
if let Some(&nei) = post_flip_analysis.edge_key_to_index.get(&key) {
refined_creases[nei] = child_crease;
edge_parent_map[nei] = ei as u32;
}
});
let refined_corners: Vec<f32> = std::iter::repeat(0.0)
.take(face_count)
.chain(topo_mesh.vertex_corners.iter().map(|&c| {
if options.corner_normalize || c <= 0.0 {
c
} else {
decay_sharpness(c)
}
}))
.collect();
let refined_mesh = Mesh {
vertex_count: total_verts,
face_vertex_counts: fvc,
face_vertex_indices: fvi,
edge_vertices: post_flip_analysis.edge_vertices.clone(),
edge_creases: refined_creases,
vertex_corners: refined_corners,
};
let mut vertex_origin = Vec::with_capacity(total_verts as usize);
vertex_origin.extend((0..face_count).map(|i| VertexOrigin::Face(i as u32)));
vertex_origin.extend((0..vertex_count).map(|i| VertexOrigin::Vertex(i as u32)));
let lineage = LineageMaps {
vertex_origin,
face_parent,
edge_parent: edge_parent_map,
};
let adjacency = {
let (_, face_edges) = post_flip_analysis.face_edges.clone().into_parts();
let edge_faces: Vec<[u32; 2]> = (0..post_flip_analysis.edge_vertices.len())
.map(|ei| {
let ef = post_flip_analysis.edge_faces.row(ei);
match ef.len() {
0 => [u32::MAX, u32::MAX],
1 => [ef[0], u32::MAX],
_ => [ef[0], ef[1]],
}
})
.collect();
let edge_is_boundary: Vec<bool> = edge_faces.iter().map(|ef| ef[1] == u32::MAX).collect();
let vertex_count_post = post_flip_analysis.vertex_edges.len();
let mut vertex_is_boundary = vec![false; vertex_count_post];
for vi in 0..vertex_count_post {
if post_flip_analysis
.vertex_edges
.row(vi)
.iter()
.any(|&ei| edge_is_boundary[ei as usize])
{
vertex_is_boundary[vi] = true;
}
}
let (vertex_edge_offsets, vertex_edges) = post_flip_analysis.vertex_edges.clone().into_parts();
let (vertex_face_offsets, vertex_faces) = post_flip_analysis.vertex_faces.clone().into_parts();
Adjacency {
face_edges,
edge_faces,
vertex_edge_offsets,
vertex_edges,
vertex_face_offsets,
vertex_faces,
edge_is_boundary,
vertex_is_boundary,
}
};
let child_effective_edge_creases = compute_effective_edge_creases(
&post_flip_analysis,
&new_face_selected,
selection_boundary_crease,
);
Ok(Sqrt3LevelData {
mesh: refined_mesh,
topo: post_flip_analysis,
face_selected: new_face_selected,
effective_edge_creases: child_effective_edge_creases,
lineage,
adjacency,
})
}
pub(crate) fn vertex_stencils_from_level(
parent: &Sqrt3LevelData,
options: &SchemeOptions,
) -> StencilTable {
let topology = &parent.topo;
let vertex_count = parent.mesh.vertex_count as usize;
let face_count = topology.faces.len();
let centroid_stencils: Vec<Sparse> = (0..face_count)
.map(|fi| {
let fv = topology.faces.row(fi);
let w = 1.0 / fv.len() as f32;
fv.iter().map(|&v| (v, w)).collect()
})
.collect();
let vp_stencils: Vec<Sparse> = (0..vertex_count)
.map(|vi| {
vertex_point_stencil(
vi,
topology,
&parent.mesh.vertex_corners,
options,
&parent.face_selected,
&parent.effective_edge_creases,
¢roid_stencils,
)
})
.collect();
let mut all_stencils = Vec::with_capacity(face_count + vertex_count);
all_stencils.extend(centroid_stencils);
all_stencils.extend(vp_stencils);
pack(&all_stencils)
}