Skip to main content

honeycomb_kernels/utils/
routines.rs

1use honeycomb_core::{
2    cmap::{CMap2, DartIdType, OrbitPolicy, VertexIdType},
3    geometry::{CoordsFloat, Vertex2},
4    stm::{StmClosureResult, Transaction, unwrap_or_retry},
5};
6use smallvec::SmallVec;
7
8/// Check if all faces incident to the vertex have the same orientation.
9///
10/// Note that this function expects the incident faces to be triangles.
11///
12/// # Errors
13///
14/// This method is meant to be called in a context where the returned `Result` is used to
15/// validate the transaction passed as argument. Errors should not be processed manually,
16/// only processed via the `?` operator.
17pub fn is_orbit_orientation_consistent<T: CoordsFloat>(
18    t: &mut Transaction,
19    map: &CMap2<T>,
20    vid: VertexIdType,
21) -> StmClosureResult<bool> {
22    let mut tmp: SmallVec<DartIdType, 10> = SmallVec::new();
23    for d in map.orbit_tx(t, OrbitPolicy::Vertex, vid) {
24        tmp.push(d?);
25    }
26    let new_v = unwrap_or_retry(map.read_vertex(t, vid)?)?;
27
28    let ref_crossp = {
29        let d = tmp[0];
30        let b1d = map.beta_tx::<1>(t, d)?;
31        let b1b1d = map.beta_tx::<1>(t, b1d)?;
32        let vid1 = map.vertex_id_tx(t, b1d)?;
33        let vid2 = map.vertex_id_tx(t, b1b1d)?;
34        let v1 = unwrap_or_retry(map.read_vertex(t, vid1)?)?;
35        let v2 = unwrap_or_retry(map.read_vertex(t, vid2)?)?;
36
37        Vertex2::cross_product_from_vertices(&new_v, &v1, &v2)
38    };
39    if ref_crossp.is_zero() {
40        return Ok(false);
41    }
42
43    let ref_sign = ref_crossp.signum();
44    for &d in &tmp[1..] {
45        let b1d = map.beta_tx::<1>(t, d)?;
46        let b1b1d = map.beta_tx::<1>(t, b1d)?;
47        let vid1 = map.vertex_id_tx(t, b1d)?;
48        let vid2 = map.vertex_id_tx(t, b1b1d)?;
49        let v1 = unwrap_or_retry(map.read_vertex(t, vid1)?)?;
50        let v2 = unwrap_or_retry(map.read_vertex(t, vid2)?)?;
51
52        let crossp = Vertex2::cross_product_from_vertices(&new_v, &v1, &v2);
53
54        if ref_sign != crossp.signum() || crossp.is_zero() {
55            return Ok(false);
56        }
57    }
58
59    Ok(true)
60}