use std::{
fs::File,
io::{self, BufRead, BufReader, BufWriter, Write},
path::Path,
};
use crate::{
geometry::{
Point3,
point::{Point, PointOps},
spatial_element::SpatialElement,
vector::{Vector, VectorOps},
},
mesh::basic_types::Mesh,
numeric::scalar::Scalar,
};
pub fn write_obj<T: Scalar, const N: usize, P: AsRef<Path>>(
mesh: &Mesh<T, N>,
path: P,
) -> io::Result<()>
where
Point<T, N>: PointOps<T, N, Vector = Vector<T, N>>,
Vector<T, N>: VectorOps<T, N, Cross = Vector<T, N>>,
for<'a> &'a T: std::ops::Sub<&'a T, Output = T>
+ std::ops::Mul<&'a T, Output = T>
+ std::ops::Add<&'a T, Output = T>
+ std::ops::Div<&'a T, Output = T>
+ std::ops::Neg<Output = T>,
{
let file = File::create(path)?;
let mut out = BufWriter::new(file);
for v in &mesh.vertices {
let coords = v.position.coords();
writeln!(
out,
"v {:?} {:?} {:?}",
coords[0].to_f64().unwrap(),
coords[1].to_f64().unwrap(),
coords[2].to_f64().unwrap()
)?;
}
for f in 0..mesh.faces.len() {
if mesh.faces[f].removed {
continue; }
let vs = mesh.face_vertices(f);
writeln!(out, "f {:?} {:?} {:?}", vs[0] + 1, vs[1] + 1, vs[2] + 1)?;
}
out.flush()
}
pub fn read_obj<T: Scalar, P: AsRef<Path>>(path: P) -> io::Result<Mesh<T, 3>>
where
Point<T, 3>: PointOps<T, 3, Vector = Vector<T, 3>>,
Vector<T, 3>: VectorOps<T, 3, Cross = Vector<T, 3>>,
for<'a> &'a T: std::ops::Sub<&'a T, Output = T>
+ std::ops::Mul<&'a T, Output = T>
+ std::ops::Add<&'a T, Output = T>
+ std::ops::Div<&'a T, Output = T>
+ std::ops::Neg<Output = T>,
{
let file = File::open(path)?;
let reader = BufReader::new(file);
let mut mesh = Mesh::new();
let mut vertex_map = Vec::new();
for line in reader.lines() {
let l = line?;
let mut parts = l.split_whitespace();
match parts.next() {
Some("v") => {
let x: f64 = parts.next().unwrap().parse().unwrap();
let y: f64 = parts.next().unwrap().parse().unwrap();
let z: f64 = parts.next().unwrap().parse().unwrap();
let vid = mesh.add_vertex(Point3::<T>::from_vals([x, y, z]));
vertex_map.push(vid);
}
Some("f") => {
let i: usize = parts.next().unwrap().parse().unwrap();
let j: usize = parts.next().unwrap().parse().unwrap();
let k: usize = parts.next().unwrap().parse().unwrap();
mesh.add_triangle(i - 1, j - 1, k - 1);
}
_ => {
}
}
}
Ok(mesh)
}