Compare commits

...

7 Commits

Author SHA1 Message Date
efe15580c7 Revert "ignore errors on the modeling cmds that are only for the artifact graph"
This reverts commit db62c1962d.
2025-04-04 16:18:53 -07:00
db62c1962d ignore errors on the modeling cmds that are only for the artifact graph
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 16:07:48 -07:00
f6ffb4a01e fixups
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 15:48:49 -07:00
50da159e8f updates
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 15:48:18 -07:00
136fad95aa updates
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 15:46:21 -07:00
f769322c8f docs
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 15:13:23 -07:00
7313c599fa updates
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 15:12:20 -07:00
8 changed files with 11740 additions and 70 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -195,6 +195,27 @@ An angled line to.
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
----
An angled line.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `AngledLine`| | No |
| `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
----
A base path.

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

View File

@ -209,24 +209,9 @@ pub(crate) async fn do_post_extrude<'a>(
};
// 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
// are the ones that work with GetOppositeEdge and GetNextAdjacentEdge, aka the n sides in the sweep.
// So here we're figuring out that n number as yielded_sides_count here,
// making sure that circle() calls count but close() don't (no length)
let count_of_first_set_of_faces_if_sectional = if sectional {
sketch
.paths
.iter()
.filter(|p| {
let is_circle = matches!(p, Path::Circle { .. });
let has_length = p.get_base().from != p.get_base().to;
is_circle || has_length
})
.count()
} else {
usize::MAX
};
// We need to not run Solid3dGetOppositeEdge and Solid3dGetNextAdjacentEdge because it is too
// hard to know when they work or fail.
if !sectional {
for (curve_id, face_id) in face_infos
.iter()
.filter(|face_info| face_info.cap == ExtrusionFaceCapType::None)
@ -237,7 +222,6 @@ pub(crate) async fn do_post_extrude<'a>(
None
}
})
.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.
@ -263,6 +247,7 @@ pub(crate) async fn do_post_extrude<'a>(
)
.await?;
}
}
let Faces {
sides: face_id_map,
@ -293,7 +278,11 @@ pub(crate) async fn do_post_extrude<'a>(
});
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 {
face_id: *actual_face_id,
tag: path.get_base().tag.clone(),

View File

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

View File

@ -51,6 +51,13 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// You can provide more than one sketch to sweep, and they will all be
/// swept along the same path.
///
/// By default, we set `sectional` to `true`, which means that the sweep will
/// be broken up into sub-sweeps (extrusions, revolves, sweeps) based on
/// the trajectory path components.
///
/// If your sweep fails, try setting `sectional` to `false` to create a single
/// solid.
///
/// ```no_run
/// // Create a pipe using a sweep.
///
@ -82,7 +89,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// radius = 2,
/// )
/// |> hole(pipeHole, %)
/// |> sweep(path = sweepPath)
/// |> sweep(path = sweepPath, sectional = false)
/// ```
///
/// ```no_run
@ -150,7 +157,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// }, %)
/// |> xLine(length = 384.93)
///
/// sweep(circleSketch, path = sweepPath, sectional = true)
/// sweep(circleSketch, path = sweepPath)
/// ```
#[stdlib {
@ -161,7 +168,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
args = {
sketches = { docs = "The sketch or set of sketches that should be swept in space" },
path = { docs = "The path to sweep the sketch along" },
sectional = { docs = "If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components." },
sectional = { docs = "If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components. This defaults to true." },
tolerance = { docs = "Tolerance for this operation" },
tag_start = { docs = "A named tag for the face at the start of the sweep, i.e. the original sketch" },
tag_end = { docs = "A named tag for the face at the end of the sweep" },
@ -183,6 +190,8 @@ async fn inner_sweep(
SweepPath::Helix(helix) => helix.value.into(),
};
let sectional = sectional.unwrap_or(true);
let mut solids = Vec::new();
for sketch in &sketches {
let id = exec_state.next_uuid();
@ -191,7 +200,7 @@ async fn inner_sweep(
ModelingCmd::from(mcmd::Sweep {
target: sketch.id.into(),
trajectory,
sectional: sectional.unwrap_or(false),
sectional,
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
}),
)
@ -202,7 +211,7 @@ async fn inner_sweep(
sketch,
id.into(),
0.0,
sectional.unwrap_or(false),
sectional,
&super::extrude::NamedCapTags {
start: tag_start.as_ref(),
end: tag_end.as_ref(),

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 90 KiB