1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 Array, Vector3,
6 array::Constraint,
7 array_type,
8 validate::{Validate, Validator},
9};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
13#[serde(tag = "type")]
14pub enum Grid2 {
15 #[doc = include_str!("../docs/images/grid2_regular.svg")]
19 Regular {
20 size: [f64; 2],
22 count: [u32; 2],
24 },
25 #[doc = include_str!("../docs/images/grid2_tensor.svg")]
29 Tensor {
30 u: Array<array_type::Scalar>,
33 v: Array<array_type::Scalar>,
36 },
37}
38
39impl Grid2 {
40 pub fn from_size_and_count(size: [f64; 2], count: [u32; 2]) -> Self {
42 Self::Regular { size, count }
43 }
44
45 pub fn from_arrays(u: Array<array_type::Scalar>, v: Array<array_type::Scalar>) -> Self {
47 Self::Tensor { u, v }
48 }
49
50 pub fn count(&self) -> [u32; 2] {
52 match self {
53 Self::Regular { count, .. } => *count,
54 Self::Tensor { u, v } => [u.item_count() as u32, v.item_count() as u32],
55 }
56 }
57
58 pub fn flat_count(&self) -> u64 {
60 self.count().into_iter().map(u64::from).product()
61 }
62
63 pub fn flat_corner_count(&self) -> u64 {
65 self.count().into_iter().map(|n| u64::from(n) + 1).product()
66 }
67}
68
69impl Default for Grid2 {
70 fn default() -> Self {
72 Self::Regular {
73 size: [1.0, 1.0],
74 count: [1, 1],
75 }
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
81#[serde(tag = "type")]
82#[allow(clippy::large_enum_variant)]
83pub enum Grid3 {
84 #[doc = include_str!("../docs/images/grid3_regular.svg")]
88 Regular {
89 size: Vector3,
91 count: [u32; 3],
93 },
94 #[doc = include_str!("../docs/images/grid3_tensor.svg")]
99 Tensor {
100 u: Array<array_type::Scalar>,
103 v: Array<array_type::Scalar>,
106 w: Array<array_type::Scalar>,
109 },
110}
111
112impl Grid3 {
113 pub fn from_size_and_count(size: Vector3, count: [u32; 3]) -> Self {
115 Self::Regular { size, count }
116 }
117
118 pub fn from_arrays(
120 u: Array<array_type::Scalar>,
121 v: Array<array_type::Scalar>,
122 w: Array<array_type::Scalar>,
123 ) -> Self {
124 Self::Tensor { u, v, w }
125 }
126
127 pub fn count(&self) -> [u32; 3] {
129 match self {
130 Self::Regular { count, .. } => *count,
131 Self::Tensor { u, v, w } => [
133 u.item_count() as u32,
134 v.item_count() as u32,
135 w.item_count() as u32,
136 ],
137 }
138 }
139
140 pub fn flat_count(&self) -> u64 {
142 self.count().iter().map(|n| u64::from(*n)).product()
143 }
144
145 pub fn flat_corner_count(&self) -> u64 {
147 self.count().iter().map(|n| u64::from(*n) + 1).product()
148 }
149}
150
151impl Default for Grid3 {
152 fn default() -> Self {
153 Self::Regular {
154 size: [1.0, 1.0, 1.0],
155 count: [1, 1, 1],
156 }
157 }
158}
159
160const fn i() -> Vector3 {
161 [1.0, 0.0, 0.0]
162}
163
164const fn j() -> Vector3 {
165 [0.0, 1.0, 0.0]
166}
167
168const fn k() -> Vector3 {
169 [0.0, 0.0, 1.0]
170}
171
172#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)]
174#[repr(C)]
175pub struct Orient2 {
176 pub origin: Vector3,
178 #[serde(default = "i")]
182 pub u: Vector3,
183 #[serde(default = "j")]
187 pub v: Vector3,
188}
189
190impl Orient2 {
191 pub fn new(origin: Vector3, u: Vector3, v: Vector3) -> Self {
193 Self { origin, u, v }
194 }
195
196 pub fn from_origin(origin: Vector3) -> Self {
198 Self::new(origin, i(), j())
199 }
200
201 pub(crate) fn validate_ortho(&self, val: &mut Validator) {
202 val.enter("Orient2").vectors_ortho2(self.u, self.v);
203 }
204}
205
206impl Default for Orient2 {
207 fn default() -> Self {
209 Self {
210 origin: [0.0; 3],
211 u: i(),
212 v: j(),
213 }
214 }
215}
216
217#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema)]
219#[repr(C)]
220pub struct Orient3 {
221 pub origin: Vector3,
223 #[serde(default = "i")]
226 pub u: Vector3,
227 #[serde(default = "j")]
230 pub v: Vector3,
231 #[serde(default = "k")]
234 pub w: Vector3,
235}
236
237impl Orient3 {
238 pub fn new(origin: Vector3, u: Vector3, v: Vector3, w: Vector3) -> Self {
240 Self { origin, u, v, w }
241 }
242
243 pub fn from_origin(origin: Vector3) -> Self {
245 Self::new(origin, i(), j(), k())
246 }
247}
248
249impl Default for Orient3 {
250 fn default() -> Self {
251 Self {
252 origin: [0.0; 3],
253 u: i(),
254 v: j(),
255 w: k(),
256 }
257 }
258}
259
260impl Validate for Grid2 {
261 fn validate_inner(&mut self, val: &mut Validator) {
262 match self {
263 Grid2::Regular { size, count } => {
264 val.enter("Grid2::Regular")
265 .finite_seq(*size, "size")
266 .above_zero_seq(*size, "size")
267 .above_zero_seq(*count, "count");
268 }
269 Grid2::Tensor { u, v } => {
270 val.enter("Grid2::Tensor")
271 .grid_count(&[u.item_count(), v.item_count()])
272 .array(u, Constraint::Size, "u")
273 .array(v, Constraint::Size, "v");
274 }
275 }
276 }
277}
278
279impl Validate for Grid3 {
280 fn validate_inner(&mut self, val: &mut Validator) {
281 match self {
282 Grid3::Regular { size, count } => {
283 val.enter("Grid3::Regular")
284 .finite_seq(*size, "size")
285 .above_zero_seq(*size, "size")
286 .above_zero_seq(*count, "count");
287 }
288 Grid3::Tensor { u, v, w } => {
289 val.enter("Grid3::Tensor")
290 .grid_count(&[u.item_count(), v.item_count(), w.item_count()])
291 .array(u, Constraint::Size, "u")
292 .array(v, Constraint::Size, "v")
293 .array(w, Constraint::Size, "w");
294 }
295 }
296 }
297}
298
299impl Validate for Orient2 {
300 fn validate_inner(&mut self, val: &mut Validator) {
301 val.enter("Orient2")
302 .finite_seq(self.origin, "origin")
303 .unit_vector(self.u, "u")
304 .unit_vector(self.v, "v");
305 }
306}
307
308impl Validate for Orient3 {
309 fn validate_inner(&mut self, val: &mut Validator) {
310 val.enter("Orient3")
311 .finite_seq(self.origin, "origin")
312 .unit_vector(self.u, "u")
313 .unit_vector(self.v, "v")
314 .unit_vector(self.w, "w")
315 .vectors_ortho3(self.u, self.v, self.w);
316 }
317}