use crate::mesh::{Edge, EdgeKey, MapEdge2dToCells, Mesh, PointId};
use russell_lab::sort2;
use std::collections::{HashMap, HashSet};
pub(crate) fn extract_features_2d(
mesh: &Mesh,
all_2d_edges: &MapEdge2dToCells,
extract_all: bool,
) -> (HashSet<PointId>, HashMap<EdgeKey, Edge>, Vec<f64>, Vec<f64>) {
assert_eq!(mesh.ndim, 2);
let mut marked_edges_map = HashMap::new();
mesh.marked_edges.iter().for_each(|(marker, p1, p2)| {
let mut edge_key = (*p1, *p2);
sort2(&mut edge_key);
marked_edges_map.insert(edge_key, *marker);
});
let mut points = HashSet::new();
let mut edges = HashMap::new();
let mut min = vec![f64::MAX; mesh.ndim];
let mut max = vec![f64::MIN; mesh.ndim];
for (edge_key, shared_by) in all_2d_edges {
let accept = if extract_all {
true
} else {
shared_by.len() == 1 };
if !accept {
continue;
}
let (cell_id, e) = shared_by[0];
let cell = &mesh.cells[cell_id];
let mut edge = Edge {
kind: cell.kind.edge_kind().unwrap(),
points: vec![0; cell.kind.edge_nnode()],
marker: marked_edges_map.get(edge_key).cloned().unwrap_or(0),
};
for i in 0..edge.points.len() {
edge.points[i] = cell.points[cell.kind.edge_node_id(e, i)];
points.insert(edge.points[i]);
for j in 0..mesh.ndim {
min[j] = f64::min(min[j], mesh.points[edge.points[i]].coords[j]);
max[j] = f64::max(max[j], mesh.points[edge.points[i]].coords[j]);
}
}
edges.insert(*edge_key, edge);
}
(points, edges, min, max)
}
#[cfg(test)]
mod tests {
use super::extract_features_2d;
use crate::mesh::algorithms::extract_all_2d_edges;
use crate::mesh::{Edge, EdgeKey, PointId, Samples};
use crate::util::AsArray2D;
use russell_lab::array_approx_eq;
use std::collections::HashMap;
fn validate_edges<'a, T>(
edges: &HashMap<EdgeKey, Edge>,
correct_keys: &[EdgeKey], correct_points: &'a T,
) where
T: AsArray2D<'a, PointId>,
{
let mut keys: Vec<_> = edges.keys().map(|k| *k).collect();
keys.sort();
assert_eq!(keys, correct_keys);
for i in 0..keys.len() {
assert_eq!(edges.get(&keys[i]).unwrap().points, correct_points.row(i));
}
}
#[test]
fn extract_features_2d_works() {
let mesh = Samples::two_qua4();
let all_2d_edges = extract_all_2d_edges(&mesh);
let (points, edges, min, max) = extract_features_2d(&mesh, &all_2d_edges, false);
let correct_keys = [(0, 1), (0, 3), (1, 4), (2, 3), (2, 5), (4, 5)];
let correct_points = [[1, 0], [0, 3], [4, 1], [3, 2], [2, 5], [5, 4]];
validate_edges(&edges, &correct_keys, &correct_points);
assert_eq!(min, &[0.0, 0.0]);
assert_eq!(max, &[2.0, 1.0]);
let mut points: Vec<_> = points.iter().map(|id| *id).collect();
points.sort();
assert_eq!(points, &[0, 1, 2, 3, 4, 5]);
}
#[test]
fn extract_features_2d_all_works() {
let mesh = Samples::two_qua4();
let all_2d_edges = extract_all_2d_edges(&mesh);
let (points, edges, min, max) = extract_features_2d(&mesh, &all_2d_edges, true);
let correct_keys = [(0, 1), (0, 3), (1, 2), (1, 4), (2, 3), (2, 5), (4, 5)];
let correct_points = [[1, 0], [0, 3], [2, 1], [4, 1], [3, 2], [2, 5], [5, 4]];
validate_edges(&edges, &correct_keys, &correct_points);
assert_eq!(min, &[0.0, 0.0]);
assert_eq!(max, &[2.0, 1.0]);
let mut points: Vec<_> = points.iter().map(|id| *id).collect();
points.sort();
assert_eq!(points, &[0, 1, 2, 3, 4, 5]);
}
#[test]
fn extract_features_2d_mixed_works() {
let mesh = Samples::mixed_shapes_2d();
let all_2d_edges = extract_all_2d_edges(&mesh);
let (points, edges, min, max) = extract_features_2d(&mesh, &all_2d_edges, false);
let correct_keys = [(1, 2), (1, 4), (2, 3), (3, 4)];
let correct_points = [[2, 1], [1, 4], [3, 2], [4, 3]];
validate_edges(&edges, &correct_keys, &correct_points);
assert_eq!(min, &[1.0, 0.0]); assert_eq!(max, &[2.0, 1.0]); let mut points: Vec<_> = points.iter().map(|id| *id).collect();
points.sort();
assert_eq!(points, &[1, 2, 3, 4,]); }
#[test]
fn extract_features_2d_block_works() {
let mesh = Samples::block_2d_four_qua16();
let all_2d_edges = extract_all_2d_edges(&mesh);
let (points, edges, min, max) = extract_features_2d(&mesh, &all_2d_edges, false);
let correct_keys = [(0, 1), (0, 3), (1, 16), (3, 29), (16, 17), (17, 40), (28, 29), (28, 40)];
let correct_points = [
[1, 0, 8, 4],
[0, 3, 11, 7],
[16, 1, 21, 18],
[3, 29, 35, 32],
[17, 16, 22, 19],
[40, 17, 43, 41],
[29, 28, 34, 31],
[28, 40, 44, 42],
];
validate_edges(&edges, &correct_keys, &correct_points);
assert_eq!(min, &[0.0, 0.0]);
assert_eq!(max, &[3.0, 3.0]);
let mut points: Vec<_> = points.iter().map(|id| *id).collect();
points.sort();
assert_eq!(
points,
&[0, 1, 3, 4, 7, 8, 11, 16, 17, 18, 19, 21, 22, 28, 29, 31, 32, 34, 35, 40, 41, 42, 43, 44]
);
}
#[test]
fn extract_features_2d_all_block_works() {
let mesh = Samples::block_2d_four_qua16();
let all_2d_edges = extract_all_2d_edges(&mesh);
let (points, edges, min, max) = extract_features_2d(&mesh, &all_2d_edges, true);
let correct_keys = [
(0, 1),
(0, 3),
(1, 2),
(1, 16),
(2, 3),
(2, 17),
(2, 28),
(3, 29),
(16, 17),
(17, 40),
(28, 29),
(28, 40),
];
let correct_points = [
[1, 0, 8, 4],
[0, 3, 11, 7],
[2, 1, 9, 5],
[16, 1, 21, 18],
[3, 2, 10, 6],
[2, 17, 23, 20],
[28, 2, 33, 30],
[3, 29, 35, 32],
[17, 16, 22, 19],
[40, 17, 43, 41],
[29, 28, 34, 31],
[28, 40, 44, 42],
];
validate_edges(&edges, &correct_keys, &correct_points);
assert_eq!(min, &[0.0, 0.0]);
assert_eq!(max, &[3.0, 3.0]);
let mut points: Vec<_> = points.iter().map(|id| *id).collect();
points.sort();
assert_eq!(
points,
&[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 31, 32, 33, 34, 35,
40, 41, 42, 43, 44
]
);
}
#[test]
fn extract_features_2d_ring_works() {
let mesh = Samples::ring_eight_qua8_rad1_thick1();
let all_2d_edges = extract_all_2d_edges(&mesh);
let (points, edges, min, max) = extract_features_2d(&mesh, &all_2d_edges, false);
let correct_keys = [
(0, 1),
(0, 3),
(1, 2),
(2, 5),
(3, 6),
(5, 8),
(6, 9),
(8, 11),
(9, 12),
(11, 14),
(12, 13),
(13, 14),
];
let correct_points = [
[1, 0, 15],
[0, 3, 25],
[2, 1, 16],
[5, 2, 27],
[3, 6, 28],
[8, 5, 30],
[6, 9, 31],
[11, 8, 33],
[9, 12, 34],
[14, 11, 36],
[12, 13, 23],
[13, 14, 24],
];
validate_edges(&edges, &correct_keys, &correct_points);
array_approx_eq(&min, &[0.0, 0.0], 1e-15);
array_approx_eq(&max, &[2.0, 2.0], 1e-15);
let mut points: Vec<_> = points.iter().map(|id| *id).collect();
points.sort();
assert_eq!(
points,
&[0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 15, 16, 23, 24, 25, 27, 28, 30, 31, 33, 34, 36,]
);
}
}