1use crate::{Color, Point, Tolerance, Vector, Xform};
2use serde::{Deserialize, Serialize};
3use std::collections::{HashMap, HashSet};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum NormalWeighting {
8 Area,
9 Angle,
10 Uniform,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15#[serde(tag = "type", rename = "Mesh")]
16pub struct Mesh {
17 pub halfedge: HashMap<usize, HashMap<usize, Option<usize>>>, pub vertex: HashMap<usize, VertexData>, pub face: HashMap<usize, Vec<usize>>, pub facedata: HashMap<usize, HashMap<String, f32>>, pub edgedata: HashMap<(usize, usize), HashMap<String, f32>>, pub default_vertex_attributes: HashMap<String, f32>, pub default_face_attributes: HashMap<String, f32>, pub default_edge_attributes: HashMap<String, f32>, #[serde(skip)]
26 pub triangulation: HashMap<usize, Vec<[usize; 3]>>, max_vertex: usize, max_face: usize, pub guid: String, pub name: String, #[serde(skip)]
32 pub pointcolors: Vec<Color>, #[serde(skip)]
34 pub facecolors: Vec<Color>, #[serde(skip)]
36 pub linecolors: Vec<Color>, #[serde(skip)]
38 pub widths: Vec<f32>, #[serde(default = "Xform::identity")]
40 pub xform: Xform, }
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct VertexData {
46 pub x: f32, pub y: f32, pub z: f32, pub attributes: HashMap<String, f32>, }
51
52impl VertexData {
53 pub fn new(point: Point) -> Self {
54 Self {
55 x: point.x(),
56 y: point.y(),
57 z: point.z(),
58 attributes: HashMap::new(),
59 }
60 }
61
62 pub fn position(&self) -> Point {
63 Point::new(self.x, self.y, self.z)
64 }
65
66 pub fn set_position(&mut self, point: Point) {
67 self.x = point.x();
68 self.y = point.y();
69 self.z = point.z();
70 }
71
72 pub fn color(&self) -> [f32; 3] {
73 [
74 self.attributes.get("r").copied().unwrap_or(0.5),
75 self.attributes.get("g").copied().unwrap_or(0.5),
76 self.attributes.get("b").copied().unwrap_or(0.5),
77 ]
78 }
79
80 pub fn set_color(&mut self, r: f32, g: f32, b: f32) {
81 self.attributes.insert("r".to_string(), r);
82 self.attributes.insert("g".to_string(), g);
83 self.attributes.insert("b".to_string(), b);
84 }
85
86 pub fn normal(&self) -> Option<[f32; 3]> {
87 let nx = self.attributes.get("nx")?;
88 let ny = self.attributes.get("ny")?;
89 let nz = self.attributes.get("nz")?;
90 Some([*nx, *ny, *nz])
91 }
92
93 pub fn set_normal(&mut self, nx: f32, ny: f32, nz: f32) {
94 self.attributes.insert("nx".to_string(), nx);
95 self.attributes.insert("ny".to_string(), ny);
96 self.attributes.insert("nz".to_string(), nz);
97 }
98}
99
100impl Default for Mesh {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106impl Mesh {
107 pub fn new() -> Self {
109 let mut default_vertex_attributes = HashMap::new();
110 default_vertex_attributes.insert("x".to_string(), 0.0);
111 default_vertex_attributes.insert("y".to_string(), 0.0);
112 default_vertex_attributes.insert("z".to_string(), 0.0);
113
114 Mesh {
115 halfedge: HashMap::new(),
116 vertex: HashMap::new(),
117 face: HashMap::new(),
118 facedata: HashMap::new(),
119 edgedata: HashMap::new(),
120 default_vertex_attributes,
121 default_face_attributes: HashMap::new(),
122 default_edge_attributes: HashMap::new(),
123 triangulation: HashMap::new(),
124 max_vertex: 0,
125 max_face: 0,
126 guid: uuid::Uuid::new_v4().to_string(),
127 name: "my_mesh".to_string(),
128 pointcolors: Vec::new(),
129 facecolors: Vec::new(),
130 linecolors: Vec::new(),
131 widths: Vec::new(),
132 xform: Xform::identity(),
133 }
134 }
135
136 pub fn is_empty(&self) -> bool {
137 self.vertex.is_empty() && self.face.is_empty()
138 }
139
140 pub fn clear(&mut self) {
141 self.halfedge.clear();
142 self.vertex.clear();
143 self.face.clear();
144 self.facedata.clear();
145 self.edgedata.clear();
146 self.triangulation.clear();
147 self.max_vertex = 0;
148 self.max_face = 0;
149 self.pointcolors.clear();
150 self.facecolors.clear();
151 self.linecolors.clear();
152 self.widths.clear();
153 }
154
155 pub fn number_of_vertices(&self) -> usize {
156 self.vertex.len()
157 }
158
159 pub fn number_of_faces(&self) -> usize {
160 self.face.len()
161 }
162
163 pub fn number_of_edges(&self) -> usize {
164 let mut seen = HashSet::new();
165 let mut count = 0;
166
167 for u in self.halfedge.keys() {
168 if let Some(neighbors) = self.halfedge.get(u) {
169 for v in neighbors.keys() {
170 let edge = if u < v { (*u, *v) } else { (*v, *u) };
171 if seen.insert(edge) {
172 count += 1;
173 }
174 }
175 }
176 }
177
178 count
179 }
180
181 pub fn euler(&self) -> i32 {
182 let v = self.number_of_vertices() as i32;
183 let e = self.number_of_edges() as i32;
184 let f = self.number_of_faces() as i32;
185 v - e + f
186 }
187
188 pub fn add_vertex(&mut self, position: Point, key: Option<usize>) -> usize {
189 let vertex_key = key.unwrap_or_else(|| {
190 self.max_vertex += 1;
191 self.max_vertex
192 });
193
194 if vertex_key >= self.max_vertex {
195 self.max_vertex = vertex_key + 1;
196 }
197
198 let vertex_data = VertexData::new(position);
199 self.vertex.insert(vertex_key, vertex_data);
200 self.halfedge.entry(vertex_key).or_default();
201 self.pointcolors.push(Color::white());
202
203 vertex_key
204 }
205
206 pub fn add_face(&mut self, vertices: Vec<usize>, fkey: Option<usize>) -> Option<usize> {
207 if vertices.len() < 3 {
208 return None;
209 }
210
211 if !vertices.iter().all(|v| self.vertex.contains_key(v)) {
212 return None;
213 }
214
215 let mut unique_vertices = HashSet::new();
216 for vertex in &vertices {
217 if !unique_vertices.insert(*vertex) {
218 return None;
219 }
220 }
221
222 let face_key = fkey.unwrap_or_else(|| {
223 self.max_face += 1;
224 self.max_face
225 });
226
227 if face_key >= self.max_face {
228 self.max_face = face_key + 1;
229 }
230
231 self.face.insert(face_key, vertices.clone());
232 self.triangulation.remove(&face_key);
233 self.facecolors.push(Color::white());
234
235 for i in 0..vertices.len() {
236 let u = vertices[i];
237 let v = vertices[(i + 1) % vertices.len()];
238
239 self.halfedge.entry(u).or_default();
240 self.halfedge.entry(v).or_default();
241
242 let is_new_edge = !self.halfedge.get(&v).unwrap().contains_key(&u);
243
244 self.halfedge.get_mut(&u).unwrap().insert(v, Some(face_key));
245
246 if is_new_edge {
247 self.halfedge.get_mut(&v).unwrap().insert(u, None);
248 self.linecolors.push(Color::white());
249 self.widths.push(1.0);
250 }
251 }
252
253 Some(face_key)
254 }
255
256 pub fn vertex_position(&self, vertex_key: usize) -> Option<Point> {
257 self.vertex.get(&vertex_key).map(|v| v.position())
258 }
259
260 pub fn face_vertices(&self, face_key: usize) -> Option<&Vec<usize>> {
261 self.face.get(&face_key)
262 }
263
264 pub fn vertex_neighbors(&self, vertex_key: usize) -> Vec<usize> {
265 self.halfedge
266 .get(&vertex_key)
267 .map(|neighbors| neighbors.keys().copied().collect())
268 .unwrap_or_default()
269 }
270
271 pub fn vertex_faces(&self, vertex_key: usize) -> Vec<usize> {
272 let mut faces = Vec::new();
273 for (face_key, face_vertices) in &self.face {
274 if face_vertices.contains(&vertex_key) {
275 faces.push(*face_key);
276 }
277 }
278 faces
279 }
280
281 pub fn is_vertex_on_boundary(&self, vertex_key: usize) -> bool {
282 if let Some(neigh) = self.halfedge.get(&vertex_key) {
283 for (_v, face_opt) in neigh.iter() {
284 if face_opt.is_none() {
285 return true;
286 }
287 }
288 }
289
290 for (_u, neigh) in self.halfedge.iter() {
291 if let Some(face_opt) = neigh.get(&vertex_key) {
292 if face_opt.is_none() {
293 return true;
294 }
295 }
296 }
297 false
298 }
299
300 pub fn face_normal(&self, face_key: usize) -> Option<Vector> {
301 let vertices = self.face.get(&face_key)?;
302 if vertices.len() < 3 {
303 return None;
304 }
305
306 let p0 = self.vertex_position(vertices[0])?;
307 let p1 = self.vertex_position(vertices[1])?;
308 let p2 = self.vertex_position(vertices[2])?;
309
310 let u = Vector::new(p1.x() - p0.x(), p1.y() - p0.y(), p1.z() - p0.z());
311 let v = Vector::new(p2.x() - p0.x(), p2.y() - p0.y(), p2.z() - p0.z());
312
313 let mut normal = u.cross(&v);
314 let len = normal.magnitude();
315 if len > Tolerance::ZERO_TOLERANCE as f32 {
316 Some(Vector::new(
317 normal.x() / len,
318 normal.y() / len,
319 normal.z() / len,
320 ))
321 } else {
322 None
323 }
324 }
325
326 pub fn vertex_normal(&self, vertex_key: usize) -> Option<Vector> {
327 self.vertex_normal_weighted(vertex_key, NormalWeighting::Area)
328 }
329
330 pub fn vertex_normal_weighted(
331 &self,
332 vertex_key: usize,
333 weighting: NormalWeighting,
334 ) -> Option<Vector> {
335 let faces = self.vertex_faces(vertex_key);
336 if faces.is_empty() {
337 return None;
338 }
339
340 let mut normal_acc = Vector::new(0.0, 0.0, 0.0);
341
342 for face_key in faces {
343 if let Some(face_normal) = self.face_normal(face_key) {
344 let weight = match weighting {
345 NormalWeighting::Area => self.face_area(face_key).unwrap_or(1.0),
346 NormalWeighting::Angle => self
347 .vertex_angle_in_face(vertex_key, face_key)
348 .unwrap_or(1.0),
349 NormalWeighting::Uniform => 1.0,
350 };
351
352 normal_acc.set_x(normal_acc.x() + face_normal.x() * weight);
353 normal_acc.set_y(normal_acc.y() + face_normal.y() * weight);
354 normal_acc.set_z(normal_acc.z() + face_normal.z() * weight);
355 }
356 }
357
358 let len = normal_acc.magnitude();
359 if len > Tolerance::ZERO_TOLERANCE as f32 {
360 Some(Vector::new(
361 normal_acc.x() / len,
362 normal_acc.y() / len,
363 normal_acc.z() / len,
364 ))
365 } else {
366 None
367 }
368 }
369
370 pub fn face_area(&self, face_key: usize) -> Option<f32> {
371 let vertices = self.face.get(&face_key)?;
372 if vertices.len() < 3 {
373 return Some(0.0);
374 }
375
376 let mut area = 0.0;
377 let p0 = self.vertex_position(vertices[0])?;
378
379 for i in 1..(vertices.len() - 1) {
380 let p1 = self.vertex_position(vertices[i])?;
381 let p2 = self.vertex_position(vertices[i + 1])?;
382
383 let u = Vector::new(p1.x() - p0.x(), p1.y() - p0.y(), p1.z() - p0.z());
384 let v = Vector::new(p2.x() - p0.x(), p2.y() - p0.y(), p2.z() - p0.z());
385
386 area += u.cross(&v).magnitude() * 0.5;
387 }
388
389 Some(area)
390 }
391
392 pub fn vertex_angle_in_face(&self, vertex_key: usize, face_key: usize) -> Option<f32> {
393 let vertices = self.face.get(&face_key)?;
394 let vertex_index = vertices.iter().position(|&v| v == vertex_key)?;
395
396 let n = vertices.len();
397 let prev_vertex = vertices[(vertex_index + n - 1) % n];
398 let next_vertex = vertices[(vertex_index + 1) % n];
399
400 let center = self.vertex_position(vertex_key)?;
401 let prev_pos = self.vertex_position(prev_vertex)?;
402 let next_pos = self.vertex_position(next_vertex)?;
403
404 let mut u = Vector::new(
405 prev_pos.x() - center.x(),
406 prev_pos.y() - center.y(),
407 prev_pos.z() - center.z(),
408 );
409 let mut v = Vector::new(
410 next_pos.x() - center.x(),
411 next_pos.y() - center.y(),
412 next_pos.z() - center.z(),
413 );
414
415 let u_len = u.magnitude();
416 let v_len = v.magnitude();
417
418 if u_len < Tolerance::ZERO_TOLERANCE as f32 || v_len < Tolerance::ZERO_TOLERANCE as f32 {
419 return Some(0.0);
420 }
421
422 let cos_angle = u.dot(&v) / (u_len * v_len);
423 let cos_angle = cos_angle.clamp(-1.0, 1.0);
424 Some(cos_angle.acos())
425 }
426
427 pub fn face_normals(&self) -> HashMap<usize, Vector> {
428 let mut normals = HashMap::new();
429 for face_key in self.face.keys() {
430 if let Some(normal) = self.face_normal(*face_key) {
431 normals.insert(*face_key, normal);
432 }
433 }
434 normals
435 }
436
437 pub fn vertex_normals(&self) -> HashMap<usize, Vector> {
438 self.vertex_normals_weighted(NormalWeighting::Area)
439 }
440
441 pub fn vertex_normals_weighted(&self, weighting: NormalWeighting) -> HashMap<usize, Vector> {
442 let mut normals = HashMap::new();
443 for vertex_key in self.vertex.keys() {
444 if let Some(normal) = self.vertex_normal_weighted(*vertex_key, weighting) {
445 normals.insert(*vertex_key, normal);
446 }
447 }
448 normals
449 }
450
451 pub fn vertex_index(&self) -> HashMap<usize, usize> {
452 let mut keys: Vec<usize> = self.vertex.keys().copied().collect();
453 keys.sort();
454 keys.iter()
455 .enumerate()
456 .map(|(index, &key)| (key, index))
457 .collect()
458 }
459
460 pub fn to_vertices_and_faces(&self) -> (Vec<Point>, Vec<Vec<usize>>) {
461 let vertex_index = self.vertex_index();
462 let mut vertices: Vec<Point> = vec![Point::default(); self.vertex.len()];
463
464 for (&key, data) in &self.vertex {
465 let idx = vertex_index[&key];
466 vertices[idx] = data.position();
467 }
468
469 let mut face_keys: Vec<usize> = self.face.keys().copied().collect();
471 face_keys.sort();
472
473 let mut faces = Vec::new();
474 for face_key in face_keys {
475 let face_vertices = &self.face[&face_key];
476 let remapped: Vec<usize> = face_vertices.iter().map(|v| vertex_index[v]).collect();
477 faces.push(remapped);
478 }
479
480 (vertices, faces)
481 }
482
483 pub fn from_polygons(polygons: Vec<Vec<Point>>, precision: Option<f32>) -> Self {
484 let mut mesh = Mesh::new();
485 let mut map_eps: HashMap<(i64, i64, i64), usize> = HashMap::new();
486 let mut map_exact: HashMap<(u64, u64, u64), usize> = HashMap::new();
487 let eps = precision.unwrap_or(0.0);
488 let use_eps = eps > 0.0;
489
490 let mut get_vkey = |p: &Point, mesh: &mut Mesh| -> usize {
491 if use_eps {
492 let kx = (p.x() / eps).round() as i64;
493 let ky = (p.y() / eps).round() as i64;
494 let kz = (p.z() / eps).round() as i64;
495 let key = (kx, ky, kz);
496 if let Some(&vk) = map_eps.get(&key) {
497 return vk;
498 }
499 let vk = mesh.add_vertex(p.clone(), None);
500 map_eps.insert(key, vk);
501 vk
502 } else {
503 let key = (
504 p.x().to_bits() as u64,
505 p.y().to_bits() as u64,
506 p.z().to_bits() as u64,
507 );
508 if let Some(&vk) = map_exact.get(&key) {
509 return vk;
510 }
511 let vk = mesh.add_vertex(p.clone(), None);
512 map_exact.insert(key, vk);
513 vk
514 }
515 };
516
517 for poly in polygons.into_iter() {
518 if poly.len() < 3 {
519 continue;
520 }
521 let mut vkeys: Vec<usize> = Vec::with_capacity(poly.len());
522 for p in &poly {
523 let vk = get_vkey(p, &mut mesh);
524 vkeys.push(vk);
525 }
526 let _ = mesh.add_face(vkeys, None);
527 }
528
529 mesh
530 }
531
532 pub fn set_vertex_color(&mut self, index: usize, color: Color) {
537 if index < self.pointcolors.len() {
538 self.pointcolors[index] = color;
539 }
540 }
541
542 pub fn set_face_color(&mut self, index: usize, color: Color) {
543 if index < self.facecolors.len() {
544 self.facecolors[index] = color;
545 }
546 }
547
548 pub fn set_edge_color(&mut self, index: usize, color: Color) {
549 if index < self.linecolors.len() {
550 self.linecolors[index] = color;
551 }
552 }
553
554 pub fn set_edge_width(&mut self, index: usize, width: f32) {
555 if index < self.widths.len() {
556 self.widths[index] = width;
557 }
558 }
559
560 pub fn jsondump(&self) -> serde_json::Value {
566 let pointcolors_flat: Vec<u8> = self
567 .pointcolors
568 .iter()
569 .flat_map(|c| vec![c.r, c.g, c.b])
570 .collect();
571
572 let facecolors_flat: Vec<u8> = self
573 .facecolors
574 .iter()
575 .flat_map(|c| vec![c.r, c.g, c.b])
576 .collect();
577
578 let linecolors_flat: Vec<u8> = self
579 .linecolors
580 .iter()
581 .flat_map(|c| vec![c.r, c.g, c.b])
582 .collect();
583
584 serde_json::json!({
585 "type": "Mesh",
586 "guid": self.guid,
587 "name": self.name,
588 "vertex": self.vertex,
589 "face": self.face,
590 "halfedge": self.halfedge,
591 "facedata": self.facedata,
592 "edgedata": self.edgedata,
593 "default_vertex_attributes": self.default_vertex_attributes,
594 "default_face_attributes": self.default_face_attributes,
595 "default_edge_attributes": self.default_edge_attributes,
596 "max_vertex": self.max_vertex,
597 "max_face": self.max_face,
598 "pointcolors": pointcolors_flat,
599 "facecolors": facecolors_flat,
600 "linecolors": linecolors_flat,
601 "widths": self.widths
602 })
603 }
604
605 pub fn jsonload(data: &serde_json::Value) -> Option<Self> {
606 let mut mesh = Mesh::new();
607
608 if let Some(guid) = data.get("guid").and_then(|v| v.as_str()) {
609 mesh.guid = guid.to_string();
610 }
611 if let Some(name) = data.get("name").and_then(|v| v.as_str()) {
612 mesh.name = name.to_string();
613 }
614
615 if let Some(vertex_data) = data.get("vertex") {
616 mesh.vertex = serde_json::from_value(vertex_data.clone()).ok()?;
617 }
618 if let Some(face_data) = data.get("face") {
619 mesh.face = serde_json::from_value(face_data.clone()).ok()?;
620 }
621 if let Some(halfedge_data) = data.get("halfedge") {
622 mesh.halfedge = serde_json::from_value(halfedge_data.clone()).ok()?;
623 }
624 if let Some(facedata) = data.get("facedata") {
625 mesh.facedata = serde_json::from_value(facedata.clone()).ok()?;
626 }
627 if let Some(edgedata) = data.get("edgedata") {
628 mesh.edgedata = serde_json::from_value(edgedata.clone()).ok()?;
629 }
630 if let Some(max_vertex) = data.get("max_vertex").and_then(|v| v.as_u64()) {
631 mesh.max_vertex = max_vertex as usize;
632 }
633 if let Some(max_face) = data.get("max_face").and_then(|v| v.as_u64()) {
634 mesh.max_face = max_face as usize;
635 }
636
637 if let Some(pointcolors_flat) = data.get("pointcolors").and_then(|v| v.as_array()) {
639 let rgb_values: Vec<u8> = pointcolors_flat
640 .iter()
641 .filter_map(|v| v.as_u64().map(|n| n as u8))
642 .collect();
643 mesh.pointcolors = rgb_values
644 .chunks(3)
645 .map(|chunk| {
646 if chunk.len() == 3 {
647 Color::new(chunk[0], chunk[1], chunk[2], 255)
648 } else {
649 Color::white()
650 }
651 })
652 .collect();
653 }
654
655 if let Some(facecolors_flat) = data.get("facecolors").and_then(|v| v.as_array()) {
656 let rgb_values: Vec<u8> = facecolors_flat
657 .iter()
658 .filter_map(|v| v.as_u64().map(|n| n as u8))
659 .collect();
660 mesh.facecolors = rgb_values
661 .chunks(3)
662 .map(|chunk| {
663 if chunk.len() == 3 {
664 Color::new(chunk[0], chunk[1], chunk[2], 255)
665 } else {
666 Color::white()
667 }
668 })
669 .collect();
670 }
671
672 if let Some(linecolors_flat) = data.get("linecolors").and_then(|v| v.as_array()) {
673 let rgb_values: Vec<u8> = linecolors_flat
674 .iter()
675 .filter_map(|v| v.as_u64().map(|n| n as u8))
676 .collect();
677 mesh.linecolors = rgb_values
678 .chunks(3)
679 .map(|chunk| {
680 if chunk.len() == 3 {
681 Color::new(chunk[0], chunk[1], chunk[2], 255)
682 } else {
683 Color::white()
684 }
685 })
686 .collect();
687 }
688
689 if let Some(widths) = data.get("widths").and_then(|v| v.as_array()) {
690 mesh.widths = widths
691 .iter()
692 .filter_map(|v| v.as_f64().map(|n| n as f32))
693 .collect();
694 }
695
696 Some(mesh)
697 }
698
699 pub fn to_json(&self, filename: &str) -> std::io::Result<()> {
700 let data = self.jsondump();
701 std::fs::write(filename, serde_json::to_string_pretty(&data)?)
702 }
703
704 pub fn from_json(filename: &str) -> std::io::Result<Self> {
705 let content = std::fs::read_to_string(filename)?;
706 let data: serde_json::Value = serde_json::from_str(&content)?;
707 Self::jsonload(&data).ok_or_else(|| {
708 std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid mesh data")
709 })
710 }
711}
712
713#[cfg(test)]
714#[path = "mesh_test.rs"]
715mod mesh_test;