99 let τ = 0.05; |
99 let τ = 0.05; |
100 |
100 |
101 std::fs::create_dir_all(PREFIX)?; |
101 std::fs::create_dir_all(PREFIX)?; |
102 for face in Face::all() { |
102 for face in Face::all() { |
103 write_face_csv(format!("{PREFIX}/{face}"), face, 32, |x| f.apply(x) + g.apply(x))?; |
103 write_face_csv(format!("{PREFIX}/{face}"), face, 32, |x| f.apply(x) + g.apply(x))?; |
104 write_face_img(format!("{PREFIX}/{face}"), face, 128, |x| f.apply(x) + g.apply(x))?; |
104 } |
105 } |
105 write_face_imgs(128, |x| f.apply(x) + g.apply(x))?; |
106 |
106 |
107 run_and_save("x1", &f, &g, OnCube::new(F3, Loc([0.1, 0.7])), τ)?; |
107 run_and_save("x1", &f, &g, OnCube::new(F3, Loc([0.1, 0.7])), τ)?; |
108 run_and_save("x2", &f, &g, OnCube::new(F2, Loc([0.1, 0.7])), τ)?; |
108 run_and_save("x2", &f, &g, OnCube::new(F2, Loc([0.1, 0.7])), τ)?; |
109 run_and_save("x3", &f, &g, OnCube::new(F6, Loc([0.6, 0.2])), τ) |
109 run_and_save("x3", &f, &g, OnCube::new(F6, Loc([0.6, 0.2])), τ) |
110 } |
110 } |
143 Ok(()) |
143 Ok(()) |
144 } |
144 } |
145 |
145 |
146 /// Writes the values of `f` on `face` of a [`OnCube`] into a PNG file |
146 /// Writes the values of `f` on `face` of a [`OnCube`] into a PNG file |
147 /// with resolution `n × n`. |
147 /// with resolution `n × n`. |
148 fn write_face_img(filename : String, face : Face, n : usize, mut f : impl FnMut(&OnCube) -> f64) -> DynError { |
148 fn write_face_imgs(n : usize, mut f : impl FnMut(&OnCube) -> f64) -> DynError { |
149 let mut img = ImageBuffer::new(n as u32, n as u32); |
|
150 let grid = LinSpace { |
149 let grid = LinSpace { |
151 start : Loc([0.0, 0.0]), |
150 start : Loc([0.0, 0.0]), |
152 end : Loc([1.0, 1.0]), |
151 end : Loc([1.0, 1.0]), |
153 count : [n, n] |
152 count : [n, n] |
154 }; |
153 }; |
155 let rawdata : Vec<_> = grid.into_iter() |
154 |
156 .map(|x| f(&OnCube::new(face, x))) |
155 let mut m = 0.0; |
157 .collect(); |
156 let mut datas = Vec::new(); |
158 let a = rawdata.iter().copied().reduce(f64::max).unwrap(); |
157 |
159 img.pixels_mut() |
158 for face in Face::all() { |
160 .zip(rawdata) |
159 let rawdata : Vec<_> = grid.into_iter() |
161 .for_each(|(p, v)| { |
160 .map(|Loc([x,y])| f(&OnCube::new(face, Loc([x, 1.0-y])))) |
162 let t = v/a; |
161 .collect(); |
163 let rgb = [1.0-t, 1.0-t, 1.0]; |
162 m = rawdata.iter().copied().fold(m, f64::max); |
164 *p = Rgb(rgb.map(|v| (v*(u8::RANGE_MAX as f64)) as u8)) |
163 datas.push((face, rawdata)); |
165 }); |
164 } |
166 |
165 |
167 img.save_with_format(format!("{filename}.png"), ImageFormat::Png)?; |
166 for (face, rawdata) in datas { |
|
167 let mut img = ImageBuffer::new(n as u32, n as u32); |
|
168 img.pixels_mut() |
|
169 .zip(rawdata) |
|
170 .for_each(|(p, v)| { |
|
171 let t = v/m; |
|
172 // A very colourful option for bug hunting. |
|
173 //let rgb = [(50.0*t).cos(), (20.0*t).sin(), (3.0*t).cos()]; |
|
174 let rgb = [1.0-t, 1.0-t, 1.0]; |
|
175 *p = Rgb(rgb.map(|v| (v*(u8::RANGE_MAX as f64)) as u8)) |
|
176 }); |
|
177 |
|
178 img.save_with_format(format!("{PREFIX}/{face}.png"), ImageFormat::Png)?; |
|
179 } |
168 |
180 |
169 Ok(()) |
181 Ok(()) |
170 } |
182 } |
171 |
183 |
172 /// Writes the values of `f` on `face` of a [`OnCube`] into a CSV file |
184 /// Writes the values of `f` on `face` of a [`OnCube`] into a CSV file |