altium_format/records/pcb/
component.rs1use super::{PcbPad, PcbRecord};
4use crate::types::{Coord, CoordRect, ParameterCollection};
5
6#[derive(Debug, Clone, Default)]
8pub struct PcbComponent {
9 pub pattern: String,
11 pub description: String,
13 pub height: Coord,
15 pub item_guid: String,
17 pub revision_guid: String,
19 pub primitives: Vec<PcbRecord>,
21}
22
23impl PcbComponent {
24 pub fn import_from_parameters(&mut self, p: &ParameterCollection) {
26 self.pattern = p
27 .get("PATTERN")
28 .map(|v| v.as_str().to_string())
29 .unwrap_or_default();
30 self.height = Coord::from_raw(p.get("HEIGHT").map(|v| v.as_int_or(0)).unwrap_or(0));
31 self.description = p
32 .get("DESCRIPTION")
33 .map(|v| v.as_str().to_string())
34 .unwrap_or_default();
35 self.item_guid = p
36 .get("ITEMGUID")
37 .map(|v| v.as_str().to_string())
38 .unwrap_or_default();
39 self.revision_guid = p
40 .get("REVISIONGUID")
41 .map(|v| v.as_str().to_string())
42 .unwrap_or_default();
43 }
44
45 pub fn export_to_parameters(&self) -> ParameterCollection {
47 let mut params = ParameterCollection::new();
48 params.add("PATTERN", &self.pattern);
49 params.add_int("HEIGHT", self.height.to_raw());
50 if !self.description.is_empty() {
51 params.add("DESCRIPTION", &self.description);
52 }
53 if !self.item_guid.is_empty() {
54 params.add("ITEMGUID", &self.item_guid);
55 }
56 if !self.revision_guid.is_empty() {
57 params.add("REVISIONGUID", &self.revision_guid);
58 }
59 params
60 }
61
62 pub fn name(&self) -> &str {
64 &self.pattern
65 }
66
67 pub fn pad_count(&self) -> usize {
69 self.primitives
70 .iter()
71 .filter(|p| matches!(p, PcbRecord::Pad(_)))
72 .count()
73 }
74
75 pub fn pads(&self) -> impl Iterator<Item = &PcbPad> {
77 self.primitives.iter().filter_map(|p| {
78 if let PcbRecord::Pad(pad) = p {
79 Some(pad.as_ref())
80 } else {
81 None
82 }
83 })
84 }
85
86 pub fn primitive_count(&self) -> usize {
88 self.primitives.len()
89 }
90
91 pub fn calculate_bounds(&self) -> CoordRect {
93 let mut bounds = CoordRect::default();
94 let mut first = true;
95
96 for prim in &self.primitives {
97 let prim_bounds = match prim {
98 PcbRecord::Arc(r) => r.calculate_bounds(),
99 PcbRecord::Pad(r) => r.calculate_bounds(),
100 PcbRecord::Via(r) => r.calculate_bounds(),
101 PcbRecord::Track(r) => r.calculate_bounds(),
102 PcbRecord::Text(r) => r.calculate_bounds(),
103 PcbRecord::Fill(r) => r.calculate_bounds(),
104 PcbRecord::Region(r) => r.calculate_bounds(),
105 PcbRecord::ComponentBody(r) => r.calculate_bounds(),
106 PcbRecord::Polygon(_) => continue, PcbRecord::Unknown { .. } => continue,
108 };
109
110 if first {
111 bounds = prim_bounds;
112 first = false;
113 } else {
114 bounds = bounds.union(prim_bounds);
115 }
116 }
117
118 bounds
119 }
120}