object.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. use std::{
  2. fs::File,
  3. io::{Cursor, Read, Write},
  4. path::PathBuf,
  5. };
  6. use binrw::{BinRead, BinWriterExt};
  7. use ezcad::{
  8. array_of::ArrayOf,
  9. layer::Layer,
  10. objects::{
  11. circle::Circle,
  12. hatch::{Hatch, HatchFlag, HatchPattern, HatchSetting, Hatches},
  13. rectangle::Rectangle,
  14. Object, ObjectCore, Translate,
  15. },
  16. pen::Pen,
  17. types::{ObjectType, Point},
  18. };
  19. use log::{debug, warn};
  20. use rand::{seq::SliceRandom, thread_rng};
  21. use serde::{de, Deserialize, Serialize};
  22. #[derive(Debug, Serialize, Deserialize)]
  23. #[serde(rename_all = "PascalCase")]
  24. pub struct DeleteObjects {
  25. layer: usize,
  26. object: Option<usize>,
  27. }
  28. impl DeleteObjects {
  29. pub fn delete(&self, layers: &mut ArrayOf<Layer>) {
  30. debug!(
  31. "Deleting layer #{} {}",
  32. match &self.object {
  33. Some(object) => format!("object #{}", object),
  34. None => format!("all objects"),
  35. },
  36. self.layer,
  37. );
  38. let layer: &mut Layer = layers.get_mut(self.layer).expect("Invalid layer index");
  39. match self.object {
  40. Some(index) => {
  41. assert!(index < layer.objects.len(), "Invalid object index");
  42. layer.objects.remove(index);
  43. }
  44. None => layer.objects.clear(),
  45. }
  46. }
  47. }
  48. #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
  49. #[serde(rename_all = "PascalCase")]
  50. pub struct HatchConfig {
  51. line_spacing: f64,
  52. count: Option<u32>,
  53. edge_offset: Option<f64>,
  54. start_offset: Option<f64>,
  55. end_offset: Option<f64>,
  56. angle: Option<f64>,
  57. rotate_angle: Option<f64>,
  58. line_reduction: Option<f64>,
  59. loop_distance: Option<f64>,
  60. loop_count: Option<u32>,
  61. pattern: Option<HatchPattern>,
  62. follow_edge_once: Option<bool>,
  63. cross_hatch: Option<bool>,
  64. }
  65. impl From<HatchConfig> for HatchSetting {
  66. fn from(value: HatchConfig) -> Self {
  67. let mut flags: HatchFlag = match value.pattern {
  68. Some(pattern) => pattern.into(),
  69. None => HatchPattern::Directional.into(),
  70. };
  71. value
  72. .follow_edge_once
  73. .map(|x| flags.set_follow_edge_once(x.into()));
  74. value.cross_hatch.map(|x| flags.set_cross_hatch(x.into()));
  75. if value.start_offset.is_none() && value.end_offset.is_none() {
  76. flags.set_average_distribute_line(1);
  77. }
  78. let mut ret = Self::default();
  79. *ret.line_spacing = value.line_spacing;
  80. value.count.map(|x| *ret.count = x.into());
  81. value.edge_offset.map(|x| *ret.edge_offset = x.into());
  82. value.start_offset.map(|x| *ret.start_offset = x.into());
  83. value.end_offset.map(|x| *ret.end_offset = x.into());
  84. value.angle.map(|x| *ret.angle = x.into());
  85. value.rotate_angle.map(|x| *ret.rotate_angle = x.into());
  86. value.line_reduction.map(|x| *ret.line_reduction = x.into());
  87. value.loop_distance.map(|x| *ret.loop_distance = x.into());
  88. value.loop_count.map(|x| *ret.loop_count = x.into());
  89. *ret.flags = flags;
  90. *ret.enabled = true.into();
  91. ret
  92. }
  93. }
  94. #[derive(Debug, Serialize, Deserialize)]
  95. #[serde(rename_all = "PascalCase")]
  96. pub struct ArrayConfig {
  97. columns: usize,
  98. rows: usize,
  99. spacing: f64,
  100. randomize_order: bool,
  101. starting_pen: u32,
  102. }
  103. #[derive(Debug, Serialize, Deserialize, strum::Display)]
  104. #[serde(rename_all = "PascalCase")]
  105. pub enum InputObject {
  106. Rectangle {
  107. width: f64,
  108. height: f64,
  109. round_corner: Option<f64>,
  110. },
  111. Circle {
  112. radius: f64,
  113. },
  114. Import {
  115. path: PathBuf,
  116. },
  117. Existing {
  118. layer: usize,
  119. object: usize,
  120. },
  121. }
  122. impl InputObject {
  123. fn new(&self, layers: &ArrayOf<Layer>) -> Object {
  124. match self {
  125. InputObject::Rectangle {
  126. width,
  127. height,
  128. round_corner,
  129. } => Object::Rectangle(Rectangle {
  130. corner_a: Point::from((-width / 2.0, -height / 2.0)).into(),
  131. corner_b: Point::from((width / 2.0, height / 2.0)).into(),
  132. round_bottom_left: round_corner.unwrap_or(0.0).into(),
  133. round_bottom_right: round_corner.unwrap_or(0.0).into(),
  134. round_top_left: round_corner.unwrap_or(0.0).into(),
  135. round_top_right: round_corner.unwrap_or(0.0).into(),
  136. ..Default::default()
  137. }),
  138. InputObject::Circle { radius } => Object::Circle(Circle {
  139. radius: (*radius).into(),
  140. ..Default::default()
  141. }),
  142. InputObject::Import { path } => Object::read_from_file(path),
  143. InputObject::Existing { layer, object } => {
  144. let layer: &Layer = layers.get(*layer).expect("Invalid layer index");
  145. layer
  146. .objects
  147. .get(*object)
  148. .expect("Invalid object index")
  149. .clone()
  150. }
  151. }
  152. }
  153. }
  154. #[derive(Debug, Serialize, Deserialize)]
  155. #[serde(rename_all = "PascalCase")]
  156. pub struct ObjectOperation {
  157. input: InputObject,
  158. z: Option<f64>,
  159. origin: Option<Point>,
  160. pen: Option<u32>,
  161. layer: Option<usize>,
  162. array: Option<ArrayConfig>,
  163. hatch: Option<HatchConfig>,
  164. export: Option<PathBuf>,
  165. replace_object: Option<usize>,
  166. }
  167. impl ObjectOperation {
  168. pub fn process(&self, pens: &Vec<Pen>, layers: &mut ArrayOf<Layer>) {
  169. debug!("Processing object {}", self.input);
  170. let mut object: Object = self.input.new(layers);
  171. // Process basic transformation
  172. object.translate(self.origin, self.z);
  173. self.pen.map(|pen| object.set_pen(pen));
  174. // Process conversion to hatch object
  175. // Process array generation of object
  176. let new_objects = self.array.as_ref().map_or(vec![object.clone()], |array| {
  177. let bottom_left: Point = Point {
  178. x: (array.columns - 1) as f64 * array.spacing / -2.0,
  179. y: (array.rows - 1) as f64 * array.spacing / -2.0,
  180. };
  181. // Closure that returns origin point of given index in array, where index starts
  182. // from bottom left and increments to the right and wraps around to the row above
  183. let calc_pt = |index: usize| {
  184. let x_pos: f64 = (index % array.columns) as f64;
  185. let y_pos: f64 = (index / array.columns) as f64;
  186. Point {
  187. x: bottom_left.x + array.spacing * x_pos,
  188. y: bottom_left.y + array.spacing * y_pos,
  189. }
  190. };
  191. // Randomize draw order
  192. let mut seq: Vec<usize> = (0..(array.rows * array.columns)).collect();
  193. if array.randomize_order {
  194. seq.shuffle(&mut thread_rng());
  195. }
  196. // Generate objects
  197. let mut new_obj: Vec<Object> = vec![];
  198. for obj_idx in seq.into_iter() {
  199. let mut object: Object = object.clone();
  200. object.translate(Some(calc_pt(obj_idx)), None);
  201. object.set_pen(array.starting_pen + u32::try_from(obj_idx).unwrap());
  202. new_obj.push(object);
  203. }
  204. new_obj
  205. });
  206. // Process export of object
  207. self.export.as_ref().map(|path| {
  208. if new_objects.len() > 1 {
  209. warn!("Exporting only the first object in list of objects");
  210. } else {
  211. debug!(
  212. "Exporting object {} to '{}'",
  213. new_objects[0],
  214. path.to_string_lossy()
  215. );
  216. }
  217. new_objects[0].write_to_file(path);
  218. });
  219. // Append or replace object in layer
  220. let layer: &mut Layer = layers
  221. .get_mut(self.layer.unwrap_or(0))
  222. .expect("Invalid layer index");
  223. match self.replace_object {
  224. Some(object) => {
  225. // debug!("Replacing object #{} with {}", object, new_objects);
  226. layer.objects.splice(object..=object, new_objects);
  227. }
  228. None => {
  229. layer.objects.extend(new_objects);
  230. }
  231. }
  232. }
  233. }
  234. // #[derive(Debug, Serialize, Deserialize)]
  235. // #[serde(rename_all = "PascalCase")]
  236. // pub struct Array {
  237. // layer: usize,
  238. // z: f64,
  239. // columns: usize,
  240. // rows: usize,
  241. // spacing: f64,
  242. // starting_pen: usize,
  243. // object: InputObject,
  244. // hatch: Option<HatchConfig>,
  245. // }
  246. // impl Array {
  247. // pub fn generate(&self, pens: &Vec<Pen>, layers: &mut ArrayOf<Layer>) {
  248. // debug!(
  249. // "Generating {} x {} array of {:?} with spacing of {} starting from pen #{} on layer #{}",
  250. // self.columns, self.rows, self.object, self.spacing, self.starting_pen, self.layer
  251. // );
  252. // assert!(
  253. // self.rows >= 1 && self.columns >= 1,
  254. // "Invalid row/column value"
  255. // );
  256. // assert!(
  257. // self.starting_pen + (self.rows * self.columns) < pens.len(),
  258. // "Invalid starting pen"
  259. // );
  260. // let layer: &mut Layer = layers.get_mut(self.layer).expect("Invalid layer index");
  261. // let bottom_left: Point = Point {
  262. // x: (self.columns - 1) as f64 * self.spacing / -2.0,
  263. // y: (self.rows - 1) as f64 * self.spacing / -2.0,
  264. // };
  265. // // Closure that returns origin point of given index in array, where index starts
  266. // // from bottom left and increments to the right and wraps around to the row above
  267. // let calc_pt = |index: usize| {
  268. // let x_pos: f64 = (index % self.columns) as f64;
  269. // let y_pos: f64 = (index / self.columns) as f64;
  270. // Point {
  271. // x: bottom_left.x + self.spacing * x_pos,
  272. // y: bottom_left.y + self.spacing * y_pos,
  273. // }
  274. // };
  275. // // Randomize draw order
  276. // let mut seq: Vec<usize> = (0..(self.rows * self.columns)).collect();
  277. // seq.shuffle(&mut thread_rng());
  278. // // Generate objects and append to layer
  279. // for obj_idx in seq.into_iter() {
  280. // let pen: u32 = (self.starting_pen + obj_idx).try_into().unwrap();
  281. // // // Build outline object
  282. // // let mut rect: Rectangle = Rectangle::default();
  283. // // let origin: Point = calc_pt(obj_idx);
  284. // // *rect.corner_a = Point {
  285. // // x: origin.x - self.width / 2.0,
  286. // // y: origin.y - self.height / 2.0,
  287. // // };
  288. // // *rect.corner_b = Point {
  289. // // x: origin.x + self.width / 2.0,
  290. // // y: origin.y + self.height / 2.0,
  291. // // };
  292. // // *rect.core.origin = origin;
  293. // // *rect.core.pen = pen;
  294. // // *rect.core.z = self.z;
  295. // // debug!(
  296. // // "Adding hatched rectangle with pen #{} at {} (from {} to {})",
  297. // // *rect.core.pen, *rect.core.origin, *rect.corner_a, *rect.corner_b
  298. // // );
  299. // // let mut hatch_setting: HatchSetting = self.hatch.into();
  300. // // *hatch_setting.pen = pen;
  301. // // // Build hatch object
  302. // // let hatch: Hatch = Hatch {
  303. // // core: ObjectCore {
  304. // // origin: origin.into(),
  305. // // z: self.z.into(),
  306. // // ..ObjectCore::default(ObjectType::Hatch)
  307. // // },
  308. // // outline: vec![Object::Rectangle(rect)].into(),
  309. // // legacy_setting: vec![hatch_setting.clone()].into(),
  310. // // hatch_settings: vec![hatch_setting.clone()].into(),
  311. // // hatches: Some(Hatches {
  312. // // core: ObjectCore::default(ObjectType::HatchLine),
  313. // // hatch_lines: vec![].into(),
  314. // // }),
  315. // // };
  316. // // layer.objects.push(Object::Hatch(hatch));
  317. // }
  318. // }
  319. // }