use std::io::Write;
use crate::cad::svg_reader::{Point2D, SvgElement, parse_svg_elements};
use crate::error::Result;
#[derive(Clone, Copy, Debug)]
struct Pt3 {
x: f64,
y: f64,
z: f64,
}
pub fn write_svg_to_ply<W: Write>(svg_content: &str, mut writer: W) -> Result<()> {
let doc = parse_svg_elements(svg_content)?;
let mut contours: Vec<Vec<Point2D>> = Vec::new();
for elem in doc.elements {
match elem {
SvgElement::Rect {
x,
y,
width,
height,
..
} => {
contours.push(vec![
Point2D::new(x, y),
Point2D::new(x + width, y),
Point2D::new(x + width, y + height),
Point2D::new(x, y + height),
]);
}
SvgElement::Circle { center, radius, .. } => {
let segments = crate::cad::DEFAULT_CIRCLE_SEGMENTS;
let mut pts = Vec::with_capacity(segments);
for i in 0..segments {
let theta = (i as f64) * std::f64::consts::TAU / (segments as f64);
pts.push(Point2D::new(
center.x + radius * theta.cos(),
center.y + radius * theta.sin(),
));
}
contours.push(pts);
}
SvgElement::Polyline { points, .. } => {
if points.len() >= 3 {
contours.push(points);
}
}
_ => {}
}
}
if contours.is_empty() {
contours.push(vec![
Point2D::new(0.0, 0.0),
Point2D::new(100.0, 0.0),
Point2D::new(100.0, 100.0),
Point2D::new(0.0, 100.0),
]);
}
let extrusion_height = 20.0;
let mut vertices: Vec<Pt3> = Vec::new();
let mut faces: Vec<Vec<usize>> = Vec::new();
for contour in contours {
let n = contour.len();
if n < 3 {
continue;
}
let base_idx = vertices.len();
for pt in &contour {
vertices.push(Pt3 {
x: pt.x,
y: -pt.y,
z: 0.0,
});
}
for pt in &contour {
vertices.push(Pt3 {
x: pt.x,
y: -pt.y,
z: extrusion_height,
});
}
for i in 1..n - 1 {
faces.push(vec![base_idx, base_idx + i + 1, base_idx + i]);
}
for i in 1..n - 1 {
faces.push(vec![base_idx + n, base_idx + n + i, base_idx + n + i + 1]);
}
for i in 0..n {
let next = (i + 1) % n;
let b0 = base_idx + i;
let b1 = base_idx + next;
let t0 = base_idx + n + i;
let t1 = base_idx + n + next;
faces.push(vec![b0, b1, t1]);
faces.push(vec![b0, t1, t0]);
}
}
writeln!(writer, "ply")?;
writeln!(writer, "format ascii 1.0")?;
writeln!(writer, "comment Generated by docsvg")?;
writeln!(writer, "element vertex {}", vertices.len())?;
writeln!(writer, "property float x")?;
writeln!(writer, "property float y")?;
writeln!(writer, "property float z")?;
writeln!(writer, "element face {}", faces.len())?;
writeln!(writer, "property list uchar int vertex_indices")?;
writeln!(writer, "end_header")?;
for v in &vertices {
writeln!(writer, "{:.4} {:.4} {:.4}", v.x, v.y, v.z)?;
}
for f in &faces {
write!(writer, "{}", f.len())?;
for idx in f {
write!(writer, " {}", idx)?;
}
writeln!(writer)?;
}
Ok(())
}