use honeycomb_core::{
cmap::{CMap2, DartIdType, EdgeIdType, SewError},
geometry::{CoordsFloat, Vertex2},
stm::{Transaction, TransactionClosureResult, try_or_coerce, unwrap_or_retry},
};
use crate::utils::{EdgeAnchor, FaceAnchor, VertexAnchor};
#[inline]
pub fn cut_outer_edge<T: CoordsFloat>(
t: &mut Transaction,
map: &CMap2<T>,
e: EdgeIdType,
[nd1, nd2, nd3]: [DartIdType; 3],
) -> TransactionClosureResult<(), SewError> {
try_or_coerce!(map.link_tx::<2>(t, nd1, nd2), SewError);
try_or_coerce!(map.link_tx::<1>(t, nd2, nd3), SewError);
let f_anchor = if map.contains_attribute::<FaceAnchor>() {
let fid = map.face_id_tx(t, e)?;
map.remove_attribute_tx::<FaceAnchor>(t, fid)?
} else {
None
};
let e_anchor = if map.contains_attribute::<EdgeAnchor>() {
map.read_attribute_tx::<EdgeAnchor>(t, e)?
} else {
None
};
let ld = e as DartIdType;
let (b0ld, b1ld) = (map.beta_tx::<0>(t, ld)?, map.beta_tx::<1>(t, ld)?);
let (vid1, vid2) = (map.vertex_id_tx(t, ld)?, map.vertex_id_tx(t, b1ld)?);
let new_v = Vertex2::average(
&unwrap_or_retry(map.read_vertex_tx(t, vid1)?)?,
&unwrap_or_retry(map.read_vertex_tx(t, vid2)?)?,
);
map.write_vertex_tx(t, nd1, new_v)?;
map.unsew_tx::<1>(t, ld)?;
map.unsew_tx::<1>(t, b1ld)?;
map.sew_tx::<1>(t, ld, nd1)?;
map.sew_tx::<1>(t, nd1, b0ld)?;
map.sew_tx::<1>(t, nd3, b1ld)?;
map.sew_tx::<1>(t, b1ld, nd2)?;
if let Some(a) = f_anchor {
let fid1 = map.face_id_tx(t, nd1)?;
let fid2 = map.face_id_tx(t, nd2)?;
map.write_attribute_tx(t, fid1, a)?;
map.write_attribute_tx(t, fid2, a)?;
if map.contains_attribute::<EdgeAnchor>() {
let eid = map.edge_id_tx(t, nd1)?;
map.write_attribute_tx(t, eid, EdgeAnchor::from(a))?;
}
}
if let Some(a) = e_anchor {
let vid = map.vertex_id_tx(t, nd1)?;
map.write_attribute_tx(t, vid, VertexAnchor::from(a))?;
map.write_attribute_tx(t, nd3 as EdgeIdType, a)?;
}
Ok(())
}
#[inline]
pub fn cut_inner_edge<T: CoordsFloat>(
t: &mut Transaction,
map: &CMap2<T>,
e: EdgeIdType,
[nd1, nd2, nd3, nd4, nd5, nd6]: [DartIdType; 6],
) -> TransactionClosureResult<(), SewError> {
try_or_coerce!(map.link_tx::<2>(t, nd1, nd2), SewError);
try_or_coerce!(map.link_tx::<1>(t, nd2, nd3), SewError);
try_or_coerce!(map.link_tx::<2>(t, nd4, nd5), SewError);
try_or_coerce!(map.link_tx::<1>(t, nd5, nd6), SewError);
let (ld, rd) = (e as DartIdType, map.beta_tx::<2>(t, e as DartIdType)?);
let lf_anchor = if map.contains_attribute::<FaceAnchor>() {
let fid = map.face_id_tx(t, ld)?;
map.remove_attribute_tx::<FaceAnchor>(t, fid)?
} else {
None
};
if let Some(a) = lf_anchor
&& map.contains_attribute::<EdgeAnchor>()
{
let eid = map.edge_id_tx(t, nd1)?;
map.write_attribute_tx(t, eid, EdgeAnchor::from(a))?;
}
let rf_anchor = if map.contains_attribute::<FaceAnchor>() {
let fid = map.face_id_tx(t, rd)?;
map.remove_attribute_tx::<FaceAnchor>(t, fid)?
} else {
None
};
if let Some(a) = rf_anchor
&& map.contains_attribute::<EdgeAnchor>()
{
let eid = map.edge_id_tx(t, nd4)?;
map.write_attribute_tx(t, eid, EdgeAnchor::from(a))?;
}
if map.contains_attribute::<EdgeAnchor>()
&& let Some(a) = map.read_attribute_tx::<EdgeAnchor>(t, e)?
{
let vid1 = map.vertex_id_tx(t, nd1)?;
let vid2 = map.vertex_id_tx(t, nd4)?;
map.write_attribute_tx(t, vid1, VertexAnchor::from(a))?;
map.write_attribute_tx(t, vid2, VertexAnchor::from(a))?;
}
let (b0ld, b1ld) = (map.beta_tx::<0>(t, ld)?, map.beta_tx::<1>(t, ld)?);
let (b0rd, b1rd) = (map.beta_tx::<0>(t, rd)?, map.beta_tx::<1>(t, rd)?);
let (vid1, vid2) = (map.vertex_id_tx(t, ld)?, map.vertex_id_tx(t, b1ld)?);
let new_v = Vertex2::average(
&unwrap_or_retry(map.read_vertex_tx(t, vid1)?)?,
&unwrap_or_retry(map.read_vertex_tx(t, vid2)?)?,
);
map.write_vertex_tx(t, nd1, new_v)?;
map.unsew_tx::<2>(t, ld)?;
map.unsew_tx::<1>(t, ld)?;
map.unsew_tx::<1>(t, b1ld)?;
map.unsew_tx::<1>(t, rd)?;
map.unsew_tx::<1>(t, b1rd)?;
map.sew_tx::<2>(t, ld, nd6)?;
map.sew_tx::<2>(t, rd, nd3)?;
map.sew_tx::<1>(t, ld, nd1)?;
map.sew_tx::<1>(t, nd1, b0ld)?;
map.sew_tx::<1>(t, nd3, b1ld)?;
map.sew_tx::<1>(t, b1ld, nd2)?;
map.sew_tx::<1>(t, rd, nd4)?;
map.sew_tx::<1>(t, nd4, b0rd)?;
map.sew_tx::<1>(t, nd6, b1rd)?;
map.sew_tx::<1>(t, b1rd, nd5)?;
if let Some(a) = lf_anchor {
let fid1 = map.face_id_tx(t, nd1)?;
let fid2 = map.face_id_tx(t, nd2)?;
map.write_attribute_tx(t, fid1, a)?;
map.write_attribute_tx(t, fid2, a)?;
}
if let Some(a) = rf_anchor {
let fid4 = map.face_id_tx(t, nd4)?;
let fid5 = map.face_id_tx(t, nd5)?;
map.write_attribute_tx(t, fid4, a)?;
map.write_attribute_tx(t, fid5, a)?;
}
Ok(())
}