use honeycomb_core::cmap::{CMap2, DartIdType, EdgeIdType, NULL_DART_ID};
use honeycomb_core::geometry::CoordsFloat;
use rustc_hash::FxHashMap as HashMap;
use super::{DartSlices, IntersectionsPerEdge};
pub(crate) fn group_intersections_per_edge<T: CoordsFloat>(
cmap: &mut CMap2<T>,
intersection_metadata: Vec<(DartIdType, T)>,
) -> (IntersectionsPerEdge<T>, DartSlices) {
let mut edge_intersec: HashMap<EdgeIdType, Vec<(usize, T, DartIdType)>> = HashMap::default();
intersection_metadata
.into_iter()
.filter(|(_, t)| !t.is_nan())
.enumerate()
.for_each(|(idx, (dart_id, mut t))| {
let edge_id = cmap.edge_id(dart_id);
if edge_id != dart_id {
t = T::one() - t;
}
if let Some(storage) = edge_intersec.get_mut(&edge_id) {
storage.push((idx, t, dart_id));
} else {
edge_intersec.insert(edge_id, vec![(idx, t, dart_id)]);
}
});
for vs in edge_intersec.values_mut() {
vs.sort_by(|(_, t1, _), (_, t2, _)| t1.partial_cmp(t2).expect("E: unreachable"));
}
let n_darts_per_seg: Vec<_> = edge_intersec.values().map(|vs| 2 * vs.len()).collect();
let n_tot: usize = n_darts_per_seg.iter().sum();
let tmp = cmap.allocate_used_darts(n_tot) as usize;
let prefix_sum: Vec<usize> = n_darts_per_seg
.iter()
.scan(0, |state, &n_d| {
*state += n_d;
Some(*state - n_d) })
.collect();
#[allow(clippy::cast_possible_truncation)]
let dart_slices: Vec<Vec<DartIdType>> = n_darts_per_seg
.iter()
.zip(prefix_sum.iter())
.map(|(n_d, start)| {
((tmp + start) as DartIdType..(tmp + start + n_d) as DartIdType).collect::<Vec<_>>()
})
.collect();
(edge_intersec, dart_slices)
}
pub(crate) fn compute_intersection_ids<T: CoordsFloat>(
n_intersec: usize,
edge_intersec: &IntersectionsPerEdge<T>,
dart_slices: &DartSlices,
) -> Vec<DartIdType> {
let mut res = vec![NULL_DART_ID; n_intersec];
for ((edge_id, vs), new_darts) in edge_intersec.iter().zip(dart_slices.iter()) {
let hl = new_darts.len() / 2; let fh = &new_darts[..hl]; let sh = &new_darts[hl..]; for (i, (id, _, old_dart_id)) in vs.iter().enumerate() {
res[*id] = if *old_dart_id == *edge_id {
fh[i]
} else {
sh[hl - 1 - i]
};
}
}
res
}