allow for sketching on the face of a chamfer in kcl (#2760)
* updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * cleanup Signed-off-by: Jess Frazelle <github@jessfraz.com> * lots of cleanup Signed-off-by: Jess Frazelle <github@jessfraz.com> * lots more cleanup Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * more cleaniup Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix typos Signed-off-by: Jess Frazelle <github@jessfraz.com> * add to known issues Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -31,10 +31,10 @@ use crate::{
|
||||
docs::StdLibFn,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{
|
||||
ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, MemoryItem, Metadata, ProgramMemory, SketchGroup,
|
||||
SketchGroupSet, SketchSurface, SourceRange,
|
||||
ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory,
|
||||
SketchGroup, SketchGroupSet, SketchSurface, SourceRange,
|
||||
},
|
||||
std::{kcl_stdlib::KclStdLibFn, sketch::SketchOnFaceTag},
|
||||
std::{kcl_stdlib::KclStdLibFn, sketch::FaceTag},
|
||||
};
|
||||
|
||||
pub type StdFn = fn(Args) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<MemoryItem, KclError>> + Send>>;
|
||||
@ -252,12 +252,10 @@ impl Args {
|
||||
}
|
||||
|
||||
/// Flush just the fillets and chamfers for this specific ExtrudeGroupSet.
|
||||
pub async fn flush_batch_for_extrude_group_set(&self, extrude_group_set: &ExtrudeGroupSet) -> Result<(), KclError> {
|
||||
let extrude_groups = match extrude_group_set {
|
||||
ExtrudeGroupSet::ExtrudeGroup(eg) => vec![eg.clone()],
|
||||
ExtrudeGroupSet::ExtrudeGroups(egs) => egs.clone(),
|
||||
};
|
||||
|
||||
pub async fn flush_batch_for_extrude_group_set(
|
||||
&self,
|
||||
extrude_groups: Vec<Box<ExtrudeGroup>>,
|
||||
) -> Result<(), KclError> {
|
||||
// Make sure we don't traverse sketch_groups more than once.
|
||||
let mut traversed_sketch_groups = Vec::new();
|
||||
|
||||
@ -641,9 +639,7 @@ impl Args {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_data_and_optional_tag<T: serde::de::DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<(T, Option<SketchOnFaceTag>), KclError> {
|
||||
fn get_data_and_optional_tag<T: serde::de::DeserializeOwned>(&self) -> Result<(T, Option<FaceTag>), KclError> {
|
||||
let first_value = self
|
||||
.args
|
||||
.first()
|
||||
@ -663,9 +659,9 @@ impl Args {
|
||||
})?;
|
||||
|
||||
if let Some(second_value) = self.args.get(1) {
|
||||
let tag: SketchOnFaceTag = serde_json::from_value(second_value.get_json_value()?).map_err(|e| {
|
||||
let tag: FaceTag = serde_json::from_value(second_value.get_json_value()?).map_err(|e| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!("Failed to deserialize SketchOnFaceTag from JSON: {}", e),
|
||||
message: format!("Failed to deserialize FaceTag from JSON: {}", e),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
@ -933,6 +929,57 @@ impl Args {
|
||||
Ok((data, extrude_group))
|
||||
}
|
||||
|
||||
fn get_data_and_extrude_group_and_tag<T: serde::de::DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<(T, Box<ExtrudeGroup>, Option<String>), KclError> {
|
||||
let first_value = self
|
||||
.args
|
||||
.first()
|
||||
.ok_or_else(|| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a struct as the first argument, found `{:?}`", self.args),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?
|
||||
.get_json_value()?;
|
||||
|
||||
let data: T = serde_json::from_value(first_value).map_err(|e| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!("Failed to deserialize struct from JSON: {}", e),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
let second_value = self.args.get(1).ok_or_else(|| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected an ExtrudeGroup as the second argument, found `{:?}`",
|
||||
self.args
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
let extrude_group = if let MemoryItem::ExtrudeGroup(eg) = second_value {
|
||||
eg.clone()
|
||||
} else {
|
||||
return Err(KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected an ExtrudeGroup as the second argument, found `{:?}`",
|
||||
self.args
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
}));
|
||||
};
|
||||
let tag = if let Some(tag) = self.args.get(2) {
|
||||
tag.get_json_opt()?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok((data, extrude_group, tag))
|
||||
}
|
||||
|
||||
fn get_segment_name_to_number_sketch_group(&self) -> Result<(String, f64, Box<SketchGroup>), KclError> {
|
||||
// Iterate over our args, the first argument should be a UserVal with a string value.
|
||||
// The second argument should be a number.
|
||||
@ -1024,6 +1071,59 @@ impl Args {
|
||||
|
||||
Ok((number, sketch_set))
|
||||
}
|
||||
|
||||
pub async fn get_adjacent_face_to_tag(
|
||||
&self,
|
||||
extrude_group: &ExtrudeGroup,
|
||||
tag: &str,
|
||||
must_be_planar: bool,
|
||||
) -> Result<uuid::Uuid, KclError> {
|
||||
if tag.is_empty() {
|
||||
return Err(KclError::Type(KclErrorDetails {
|
||||
message: "Expected a non-empty tag for the face".to_string(),
|
||||
source_ranges: vec![self.source_range],
|
||||
}));
|
||||
}
|
||||
|
||||
if let Some(face_from_surface) = extrude_group
|
||||
.value
|
||||
.iter()
|
||||
.find_map(|extrude_surface| match extrude_surface {
|
||||
ExtrudeSurface::ExtrudePlane(extrude_plane) if extrude_plane.name == tag => {
|
||||
Some(Ok(extrude_plane.face_id))
|
||||
}
|
||||
// The must be planar check must be called before the arc check.
|
||||
ExtrudeSurface::ExtrudeArc(_) if must_be_planar => Some(Err(KclError::Type(KclErrorDetails {
|
||||
message: format!("Tag `{}` is a non-planar surface", tag),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))),
|
||||
ExtrudeSurface::ExtrudeArc(extrude_arc) if extrude_arc.name == tag => Some(Ok(extrude_arc.face_id)),
|
||||
ExtrudeSurface::ExtrudePlane(_) | ExtrudeSurface::ExtrudeArc(_) => None,
|
||||
})
|
||||
{
|
||||
return face_from_surface;
|
||||
}
|
||||
|
||||
// A face could also be the result of a chamfer or fillet.
|
||||
if let Some(face_from_chamfer_fillet) = extrude_group.fillet_or_chamfers.iter().find_map(|fc| {
|
||||
if fc.tag() == Some(tag) {
|
||||
Some(Ok(fc.id()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
// We want to make sure we execute the fillet before this operation.
|
||||
self.flush_batch_for_extrude_group_set(extrude_group.into()).await?;
|
||||
|
||||
return face_from_chamfer_fillet;
|
||||
}
|
||||
|
||||
// If we still haven't found the face, return an error.
|
||||
Err(KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a face with the tag `{}`", tag),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the length of the given leg.
|
||||
|
Reference in New Issue
Block a user