conspire/geometry/mesh/sets/
mod.rs1#[cfg(test)]
2mod test;
3
4use std::slice::Iter;
5
6macro_rules! sets {
7 ($set: ident, $sets: ident, $member: ty, $members: ident, $doc: literal, $docs: literal) => {
8 #[doc = $doc]
9 #[derive(Clone, Debug, PartialEq)]
10 pub struct $set {
11 label: Option<usize>,
12 name: Option<String>,
13 $members: Vec<$member>,
14 }
15 impl $set {
16 pub fn new($members: Vec<$member>) -> Self {
17 Self {
18 label: None,
19 name: None,
20 $members,
21 }
22 }
23 pub fn with_label(mut self, label: usize) -> Self {
24 self.label = Some(label);
25 self
26 }
27 pub fn with_name(mut self, name: impl Into<String>) -> Self {
28 self.name = Some(name.into());
29 self
30 }
31 pub fn label(&self) -> Option<usize> {
32 self.label
33 }
34 pub fn name(&self) -> Option<&str> {
35 self.name.as_deref()
36 }
37 pub fn $members(&self) -> &[$member] {
38 &self.$members
39 }
40 pub fn restrict(&self, map: impl Fn($member) -> Option<$member>) -> Option<Self> {
41 let $members: Vec<$member> = self.$members.iter().filter_map(|&m| map(m)).collect();
42 (!$members.is_empty()).then(|| Self {
43 label: self.label,
44 name: self.name.clone(),
45 $members,
46 })
47 }
48 }
49 #[doc = $docs]
50 #[derive(Clone, Debug, Default, PartialEq)]
51 pub struct $sets(Vec<$set>);
52 impl $sets {
53 pub fn new() -> Self {
54 Self::default()
55 }
56 pub fn push(&mut self, set: $set) {
57 self.0.push(set)
58 }
59 pub fn iter(&self) -> Iter<'_, $set> {
60 self.0.iter()
61 }
62 pub fn len(&self) -> usize {
63 self.0.len()
64 }
65 pub fn is_empty(&self) -> bool {
66 self.0.is_empty()
67 }
68 pub fn by_label(&self, label: usize) -> Option<&$set> {
70 self.0.iter().find(|set| set.label == Some(label))
71 }
72 pub fn by_name(&self, name: &str) -> Option<&$set> {
74 self.0.iter().find(|set| set.name.as_deref() == Some(name))
75 }
76 pub fn resolved_labels(&self) -> Vec<usize> {
78 let mut next = 0;
79 self.0
80 .iter()
81 .map(|set| {
82 set.label.unwrap_or_else(|| {
83 loop {
84 next += 1;
85 if self.by_label(next).is_none() {
86 return next;
87 }
88 }
89 })
90 })
91 .collect()
92 }
93 }
94 impl<'a> IntoIterator for &'a $sets {
95 type Item = &'a $set;
96 type IntoIter = Iter<'a, $set>;
97 fn into_iter(self) -> Self::IntoIter {
98 self.0.iter()
99 }
100 }
101 impl From<Vec<$set>> for $sets {
102 fn from(sets: Vec<$set>) -> Self {
103 Self(sets)
104 }
105 }
106 impl From<Vec<Vec<$member>>> for $sets {
107 fn from(sets: Vec<Vec<$member>>) -> Self {
108 Self(sets.into_iter().map($set::new).collect())
109 }
110 }
111 impl From<(Vec<Vec<$member>>, Vec<usize>)> for $sets {
112 fn from((sets, labels): (Vec<Vec<$member>>, Vec<usize>)) -> Self {
113 assert_eq!(
114 sets.len(),
115 labels.len(),
116 "There must be exactly one label for each set."
117 );
118 Self(
119 sets.into_iter()
120 .zip(labels)
121 .map(|(members, label)| $set::new(members).with_label(label))
122 .collect(),
123 )
124 }
125 }
126 };
127}
128
129sets!(
130 NodeSet,
131 NodeSets,
132 usize,
133 nodes,
134 "A set of nodes, optionally labeled and named.",
135 "Sets of nodes."
136);
137sets!(
138 SideSet,
139 SideSets,
140 (usize, usize),
141 sides,
142 "A set of element sides, each an element and the ordinal of one of its faces, optionally labeled and named.",
143 "Sets of element sides."
144);