Skip to content

Commit 3b62799

Browse files
committed
Do multiple chamfer/fillet in one API call
Also add a tolerance param for chamfer calls.
1 parent e9f6ebb commit 3b62799

File tree

4 files changed

+114
-70
lines changed

4 files changed

+114
-70
lines changed

docs/kcl-std/functions/std-solid-chamfer.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ chamfer(
1212
@solid: Solid,
1313
length: number(Length),
1414
tags: [Edge; 1+],
15+
tolerance?: number(Length),
1516
tag?: tag,
1617
): Solid
1718
```
@@ -27,6 +28,7 @@ a sharp, straight transitional edge.
2728
| `solid` | [`Solid`](/docs/kcl-std/types/std-types-Solid) | The solid whose edges should be chamfered | Yes |
2829
| `length` | `number(Length)` | The length of the chamfer | Yes |
2930
| `tags` | [`[Edge; 1+]`](/docs/kcl-std/types/std-types-Edge) | The paths you want to chamfer | Yes |
31+
| `tolerance` | `number(Length)` | The tolerance for this fillet | No |
3032
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this chamfer | No |
3133

3234
### Returns

rust/kcl-lib/src/std/chamfer.rs

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,21 @@ pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001;
2121
pub async fn chamfer(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
2222
let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::Primitive(PrimitiveType::Solid), exec_state)?;
2323
let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?;
24+
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
2425
let tags = args.kw_arg_array_and_source::<EdgeReference>("tags")?;
2526
let tag = args.get_kw_arg_opt("tag")?;
2627

2728
super::fillet::validate_unique(&tags)?;
2829
let tags: Vec<EdgeReference> = tags.into_iter().map(|item| item.0).collect();
29-
let value = inner_chamfer(solid, length, tags, tag, exec_state, args).await?;
30+
let value = inner_chamfer(solid, length, tags, tolerance, tag, exec_state, args).await?;
3031
Ok(KclValue::Solid { value })
3132
}
3233

3334
async fn inner_chamfer(
3435
solid: Box<Solid>,
3536
length: TyF64,
3637
tags: Vec<EdgeReference>,
38+
tolerance: Option<TyF64>,
3739
tag: Option<TagNode>,
3840
exec_state: &mut ExecState,
3941
args: Args,
@@ -46,47 +48,63 @@ async fn inner_chamfer(
4648
source_ranges: vec![args.source_range],
4749
}));
4850
}
51+
if tags.is_empty() {
52+
return Err(KclError::Semantic(KclErrorDetails {
53+
source_ranges: vec![args.source_range],
54+
message: "You must chamfer at least one tag".to_owned(),
55+
}));
56+
}
4957

5058
let mut solid = solid.clone();
51-
for edge_tag in tags {
52-
let edge_id = match edge_tag {
53-
EdgeReference::Uuid(uuid) => uuid,
54-
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
55-
};
59+
let edge_ids: Vec<_> = tags
60+
.into_iter()
61+
.map(|edge_tag| {
62+
let id = match edge_tag {
63+
EdgeReference::Uuid(uuid) => uuid,
64+
EdgeReference::Tag(edge_tag) => args.get_tag_engine_info(exec_state, &edge_tag)?.id,
65+
};
66+
Ok::<_, KclError>(id)
67+
})
68+
.collect::<Result<Vec<_>, _>>()?;
5669

57-
let id = exec_state.next_uuid();
58-
args.batch_end_cmd(
59-
id,
60-
ModelingCmd::from(mcmd::Solid3dFilletEdge {
61-
edge_id: None,
62-
edge_ids: vec![edge_id],
63-
extra_face_ids: vec![],
64-
strategy: Default::default(),
65-
object_id: solid.id,
66-
radius: LengthUnit(length.to_mm()),
67-
tolerance: LengthUnit(DEFAULT_TOLERANCE), // We can let the user set this in the future.
68-
cut_type: CutType::Chamfer,
69-
}),
70-
)
71-
.await?;
70+
let id = exec_state.next_uuid();
71+
let mut extra_face_ids = Vec::new();
72+
let num_extra_ids = edge_ids.len() - 1;
73+
for _ in 0..num_extra_ids {
74+
extra_face_ids.push(exec_state.next_uuid());
75+
}
76+
args.batch_end_cmd(
77+
id,
78+
ModelingCmd::from(mcmd::Solid3dFilletEdge {
79+
edge_id: None,
80+
edge_ids: edge_ids.clone(),
81+
extra_face_ids,
82+
strategy: Default::default(),
83+
object_id: solid.id,
84+
radius: LengthUnit(length.to_mm()),
85+
tolerance: LengthUnit(tolerance.as_ref().map(|t| t.to_mm()).unwrap_or(DEFAULT_TOLERANCE)),
86+
cut_type: CutType::Chamfer,
87+
}),
88+
)
89+
.await?;
7290

73-
solid.edge_cuts.push(EdgeCut::Chamfer {
74-
id,
75-
edge_id,
76-
length: length.clone(),
77-
tag: Box::new(tag.clone()),
78-
});
91+
let new_edge_cuts = edge_ids.into_iter().map(|edge_id| EdgeCut::Chamfer {
92+
id,
93+
edge_id,
94+
length: length.clone(),
95+
tag: Box::new(tag.clone()),
96+
});
97+
solid.edge_cuts.extend(new_edge_cuts);
7998

80-
if let Some(ref tag) = tag {
81-
solid.value.push(ExtrudeSurface::Chamfer(ChamferSurface {
82-
face_id: id,
83-
tag: Some(tag.clone()),
84-
geo_meta: GeoMeta {
85-
id,
86-
metadata: args.source_range.into(),
87-
},
88-
}));
89-
}
99+
if let Some(ref tag) = tag {
100+
solid.value.push(ExtrudeSurface::Chamfer(ChamferSurface {
101+
face_id: id,
102+
tag: Some(tag.clone()),
103+
geo_meta: GeoMeta {
104+
id,
105+
metadata: args.source_range.into(),
106+
},
107+
}));
90108
}
91109

92110
Ok(solid)

rust/kcl-lib/src/std/fillet.rs

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -81,43 +81,65 @@ async fn inner_fillet(
8181
exec_state: &mut ExecState,
8282
args: Args,
8383
) -> Result<Box<Solid>, KclError> {
84+
// If you try and tag multiple edges with a tagged fillet, we want to return an
85+
// error to the user that they can only tag one edge at a time.
86+
if tag.is_some() && tags.len() > 1 {
87+
return Err(KclError::Type(KclErrorDetails {
88+
message: "You can only tag one edge at a time with a tagged fillet. Either delete the tag for the fillet fn if you don't need it OR separate into individual fillet functions for each tag.".to_string(),
89+
source_ranges: vec![args.source_range],
90+
}));
91+
}
92+
if tags.is_empty() {
93+
return Err(KclError::Semantic(KclErrorDetails {
94+
source_ranges: vec![args.source_range],
95+
message: "You must fillet at least one tag".to_owned(),
96+
}));
97+
}
98+
8499
let mut solid = solid.clone();
85-
for edge_tag in tags {
86-
let edge_id = edge_tag.get_engine_id(exec_state, &args)?;
100+
let edge_ids = tags
101+
.into_iter()
102+
.map(|edge_tag| edge_tag.get_engine_id(exec_state, &args))
103+
.collect::<Result<Vec<_>, _>>()?;
87104

88-
let id = exec_state.next_uuid();
89-
args.batch_end_cmd(
90-
id,
91-
ModelingCmd::from(mcmd::Solid3dFilletEdge {
92-
edge_id: None,
93-
edge_ids: vec![edge_id],
94-
extra_face_ids: vec![],
95-
strategy: Default::default(),
96-
object_id: solid.id,
97-
radius: LengthUnit(radius.to_mm()),
98-
tolerance: LengthUnit(tolerance.as_ref().map(|t| t.to_mm()).unwrap_or(DEFAULT_TOLERANCE)),
99-
cut_type: CutType::Fillet,
100-
}),
101-
)
102-
.await?;
105+
let id = exec_state.next_uuid();
106+
let mut extra_face_ids = Vec::new();
107+
let num_extra_ids = edge_ids.len() - 1;
108+
for _ in 0..num_extra_ids {
109+
extra_face_ids.push(exec_state.next_uuid());
110+
}
111+
args.batch_end_cmd(
112+
id,
113+
ModelingCmd::from(mcmd::Solid3dFilletEdge {
114+
edge_id: None,
115+
edge_ids: edge_ids.clone(),
116+
extra_face_ids,
117+
strategy: Default::default(),
118+
object_id: solid.id,
119+
radius: LengthUnit(radius.to_mm()),
120+
tolerance: LengthUnit(tolerance.as_ref().map(|t| t.to_mm()).unwrap_or(DEFAULT_TOLERANCE)),
121+
cut_type: CutType::Fillet,
122+
}),
123+
)
124+
.await?;
103125

104-
solid.edge_cuts.push(EdgeCut::Fillet {
105-
id,
106-
edge_id,
107-
radius: radius.clone(),
108-
tag: Box::new(tag.clone()),
109-
});
126+
let new_edge_cuts = edge_ids.into_iter().map(|edge_id| EdgeCut::Fillet {
127+
id,
128+
edge_id,
129+
radius: radius.clone(),
130+
tag: Box::new(tag.clone()),
131+
});
132+
solid.edge_cuts.extend(new_edge_cuts);
110133

111-
if let Some(ref tag) = tag {
112-
solid.value.push(ExtrudeSurface::Fillet(FilletSurface {
113-
face_id: id,
114-
tag: Some(tag.clone()),
115-
geo_meta: GeoMeta {
116-
id,
117-
metadata: args.source_range.into(),
118-
},
119-
}));
120-
}
134+
if let Some(ref tag) = tag {
135+
solid.value.push(ExtrudeSurface::Fillet(FilletSurface {
136+
face_id: id,
137+
tag: Some(tag.clone()),
138+
geo_meta: GeoMeta {
139+
id,
140+
metadata: args.source_range.into(),
141+
},
142+
}));
121143
}
122144

123145
Ok(solid)

rust/kcl-lib/std/solid.kcl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ export fn chamfer(
144144
length: number(Length),
145145
/// The paths you want to chamfer
146146
tags: [Edge; 1+],
147+
/// The tolerance for this fillet
148+
tolerance?: number(Length),
147149
/// Create a new tag which refers to this chamfer
148150
tag?: tag,
149151
): Solid {}

0 commit comments

Comments
 (0)