1use std::collections::HashMap;
4
5#[derive(Clone, Debug, PartialEq)]
6pub struct Layer {
7 pub name: String,
8 pub color_hex: String,
9 pub linetype: String,
10 pub is_off: bool,
11 pub is_frozen: bool,
12 pub line_weight: Option<f64>,
13}
14
15impl Default for Layer {
16 fn default() -> Self {
17 Self {
18 name: "0".into(),
19 color_hex: "#000000".into(),
20 linetype: "CONTINUOUS".into(),
21 is_off: false,
22 is_frozen: false,
23 line_weight: None,
24 }
25 }
26}
27
28#[derive(Clone, Debug, PartialEq)]
29pub struct LineType {
30 pub name: String,
31 pub description: String,
32 pub pattern: Vec<f64>,
34}
35
36#[derive(Clone, Copy, Debug, PartialEq)]
37pub struct LwVertex {
38 pub x: f64,
39 pub y: f64,
40 pub bulge: f64,
41}
42
43#[derive(Clone, Debug, PartialEq)]
44#[allow(dead_code)]
45pub enum HatchBoundary {
46 Polyline {
47 vertices: Vec<LwVertex>,
48 is_closed: bool,
49 },
50 Edges(Vec<Entity>),
51}
52
53#[derive(Clone, Debug, PartialEq)]
54pub enum Entity {
55 Line {
56 start: (f64, f64),
57 end: (f64, f64),
58 layer: String,
59 color: Option<String>,
60 line_weight: Option<f64>,
61 linetype: Option<String>,
62 },
63 Point {
64 pt: (f64, f64),
65 layer: String,
66 color: Option<String>,
67 },
68 Circle {
69 center: (f64, f64),
70 radius: f64,
71 layer: String,
72 color: Option<String>,
73 line_weight: Option<f64>,
74 linetype: Option<String>,
75 },
76 Arc {
77 center: (f64, f64),
78 radius: f64,
79 start_deg: f64,
80 end_deg: f64,
81 layer: String,
82 color: Option<String>,
83 line_weight: Option<f64>,
84 linetype: Option<String>,
85 },
86 Ellipse {
87 center: (f64, f64),
88 major_axis: (f64, f64),
89 axis_ratio: f64,
90 start_param: f64,
91 end_param: f64,
92 layer: String,
93 color: Option<String>,
94 line_weight: Option<f64>,
95 linetype: Option<String>,
96 },
97 LwPolyline {
98 vertices: Vec<LwVertex>,
99 is_closed: bool,
100 layer: String,
101 color: Option<String>,
102 line_weight: Option<f64>,
103 linetype: Option<String>,
104 },
105 Spline {
106 degree: usize,
107 control_points: Vec<(f64, f64)>,
108 knots: Vec<f64>,
109 is_closed: bool,
110 layer: String,
111 color: Option<String>,
112 line_weight: Option<f64>,
113 },
114 Solid {
115 points: [(f64, f64); 4],
116 layer: String,
117 color: Option<String>,
118 },
119 Text {
120 text: String,
121 insert: (f64, f64),
122 height: f64,
123 rotation_deg: f64,
124 layer: String,
125 color: Option<String>,
126 h_align: u8,
127 v_align: u8,
128 },
129 MText {
130 text: String,
131 insert: (f64, f64),
132 height: f64,
133 rotation_deg: f64,
134 layer: String,
135 color: Option<String>,
136 attachment: u8,
137 },
138 Insert {
139 block_name: String,
140 insert: (f64, f64),
141 scale: (f64, f64),
142 rotation_deg: f64,
143 layer: String,
144 color: Option<String>,
145 line_weight: Option<f64>,
146 },
147 Hatch {
148 boundaries: Vec<HatchBoundary>,
149 is_solid: bool,
150 pattern_name: String,
151 layer: String,
152 color: Option<String>,
153 },
154 Dimension {
155 block_name: Option<String>,
156 text: String,
157 insert: (f64, f64),
158 layer: String,
159 color: Option<String>,
160 },
161 Leader {
162 vertices: Vec<(f64, f64)>,
163 layer: String,
164 color: Option<String>,
165 },
166}
167
168impl Entity {
169 #[must_use]
170 pub fn layer(&self) -> &str {
171 match self {
172 Self::Line { layer, .. }
173 | Self::Point { layer, .. }
174 | Self::Circle { layer, .. }
175 | Self::Arc { layer, .. }
176 | Self::Ellipse { layer, .. }
177 | Self::LwPolyline { layer, .. }
178 | Self::Spline { layer, .. }
179 | Self::Solid { layer, .. }
180 | Self::Text { layer, .. }
181 | Self::MText { layer, .. }
182 | Self::Insert { layer, .. }
183 | Self::Hatch { layer, .. }
184 | Self::Dimension { layer, .. }
185 | Self::Leader { layer, .. } => layer.as_str(),
186 }
187 }
188}
189
190#[derive(Clone, Debug, PartialEq)]
191pub struct Block {
192 pub name: String,
193 pub base_point: (f64, f64),
194 pub entities: Vec<Entity>,
195}
196
197#[derive(Clone, Debug, Default)]
198pub struct DxfDocument {
199 pub layers: HashMap<String, Layer>,
200 pub linetypes: HashMap<String, LineType>,
201 pub blocks: HashMap<String, Block>,
202 pub entities: Vec<Entity>,
203 pub ext_min: Option<(f64, f64)>,
204 pub ext_max: Option<(f64, f64)>,
205 pub ins_units: u16,
206}
207
208impl DxfDocument {
209 #[must_use]
211 pub fn find_layer(&self, name: &str) -> Option<&Layer> {
212 if let Some(l) = self.layers.get(name) {
213 return Some(l);
214 }
215 let lower = name.to_ascii_lowercase();
216 self.layers
217 .iter()
218 .find(|(k, _)| k.eq_ignore_ascii_case(&lower))
219 .map(|(_, v)| v)
220 }
221
222 #[must_use]
224 pub fn find_block(&self, name: &str) -> Option<&Block> {
225 if let Some(b) = self.blocks.get(name) {
226 return Some(b);
227 }
228 let lower = name.to_ascii_lowercase();
229 self.blocks
230 .iter()
231 .find(|(k, _)| k.eq_ignore_ascii_case(&lower))
232 .map(|(_, v)| v)
233 }
234
235 #[must_use]
237 pub fn find_linetype(&self, name: &str) -> Option<&LineType> {
238 if let Some(lt) = self.linetypes.get(name) {
239 return Some(lt);
240 }
241 let lower = name.to_ascii_lowercase();
242 self.linetypes
243 .iter()
244 .find(|(k, _)| k.eq_ignore_ascii_case(&lower))
245 .map(|(_, v)| v)
246 }
247}