use crate::*;
pub fn verify_correctness<C: MeshStorage, const M: bool>(
mesh: &PolyHedron<C, M>,
) -> Result<(), String>
{
if unsafe { (*mesh.mesh_data.get()).geometry_data.vert_data.len() }
!= unsafe { (*mesh.mesh_data.get()).topology_data.topo_verts.len() }
{
return Err(format!(
"Vertex data count does not match topological vertex count."
));
}
let edge_data_len = unsafe { (*mesh.mesh_data.get()).geometry_data.edge_data.len() };
if edge_data_len != 0
{
let topo_edges = if M
{
let topo_edge_count =
unsafe { (*mesh.mesh_data.get()).topology_data.topo_half_edges.len() };
topo_edge_count / 2
}
else
{
let topo_edge_count =
unsafe { (*mesh.mesh_data.get()).topology_data.topo_edges.len() };
topo_edge_count
};
if topo_edges != edge_data_len
{
return Err(format!(
"Edge data count does not match topological edge count."
));
}
}
let face_data_len = unsafe { (*mesh.mesh_data.get()).geometry_data.face_data.len() };
if face_data_len != 0
{
let topo_face_count =
unsafe { (*mesh.mesh_data.get()).topology_data.topo_faces.len() };
if topo_face_count != face_data_len
{
return Err(format!(
"Face data count does not match topological face count."
));
}
}
for vert_index in 0..mesh.vert_count()
{
let vert = unsafe { (*mesh.mesh_data.get()).vert_ref(VertId::new(vert_index)) };
if vert.id.is_void()
{
continue;
}
let active_vid = vert.id;
if !M
{
let edge_id = vert.arc.to_edge_id();
if !edge_id.is_void()
{
let edge = unsafe { (*mesh.mesh_data.get()).edge_ref(edge_id) };
if !edge.endpoints.iter().any(|vid| *vid == active_vid)
{
return Err(format!(
"Vertex at index {} points to edge {} but the edge doesn't point back to it.",
vert_index, edge_id
));
}
}
}
}
for edge_index in 0..unsafe { (*mesh.mesh_data.get()).edge_count() * (!M as usize) }
{
let edge = unsafe { (*mesh.mesh_data.get()).edge_ref(EdgeId::new(edge_index)) };
let id = edge.id;
let endpoints = edge.endpoints;
let cycles = edge.endpoint_cycles;
let half_edge = edge.half_edge;
if id.is_void()
{
continue;
}
if endpoints.iter().any(|vid| vid.is_void())
{
return Err(format!(
"Edge at index {} has an void endpoint [{} {}].",
edge_index, endpoints[0], endpoints[1]
));
}
if cycles[0].prev.is_void() || cycles[0].next.is_void()
{
return Err(format!(
"Edge at index {} has a broken cycle [p: {}, n: {}].",
edge_index, cycles[0].prev, cycles[0].next
));
}
if cycles[1].prev.is_void() || cycles[1].next.is_void()
{
return Err(format!(
"Edge at index {} has a broken cycle [p: {}, n: {}].",
edge_index, cycles[1].prev, cycles[1].next
));
}
for (i, prev_id) in [cycles[0].prev, cycles[1].prev].into_iter().enumerate()
{
let prev_edge = unsafe { (*mesh.mesh_data.get()).edge_ref(prev_id) };
let next = prev_edge.cycle_at(endpoints[i]).unwrap().next;
if next != id
{
return Err(format!(
"Edge at index {} points to a previous edge {} that doesn't point back to it.",
edge_index, prev_id
));
}
}
for (i, next_id) in [cycles[0].next, cycles[1].next].into_iter().enumerate()
{
let next_edge = unsafe { (*mesh.mesh_data.get()).edge_ref(next_id) };
let prev = next_edge.cycle_at(endpoints[i]).unwrap().prev;
if prev != id
{
return Err(format!(
"Edge at index {} points to a next edge {} that doesn't point back to it.",
edge_index, next_id
));
}
}
let hedge = unsafe { (*mesh.mesh_data.get()).half_edge_ref(half_edge) };
if hedge.edge != id
{
return Err(format!(
"Edge at index {} points to a half edge {} that doesn't point back to it.",
edge_index, hedge.edge
));
}
}
for half_edge_index in 0..unsafe { (*mesh.mesh_data.get()).half_edge_count() }
{
let half_edge = unsafe {
(*mesh.mesh_data.get()).half_edge_ref(HalfEdgeId::new(half_edge_index))
};
let id = half_edge.id;
let source = half_edge.source;
let orbit_next = half_edge.orbit_next;
let face_next = half_edge.face_next;
let face_prev = half_edge.face_prev;
let edge = half_edge.edge;
if id.is_void()
{
continue;
}
if source.is_void()
{
return Err(format!(
"Half edge at index {} has a void source.",
half_edge_index
));
}
if orbit_next.is_void()
{
return Err(format!(
"Half edge at index {} has a void next orbit.",
half_edge_index
));
}
if face_next.is_void()
{
return Err(format!(
"Half edge at index {} has a void face next.",
half_edge_index
));
}
let next_face = unsafe { (*mesh.mesh_data.get()).half_edge_ref(face_next) };
let prev_id = next_face.face_prev;
if prev_id != id
{
return Err(format!(
"Half edge at index {} points to next in face half edge {}, who's prev is {}.",
half_edge_index, next_face.id, next_face.face_prev
));
}
if face_prev.is_void()
{
return Err(format!(
"Half edge at index {} has a void face prev.",
half_edge_index
));
}
let prev_face = unsafe { (*mesh.mesh_data.get()).half_edge_ref(face_prev) };
let prev_id = prev_face.face_next;
if prev_id != id
{
return Err(format!(
"Half edge at index {} points to prev in face half edge {}, who's next is {}.",
half_edge_index, prev_face.id, prev_face.face_next
));
}
if !M
{
if edge.is_void()
{
return Err(format!(
"Half edge at index {} points to a void edge",
half_edge_index,
));
}
}
}
for face_index in 0..unsafe { (*mesh.mesh_data.get()).face_count() }
{
let face = unsafe { (*mesh.mesh_data.get()).face_ref(FaceId::new(face_index)) };
if face.id.is_void()
{
continue;
}
let id = face.id;
let hedge = face.half_edge;
if hedge.is_void()
{
return Err(format!(
"Face at index {} points to a void half edge.",
face_index,
));
}
let fid = unsafe { (*mesh.mesh_data.get()).half_edge_ref(hedge).face };
if fid != id
{
return Err(format!(
"Face at index {} points to half edge {} that doesn't point back to it.",
face_index, hedge
));
}
let mut current_edge = hedge;
let starting_edge = current_edge;
let mut safety_counter = 0;
loop
{
safety_counter += 1;
if safety_counter > 500
{
return Err(format!(
"Face {} has an edge cycle with over 500 elements, not strictly an error but highly suspicious, check was short circuited.",
face_index,
));
}
let hedge = unsafe { (*mesh.mesh_data.get()).half_edge_ref(current_edge) };
if hedge.face != id
{
return Err(format!(
"Face at index {} points to half edge {} that doesn't point back to it.",
face_index, hedge.id
));
}
current_edge = hedge.face_next;
if current_edge == starting_edge
{
break;
}
}
}
Ok(())
}