Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2025-04-04 15:46:21 -07:00
parent f769322c8f
commit 136fad95aa
4 changed files with 75 additions and 60 deletions

View File

@ -460,6 +460,13 @@ impl Sketch {
}, },
] ]
} }
/// Get the path by the curve ID.
pub fn get_path_by_curve_id(&self, curve_id: uuid::Uuid) -> Option<Path> {
self.paths
.iter()
.find_map(|path| (path.get_id() == curve_id).then(|| path.clone()))
}
} }
/// A sketch type. /// A sketch type.
@ -883,6 +890,11 @@ pub enum Path {
/// The y coordinate. /// The y coordinate.
y: Option<f64>, y: Option<f64>,
}, },
/// An angled line.
AngledLine {
#[serde(flatten)]
base: BasePath,
},
/// A base path. /// A base path.
Base { Base {
#[serde(flatten)] #[serde(flatten)]
@ -903,7 +915,7 @@ pub enum Path {
/// What kind of path is this? /// What kind of path is this?
#[derive(Display)] #[derive(Display)]
enum PathType { pub enum PathType {
ToPoint, ToPoint,
Base, Base,
TangentialArc, TangentialArc,
@ -912,6 +924,7 @@ enum PathType {
CircleThreePoint, CircleThreePoint,
Horizontal, Horizontal,
AngledLineTo, AngledLineTo,
AngledLine,
Arc, Arc,
} }
@ -925,6 +938,7 @@ impl From<&Path> for PathType {
Path::CircleThreePoint { .. } => Self::CircleThreePoint, Path::CircleThreePoint { .. } => Self::CircleThreePoint,
Path::Horizontal { .. } => Self::Horizontal, Path::Horizontal { .. } => Self::Horizontal,
Path::AngledLineTo { .. } => Self::AngledLineTo, Path::AngledLineTo { .. } => Self::AngledLineTo,
Path::AngledLine { .. } => Self::AngledLine,
Path::Base { .. } => Self::Base, Path::Base { .. } => Self::Base,
Path::Arc { .. } => Self::Arc, Path::Arc { .. } => Self::Arc,
Path::ArcThreePoint { .. } => Self::Arc, Path::ArcThreePoint { .. } => Self::Arc,
@ -938,6 +952,7 @@ impl Path {
Path::ToPoint { base } => base.geo_meta.id, Path::ToPoint { base } => base.geo_meta.id,
Path::Horizontal { base, .. } => base.geo_meta.id, Path::Horizontal { base, .. } => base.geo_meta.id,
Path::AngledLineTo { base, .. } => base.geo_meta.id, Path::AngledLineTo { base, .. } => base.geo_meta.id,
Path::AngledLine { base } => base.geo_meta.id,
Path::Base { base } => base.geo_meta.id, Path::Base { base } => base.geo_meta.id,
Path::TangentialArcTo { base, .. } => base.geo_meta.id, Path::TangentialArcTo { base, .. } => base.geo_meta.id,
Path::TangentialArc { base, .. } => base.geo_meta.id, Path::TangentialArc { base, .. } => base.geo_meta.id,
@ -953,6 +968,7 @@ impl Path {
Path::ToPoint { base } => base.tag.clone(), Path::ToPoint { base } => base.tag.clone(),
Path::Horizontal { base, .. } => base.tag.clone(), Path::Horizontal { base, .. } => base.tag.clone(),
Path::AngledLineTo { base, .. } => base.tag.clone(), Path::AngledLineTo { base, .. } => base.tag.clone(),
Path::AngledLine { base, .. } => base.tag.clone(),
Path::Base { base } => base.tag.clone(), Path::Base { base } => base.tag.clone(),
Path::TangentialArcTo { base, .. } => base.tag.clone(), Path::TangentialArcTo { base, .. } => base.tag.clone(),
Path::TangentialArc { base, .. } => base.tag.clone(), Path::TangentialArc { base, .. } => base.tag.clone(),
@ -968,6 +984,7 @@ impl Path {
Path::ToPoint { base } => base, Path::ToPoint { base } => base,
Path::Horizontal { base, .. } => base, Path::Horizontal { base, .. } => base,
Path::AngledLineTo { base, .. } => base, Path::AngledLineTo { base, .. } => base,
Path::AngledLine { base, .. } => base,
Path::Base { base } => base, Path::Base { base } => base,
Path::TangentialArcTo { base, .. } => base, Path::TangentialArcTo { base, .. } => base,
Path::TangentialArc { base, .. } => base, Path::TangentialArc { base, .. } => base,
@ -990,9 +1007,11 @@ impl Path {
/// Length of this path segment, in cartesian plane. /// Length of this path segment, in cartesian plane.
pub fn length(&self) -> f64 { pub fn length(&self) -> f64 {
match self { match self {
Self::ToPoint { .. } | Self::Base { .. } | Self::Horizontal { .. } | Self::AngledLineTo { .. } => { Self::ToPoint { .. }
linear_distance(self.get_from(), self.get_to()) | Self::Base { .. }
} | Self::Horizontal { .. }
| Self::AngledLineTo { .. }
| Self::AngledLine { .. } => linear_distance(self.get_from(), self.get_to()),
Self::TangentialArc { Self::TangentialArc {
base: _, base: _,
center, center,
@ -1036,6 +1055,7 @@ impl Path {
Path::ToPoint { base } => Some(base), Path::ToPoint { base } => Some(base),
Path::Horizontal { base, .. } => Some(base), Path::Horizontal { base, .. } => Some(base),
Path::AngledLineTo { base, .. } => Some(base), Path::AngledLineTo { base, .. } => Some(base),
Path::AngledLine { base, .. } => Some(base),
Path::Base { base } => Some(base), Path::Base { base } => Some(base),
Path::TangentialArcTo { base, .. } => Some(base), Path::TangentialArcTo { base, .. } => Some(base),
Path::TangentialArc { base, .. } => Some(base), Path::TangentialArc { base, .. } => Some(base),
@ -1083,7 +1103,11 @@ impl Path {
radius, radius,
} }
} }
Path::ToPoint { .. } | Path::Horizontal { .. } | Path::AngledLineTo { .. } | Path::Base { .. } => { Path::ToPoint { .. }
| Path::Horizontal { .. }
| Path::AngledLineTo { .. }
| Path::AngledLine { .. }
| Path::Base { .. } => {
let base = self.get_base(); let base = self.get_base();
GetTangentialInfoFromPathsResult::PreviousPoint(base.from) GetTangentialInfoFromPathsResult::PreviousPoint(base.from)
} }

View File

@ -209,59 +209,44 @@ pub(crate) async fn do_post_extrude<'a>(
}; };
// Face filtering attempt in order to resolve https://github.com/KittyCAD/modeling-app/issues/5328 // Face filtering attempt in order to resolve https://github.com/KittyCAD/modeling-app/issues/5328
// In case of a sectional sweep, empirically it looks that the first n faces that are yielded from the sweep // We need to not run Solid3dGetOppositeEdge and Solid3dGetNextAdjacentEdge because it is too
// are the ones that work with GetOppositeEdge and GetNextAdjacentEdge, aka the n sides in the sweep. // hard to know when they work or fail.
// So here we're figuring out that n number as yielded_sides_count here, if !sectional {
// making sure that circle() calls count but close() don't (no length) for (curve_id, face_id) in face_infos
let count_of_first_set_of_faces_if_sectional = if sectional {
sketch
.paths
.iter() .iter()
.filter(|p| { .filter(|face_info| face_info.cap == ExtrusionFaceCapType::None)
let is_circle = matches!(p, Path::Circle { .. }); .filter_map(|face_info| {
let has_length = p.get_base().from != p.get_base().to; if let (Some(curve_id), Some(face_id)) = (face_info.curve_id, face_info.face_id) {
is_circle || has_length Some((curve_id, face_id))
} else {
None
}
}) })
.count() {
} else { // Batch these commands, because the Rust code doesn't actually care about the outcome.
usize::MAX // So, there's no need to await them.
}; // Instead, the Typescript codebases (which handles WebSocket sends when compiled via Wasm)
// uses this to build the artifact graph, which the UI needs.
args.batch_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
edge_id: curve_id,
object_id: sketch.id,
face_id,
}),
)
.await?;
for (curve_id, face_id) in face_infos args.batch_modeling_cmd(
.iter() exec_state.next_uuid(),
.filter(|face_info| face_info.cap == ExtrusionFaceCapType::None) ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
.filter_map(|face_info| { edge_id: curve_id,
if let (Some(curve_id), Some(face_id)) = (face_info.curve_id, face_info.face_id) { object_id: sketch.id,
Some((curve_id, face_id)) face_id,
} else { }),
None )
} .await?;
}) }
.take(count_of_first_set_of_faces_if_sectional)
{
// Batch these commands, because the Rust code doesn't actually care about the outcome.
// So, there's no need to await them.
// Instead, the Typescript codebases (which handles WebSocket sends when compiled via Wasm)
// uses this to build the artifact graph, which the UI needs.
args.batch_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
edge_id: curve_id,
object_id: sketch.id,
face_id,
}),
)
.await?;
args.batch_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
edge_id: curve_id,
object_id: sketch.id,
face_id,
}),
)
.await?;
} }
let Faces { let Faces {
@ -293,7 +278,11 @@ pub(crate) async fn do_post_extrude<'a>(
}); });
Some(extrude_surface) Some(extrude_surface)
} }
Path::Base { .. } | Path::ToPoint { .. } | Path::Horizontal { .. } | Path::AngledLineTo { .. } => { Path::Base { .. }
| Path::ToPoint { .. }
| Path::Horizontal { .. }
| Path::AngledLineTo { .. }
| Path::AngledLine { .. } => {
let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::execution::ExtrudePlane { let extrude_surface = ExtrudeSurface::ExtrudePlane(crate::execution::ExtrudePlane {
face_id: *actual_face_id, face_id: *actual_face_id,
tag: path.get_base().tag.clone(), tag: path.get_base().tag.clone(),

View File

@ -479,7 +479,7 @@ async fn inner_angled_line(
) )
.await?; .await?;
let current_path = Path::ToPoint { let current_path = Path::AngledLine {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
to, to,

View File

@ -140,7 +140,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// }, %) /// }, %)
/// |> xLine(length = 384.93) /// |> xLine(length = 384.93)
/// ///
/// sweep([rectangleSketch, circleSketch], path = sweepPath, sectional = false) /// sweep([rectangleSketch, circleSketch], path = sweepPath)
/// ``` /// ```
/// ``` /// ```
/// // Sectionally sweep one sketch along the path /// // Sectionally sweep one sketch along the path
@ -190,6 +190,8 @@ async fn inner_sweep(
SweepPath::Helix(helix) => helix.value.into(), SweepPath::Helix(helix) => helix.value.into(),
}; };
let sectional = sectional.unwrap_or(true);
let mut solids = Vec::new(); let mut solids = Vec::new();
for sketch in &sketches { for sketch in &sketches {
let id = exec_state.next_uuid(); let id = exec_state.next_uuid();
@ -198,7 +200,7 @@ async fn inner_sweep(
ModelingCmd::from(mcmd::Sweep { ModelingCmd::from(mcmd::Sweep {
target: sketch.id.into(), target: sketch.id.into(),
trajectory, trajectory,
sectional: sectional.unwrap_or(true), sectional,
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)), tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
}), }),
) )
@ -209,7 +211,7 @@ async fn inner_sweep(
sketch, sketch,
id.into(), id.into(),
0.0, 0.0,
sectional.unwrap_or(false), sectional,
&super::extrude::NamedCapTags { &super::extrude::NamedCapTags {
start: tag_start.as_ref(), start: tag_start.as_ref(),
end: tag_end.as_ref(), end: tag_end.as_ref(),