polygon_offsetting/
draw_svg.rs

1use crate::Offset;
2
3use std::path::Path;
4use std::fs::File;
5use std::io::Write;
6
7#[derive(Debug, Default)]
8pub struct Segm {
9    p1: (f64, f64),
10    p2: (f64, f64)
11}
12
13pub fn draw_svg_offset(
14    initial_contour: &Vec<(f64, f64)>,
15    offset: &Offset,
16    dir_path: &str,
17    filename: &str
18) -> Result <(), Box<dyn std::error::Error>> {
19    let mut segments: Vec<Segm> = Vec::new();
20    let mut segms: Vec<Segm> = Vec::new();
21
22    for i in 1..initial_contour.len() {
23        let mut sgmt: Segm = Segm::default();
24
25        sgmt.p1.0 = initial_contour[i - 1].0;
26        sgmt.p1.1 = initial_contour[i - 1].1;
27        if i == initial_contour.len() { 
28            sgmt.p2.0 = initial_contour[0].0;
29            sgmt.p2.1 = initial_contour[0].1;
30            segms.push(sgmt);
31            break ;
32        }
33        sgmt.p2.0 = initial_contour[i].0;
34        sgmt.p2.1 = initial_contour[i].1;
35        segms.push(sgmt);
36    }
37
38    let contour_offset = offset.contour.clone();
39    for i in 1..contour_offset.len() {
40        let mut sgmt: Segm = Segm::default();
41
42        sgmt.p1.0 = contour_offset[i - 1].0;
43        sgmt.p1.1 = contour_offset[i - 1].1;
44        if i == contour_offset.len() { 
45            sgmt.p2.0 = contour_offset[0].0;
46            sgmt.p2.1 = contour_offset[0].1;
47            segms.push(sgmt);
48            break ;
49        }
50        sgmt.p2.0 = contour_offset[i].0;
51        sgmt.p2.1 = contour_offset[i].1;
52        segms.push(sgmt);
53    }
54
55    segments.append(&mut segms);
56
57    let mut x_min1 = 0.;
58    let mut y_min1 = 0.;
59    for i in 0..segments.len() {
60        if i == 0 {
61            x_min1 = segments[i].p1.0;
62            y_min1 = segments[i].p1.1;
63        } else {
64            if segments[i].p1.0 < x_min1 { x_min1 = segments[i].p1.0; }
65            if segments[i].p2.0 < x_min1 { x_min1 = segments[i].p2.0; }
66            if segments[i].p1.1 < y_min1 { y_min1 = segments[i].p1.1; }
67            if segments[i].p2.1 < y_min1 { y_min1 = segments[i].p2.1; }
68        }
69    }
70    segments.iter_mut().for_each(|p| {
71        p.p1.0 -= x_min1;
72        p.p2.0 -= x_min1;
73        p.p1.1 -= y_min1;
74        p.p2.1 -= y_min1;
75
76    });
77
78    let mut max_x: f64 = std::f64::NEG_INFINITY;
79    let mut max_y: f64 = std::f64::NEG_INFINITY;
80    segments.iter().for_each(|segment| {
81        let p = &segment.p1;
82        if max_x < p.0 { max_x = p.0 }
83        if max_y < p.1 { max_x = p.1 }
84
85        let p = &segment.p2;
86        if max_x < p.0 { max_x = p.0 }
87        if max_y < p.1 { max_y = p.1 }
88    });
89
90    let resize_width =  max_x / 1800.0;
91    let resize_height = max_y / 850.0;
92    let resize = if resize_width > resize_height { resize_width } else { resize_height };
93    segments.iter_mut().for_each(|s| {
94        s.p1.0 = s.p1.0 / resize;
95        s.p1.1 = s.p1.1 / resize;
96        s.p2.0 = s.p2.0 / resize;
97        s.p2.1 = s.p2.1 / resize;
98    });
99
100    let mut viewbox = vec![
101        std::f64::INFINITY,
102        std::f64::INFINITY,  
103        std::f64::NEG_INFINITY,
104        std::f64::NEG_INFINITY
105    ];
106
107    segments.iter().for_each(|segment| {
108        let p = &segment.p1;
109        if viewbox[0] > p.0 { viewbox[0] = p.0 }
110        if viewbox[1] > p.1 { viewbox[1] = p.1 }
111        if viewbox[2] < p.0 { viewbox[2] = p.0 }
112        if viewbox[3] < p.1 { viewbox[3] = p.1 }
113
114        let p = &segment.p2;
115        if viewbox[0] > p.0 { viewbox[0] = p.0 }
116        if viewbox[1] > p.1 { viewbox[1] = p.1 }
117        if viewbox[2] < p.0 { viewbox[2] = p.0 }
118        if viewbox[3] < p.1 { viewbox[3] = p.1 }
119    });
120
121    let mut txt = format!(
122        "<?xml version='1.0' encoding='UTF-8' standalone='no'?>
123            <svg xmlns='http://www.w3.org/2000/svg' viewBox='{} {} {} {}' id='export' style='background-color:white'>\n", 
124        viewbox[0] - 50., viewbox[1] - 50. , viewbox[2] + 100., viewbox[3] + 100. ).to_string();
125
126    let mut i: usize = 0;
127    segments.iter().for_each(|segment| {
128        let p1 = segment.p1;
129        let p2 = segment.p2;
130        
131        let mut path = "M ".to_string();
132        
133        path = format!("{} {} {} ", path, p1.0, (viewbox[3] - viewbox[1]) - (p1.1 - viewbox[1]));
134        path = format!("{} {} {} ", path, p2.0, (viewbox[3] - viewbox[1]) - (p2.1 - viewbox[1]));
135        
136        
137        let color = "#000000";
138        let width = 1.;
139
140        txt = format!("{}<path style='fill:none;stroke-width:{};stroke:{};' d='{}' id='{}' />\n", txt, width, color, path, 0);
141        i += 1;
142    });
143
144    txt = format!("{}</svg>", txt);
145    let env_path = std::env::current_dir().unwrap().to_str().unwrap().to_string();
146    let dir =  env_path.clone() + &dir_path;
147
148    if !(Path::new(&dir_path).exists()) {
149        std::fs::create_dir_all(&dir)?;
150    }
151    let mut file = File::create(format!("{}.svg", dir.clone() + &filename)).map_err(|e| { 
152        print!("Error on creating offset svg: {:?}", dir.clone() + &filename);
153        e 
154    })?;
155    file.write_all(txt.as_bytes()).unwrap();
156    
157    Ok(())
158}