1use bevy::prelude::{Bundle, Commands, Component, Res, Resource, Vec3};
2use bevy::utils::HashMap;
3use honeycomb_core::cmap::NULL_DART_ID;
4use honeycomb_core::{
5 cmap::{
6 CMap2, CMap3, DartIdType, EdgeIdType, FaceIdType, OrbitPolicy, VertexIdType, VolumeIdType,
7 },
8 geometry::CoordsFloat,
9};
10use itertools::Itertools;
11
12#[derive(Resource)]
16pub struct Map<T: CoordsFloat>(pub CMap2<T>);
17
18#[derive(Resource)]
20pub struct Map3<T: CoordsFloat>(pub CMap3<T>);
21
22#[derive(Resource)]
24pub struct MapVertices(pub Vec<Vec3>);
25
26#[derive(Resource)]
28pub struct FaceNormals(pub HashMap<(FaceIdType, usize), Vec3>);
29
30#[derive(Resource)]
32pub struct VolumeNormals(pub HashMap<(VolumeIdType, usize), Vec3>);
33
34#[derive(Bundle, Clone)]
38pub struct DartBundle {
39 pub(crate) id: DartId,
40 pub(crate) vertex_id: VertexId,
41 pub(crate) edge_id: EdgeId,
42 pub(crate) face_id: FaceId,
43 pub(crate) volume_id: VolumeId,
44 pub(crate) dart: Dart,
45}
46
47#[derive(Bundle, Clone)]
49pub struct VertexBundle {
50 pub(crate) id: VertexId,
51 pub(crate) vertex: Vertex,
52}
53
54#[derive(Bundle, Clone)]
56pub struct EdgeBundle {
57 pub(crate) id: EdgeId,
58 pub(crate) edge: Edge,
59}
60
61#[derive(Bundle, Clone)]
63pub struct FaceBundle {
64 pub(crate) id: FaceId,
65 pub(crate) face: Face,
66}
67
68#[derive(Component, Clone)]
72pub struct DartId(pub DartIdType);
73
74#[derive(Component, Clone)]
76pub struct VertexId(pub VertexIdType);
77
78#[derive(Component, Clone)]
80pub struct EdgeId(pub EdgeIdType);
81
82#[derive(Component, Clone)]
84pub struct FaceId(pub FaceIdType);
85
86#[derive(Component, Clone)]
88pub struct VolumeId(pub VolumeIdType);
89
90#[derive(Component, Clone)]
92pub struct Dart {
93 pub(crate) start: usize,
94 pub(crate) end: usize,
95}
96
97#[derive(Component, Clone)]
99pub struct Beta(pub u8, pub usize, pub usize); #[derive(Component, Clone)]
103pub struct Vertex(pub usize); #[derive(Component, Clone)]
107pub struct Edge(pub usize, pub usize); #[derive(Component, Clone)]
111pub struct Face(pub Vec<usize>); #[derive(Component, Clone)]
115pub struct Volume;
116
117#[allow(clippy::too_many_lines)]
125pub fn extract_data_from_map<T: CoordsFloat>(mut commands: Commands, cmap: Res<Map<T>>) {
126 let cmap = &cmap.0;
127 let map_vertices: Vec<_> = cmap.iter_vertices().collect();
128 let map_edges: Vec<_> = cmap.iter_edges().collect();
129 let map_faces: Vec<_> = cmap.iter_faces().collect();
130
131 let mut index_map: HashMap<VertexIdType, usize> = HashMap::with_capacity(cmap.n_vertices());
132
133 let vertex_vals: Vec<Vec3> = map_vertices
134 .iter()
135 .enumerate()
136 .map(|(idx, vid)| {
137 index_map.insert(*vid, idx);
138 let v = cmap
139 .force_read_vertex(*vid)
140 .expect("E: found a topological vertex with no associated coordinates");
141 Vec3::from((v.0.to_f32().unwrap(), v.1.to_f32().unwrap(), 0.0))
143 })
144 .collect();
145
146 let vertices: Vec<VertexBundle> = map_vertices
147 .iter()
148 .map(|id| VertexBundle {
149 id: VertexId(*id),
150 vertex: Vertex(index_map[id]),
151 })
152 .collect();
153
154 let edges: Vec<EdgeBundle> = map_edges
155 .iter()
156 .map(|id| {
157 let v1id = cmap.vertex_id(*id as DartIdType);
158 let v2id = if cmap.is_i_free::<2>(*id as DartIdType) {
159 cmap.vertex_id(cmap.beta::<1>(*id as DartIdType))
160 } else {
161 cmap.vertex_id(cmap.beta::<2>(*id as DartIdType))
162 };
163 EdgeBundle {
164 id: EdgeId(*id),
165 edge: Edge(index_map[&v1id], index_map[&v2id]),
166 }
167 })
168 .collect();
169
170 let mut face_normals = HashMap::new();
171 let mut darts: Vec<DartBundle> = Vec::new();
172
173 let faces: Vec<FaceBundle> = map_faces
174 .iter()
175 .map(|id| {
176 let vertex_ids: Vec<usize> = cmap
177 .orbit(OrbitPolicy::Custom(&[1]), *id as DartIdType)
178 .map(|dart_id| index_map[&cmap.vertex_id(dart_id)])
179 .collect();
180 let n_v = vertex_ids.len();
181 {
182 let (ver_in, ver, ver_out) = (&vertex_ids[n_v - 1], &vertex_ids[0], &vertex_ids[1]);
183 let (vec_in, vec_out) = (
184 vertex_vals[*ver] - vertex_vals[*ver_in],
185 vertex_vals[*ver_out] - vertex_vals[*ver],
186 );
187 let normal = (vec_in.cross(Vec3::Z).normalize()
190 + vec_out.cross(Vec3::Z).normalize())
191 .normalize();
192 face_normals.insert((*id, *ver), normal);
193 }
194 vertex_ids.windows(3).for_each(|wdw| {
195 let [ver_in, ver, ver_out] = wdw else {
196 unreachable!("i kneel");
197 };
198 let (vec_in, vec_out) = (
199 vertex_vals[*ver] - vertex_vals[*ver_in],
200 vertex_vals[*ver_out] - vertex_vals[*ver],
201 );
202 let normal = (vec_in.cross(Vec3::Z).normalize()
203 + vec_out.cross(Vec3::Z).normalize())
204 .normalize();
205 face_normals.insert((*id, *ver), normal);
206 });
207 {
208 let (ver_in, ver, ver_out) =
209 (&vertex_ids[n_v - 2], &vertex_ids[n_v - 1], &vertex_ids[0]);
210 let (vec_in, vec_out) = (
211 vertex_vals[*ver] - vertex_vals[*ver_in],
212 vertex_vals[*ver_out] - vertex_vals[*ver],
213 );
214 let normal = (vec_in.cross(Vec3::Z).normalize()
215 + vec_out.cross(Vec3::Z).normalize())
216 .normalize();
217 face_normals.insert((*id, *ver), normal);
218 }
219
220 let mut tmp = cmap
222 .orbit(OrbitPolicy::Custom(&[1]), *id as DartIdType)
223 .map(|dart_id| (dart_id, index_map[&cmap.vertex_id(dart_id)]))
224 .collect::<Vec<_>>();
225 tmp.push(tmp[0]); let bodies = tmp.windows(2).map(|wd| {
229 let [(dart_id, v1_id), (_, v2_id)] = wd else {
230 unreachable!("i kneel");
231 };
232
233 DartBundle {
234 id: DartId(*dart_id),
235 vertex_id: VertexId(cmap.vertex_id(*dart_id)),
236 edge_id: EdgeId(cmap.edge_id(*dart_id)),
237 face_id: FaceId(*id),
238 volume_id: VolumeId(1),
239 dart: Dart {
240 start: *v1_id,
241 end: *v2_id,
242 },
243 }
244 });
245
246 darts.extend(bodies);
247
248 FaceBundle {
249 id: FaceId(*id),
250 face: Face(vertex_ids),
251 }
252 })
253 .collect();
254
255 commands.insert_resource(MapVertices(vertex_vals));
256 commands.insert_resource(FaceNormals(face_normals));
257
258 for bundle in darts {
259 commands.spawn(bundle);
260 }
261 for bundle in vertices {
262 commands.spawn(bundle);
263 }
264 for bundle in edges {
265 commands.spawn(bundle);
266 }
267 for bundle in faces {
268 commands.spawn(bundle);
269 }
270}
271
272#[allow(clippy::too_many_lines)]
278pub fn extract_data_from_3d_map<T: CoordsFloat>(mut commands: Commands, cmap: Res<Map3<T>>) {
279 let cmap = &cmap.0;
280 let map_vertices: Vec<_> = cmap.iter_vertices().collect();
281 let map_edges: Vec<_> = cmap.iter_edges().collect();
282 let map_faces: Vec<_> = cmap.iter_faces().collect();
283 let map_volumes: Vec<_> = cmap.iter_volumes().collect();
284
285 let mut index_map: HashMap<VertexIdType, usize> = HashMap::with_capacity(cmap.n_vertices());
286
287 let vertex_vals: Vec<Vec3> = map_vertices
288 .iter()
289 .enumerate()
290 .map(|(idx, vid)| {
291 index_map.insert(*vid, idx);
292 let v = cmap
293 .force_read_vertex(*vid)
294 .expect("E: found a topological vertex with no associated coordinates");
295 Vec3::from((
297 v.0.to_f32().unwrap(),
298 v.1.to_f32().unwrap(),
299 v.2.to_f32().unwrap(),
300 ))
301 })
302 .collect();
303
304 let vertices: Vec<VertexBundle> = map_vertices
305 .iter()
306 .map(|id| VertexBundle {
307 id: VertexId(*id),
308 vertex: Vertex(index_map[id]),
309 })
310 .collect();
311
312 let edges: Vec<EdgeBundle> = map_edges
313 .iter()
314 .map(|id| {
315 let v1id = cmap.vertex_id(*id as DartIdType);
316 let v2id = if cmap.is_i_free::<3>(*id as DartIdType) {
317 if cmap.is_i_free::<2>(*id as DartIdType) {
318 cmap.vertex_id(cmap.beta::<1>(*id as DartIdType))
319 } else {
320 cmap.vertex_id(cmap.beta::<2>(*id as DartIdType))
321 }
322 } else {
323 cmap.vertex_id(cmap.beta::<3>(*id as DartIdType))
324 };
325 EdgeBundle {
326 id: EdgeId(*id),
327 edge: Edge(index_map[&v1id], index_map[&v2id]),
328 }
329 })
330 .collect();
331
332 let mut face_normals = HashMap::new();
333 let mut darts: Vec<DartBundle> = Vec::new();
334
335 let faces: Vec<FaceBundle> = map_faces
336 .iter()
337 .map(|id| {
338 let vertex_ids: Vec<usize> = cmap
339 .orbit(OrbitPolicy::Custom(&[1]), *id as DartIdType) .map(|dart_id| index_map[&cmap.vertex_id(dart_id)])
341 .collect();
342 let n_v = vertex_ids.len();
343 {
344 let (ver_in, ver, ver_out) = (&vertex_ids[n_v - 1], &vertex_ids[0], &vertex_ids[1]);
345 let (vec_in, vec_out) = (
346 vertex_vals[*ver] - vertex_vals[*ver_in],
347 vertex_vals[*ver_out] - vertex_vals[*ver],
348 );
349 let plane_normal = vec_in.cross(vec_out).normalize();
351 let normal = (vec_in.cross(plane_normal).normalize()
352 + vec_out.cross(plane_normal).normalize())
353 .normalize();
354 face_normals.insert((*id, *ver), normal);
355 }
356 vertex_ids.windows(3).for_each(|wdw| {
357 let [ver_in, ver, ver_out] = wdw else {
358 unreachable!("i kneel");
359 };
360 let (vec_in, vec_out) = (
361 vertex_vals[*ver] - vertex_vals[*ver_in],
362 vertex_vals[*ver_out] - vertex_vals[*ver],
363 );
364 let plane_normal = vec_in.cross(vec_out).normalize();
366 let normal = (vec_in.cross(plane_normal).normalize()
367 + vec_out.cross(plane_normal).normalize())
368 .normalize();
369 face_normals.insert((*id, *ver), normal);
370 });
371 {
372 let (ver_in, ver, ver_out) =
373 (&vertex_ids[n_v - 2], &vertex_ids[n_v - 1], &vertex_ids[0]);
374 let (vec_in, vec_out) = (
375 vertex_vals[*ver] - vertex_vals[*ver_in],
376 vertex_vals[*ver_out] - vertex_vals[*ver],
377 );
378 let plane_normal = vec_in.cross(vec_out).normalize();
380 let normal = (vec_in.cross(plane_normal).normalize()
381 + vec_out.cross(plane_normal).normalize())
382 .normalize();
383 face_normals.insert((*id, *ver), normal);
384 }
385
386 let mut tmp = cmap
388 .orbit(OrbitPolicy::Custom(&[1]), *id as DartIdType)
389 .map(|dart_id| (dart_id, index_map[&cmap.vertex_id(dart_id)]))
390 .collect::<Vec<_>>();
391 tmp.push(tmp[0]); let bodies = tmp.windows(2).map(|wd| {
395 let [(dart_id, v1_id), (_, v2_id)] = wd else {
396 unreachable!("i kneel");
397 };
398
399 DartBundle {
400 id: DartId(*dart_id),
401 vertex_id: VertexId(cmap.vertex_id(*dart_id)),
402 edge_id: EdgeId(cmap.edge_id(*dart_id)),
403 face_id: FaceId(*id),
404 volume_id: VolumeId(cmap.volume_id(*dart_id)),
405 dart: Dart {
406 start: *v1_id,
407 end: *v2_id,
408 },
409 }
410 });
411
412 darts.extend(bodies);
413
414 let mut tmp2 = cmap
416 .orbit(OrbitPolicy::Custom(&[1]), cmap.beta::<3>(*id as DartIdType))
417 .filter_map(|dart_id| {
418 if dart_id == NULL_DART_ID {
419 return None;
420 }
421 Some((dart_id, index_map[&cmap.vertex_id(dart_id)]))
422 })
423 .collect::<Vec<_>>();
424 if !tmp2.is_empty() {
425 tmp2.push(tmp2[0]); }
427 let bodies2 = tmp2.windows(2).map(|wd| {
429 let [(dart_id, v1_id), (_, v2_id)] = wd else {
430 unreachable!("i kneel");
431 };
432
433 DartBundle {
434 id: DartId(*dart_id),
435 vertex_id: VertexId(cmap.vertex_id(*dart_id)),
436 edge_id: EdgeId(cmap.edge_id(*dart_id)),
437 face_id: FaceId(*id),
438 volume_id: VolumeId(cmap.volume_id(*dart_id)),
439 dart: Dart {
440 start: *v1_id,
441 end: *v2_id,
442 },
443 }
444 });
445
446 darts.extend(bodies2);
447
448 FaceBundle {
449 id: FaceId(*id),
450 face: Face(vertex_ids),
451 }
452 })
453 .collect();
454
455 let mut volume_normals = HashMap::new();
456
457 for vol in map_volumes {
458 let darts: Vec<_> = cmap.orbit(OrbitPolicy::Volume, vol as DartIdType).collect();
459 let norms: HashMap<_, _> = darts
460 .iter()
461 .unique_by(|&d| cmap.face_id(*d))
462 .map(|d| {
463 let mut base = Vec3::default();
464 let tmp: Vec<_> = cmap
465 .orbit(OrbitPolicy::Custom(&[1]), *d as DartIdType)
466 .chain([*d])
467 .collect();
468 tmp.windows(2).for_each(|sl| {
469 let [d1, d2] = sl else { unreachable!() };
470 let (vid1, vid2) = (
471 index_map[&cmap.vertex_id(*d1)],
472 index_map[&cmap.vertex_id(*d2)],
473 );
474 let (v1, v2) = (vertex_vals[vid1], vertex_vals[vid2]);
475 base.x += (v1.y - v2.y) * (v1.z + v2.z);
476 base.y += (v1.z - v2.z) * (v1.x + v2.x);
477 base.z += (v1.x - v2.x) * (v1.y + v2.y);
478 });
479 (cmap.face_id(*d), base.normalize())
480 })
481 .collect();
482
483 for d in darts {
486 let fid = cmap.face_id(d);
487 let vid = index_map[&cmap.vertex_id(d)];
488 if let Some(val) = volume_normals.get_mut(&(vol, vid)) {
489 *val += norms[&fid];
490 } else {
491 volume_normals.insert((vol, vid), norms[&fid]);
492 }
493 }
494 }
495 for val in volume_normals.values_mut() {
496 *val = val.normalize();
497 }
498
499 commands.insert_resource(MapVertices(vertex_vals));
500 commands.insert_resource(FaceNormals(face_normals));
501 commands.insert_resource(VolumeNormals(volume_normals));
502
503 for bundle in darts {
504 commands.spawn(bundle);
505 }
506 for bundle in vertices {
507 commands.spawn(bundle);
508 }
509 for bundle in edges {
510 commands.spawn(bundle);
511 }
512 for bundle in faces {
513 commands.spawn(bundle);
514 }
515}