From 2804ddd2b14ef20af687b68d964d3a57c06b7eff Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 20 May 2026 17:54:01 +0200 Subject: [PATCH 01/78] add angle(lines=[..]) support using PointsAtAngle --- rust/kcl-lib/src/execution/exec_ast.rs | 329 ++++++++++++++++++++++-- rust/kcl-lib/src/execution/fn_call.rs | 29 ++- rust/kcl-lib/src/execution/geometry.rs | 9 + rust/kcl-lib/src/execution/kcl_value.rs | 10 +- rust/kcl-lib/src/std/constraints.rs | 164 +++--------- rust/kcl-lib/std/solver.kcl | 4 +- 6 files changed, 380 insertions(+), 165 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 84b76437cf3..5b09fe1b544 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use async_recursion::async_recursion; use ezpz::Constraint; use ezpz::NonLinearSystemError; +use ezpz::datatypes::inputs::DatumPoint; use indexmap::IndexMap; use kittycad_modeling_cmds as kcmc; @@ -13,9 +14,11 @@ use crate::errors::KclError; use crate::errors::KclErrorDetails; use crate::exec::Sketch; use crate::execution::AbstractSegment; +use crate::execution::AngleConstraintMode; use crate::execution::Artifact; use crate::execution::ArtifactId; use crate::execution::BodyType; +use crate::execution::ConstrainableLine2d; use crate::execution::ConstraintKind; use crate::execution::ControlFlowKind; use crate::execution::EarlyReturn; @@ -193,6 +196,93 @@ fn datum_line_from_constrainable( )) } +fn datum_points_from_constrainable_line( + line: &ConstrainableLine2d, + range: SourceRange, +) -> Result<[DatumPoint; 2], KclError> { + Ok([ + DatumPoint::new_xy( + line.vars[0].x.to_constraint_id(range)?, + line.vars[0].y.to_constraint_id(range)?, + ), + DatumPoint::new_xy( + line.vars[1].x.to_constraint_id(range)?, + line.vars[1].y.to_constraint_id(range)?, + ), + ]) +} + +fn same_datum_point(point0: DatumPoint, point1: DatumPoint) -> bool { + point0.x_id == point1.x_id && point0.y_id == point1.y_id +} + +fn connected_datum_points(existing_constraints: &[Constraint], point0: DatumPoint, point1: DatumPoint) -> bool { + if same_datum_point(point0, point1) { + return true; + } + + let mut visited = vec![point0]; + let mut index = 0; + while let Some(current) = visited.get(index).copied() { + index += 1; + + for constraint in existing_constraints { + let Constraint::PointsCoincident(a, b) = constraint else { + continue; + }; + let next = if same_datum_point(current, *a) { + *b + } else if same_datum_point(current, *b) { + *a + } else { + continue; + }; + + if same_datum_point(next, point1) { + return true; + } + if !visited.iter().any(|point| same_datum_point(*point, next)) { + visited.push(next); + } + } + } + + false +} + +fn points_at_angle_constraint( + line0: &ConstrainableLine2d, + line1: &ConstrainableLine2d, + existing_constraints: &[Constraint], + angle_kind: ezpz::datatypes::AngleKind, + range: SourceRange, +) -> Result { + let line0_points = datum_points_from_constrainable_line(line0, range)?; + let line1_points = datum_points_from_constrainable_line(line1, range)?; + let mut candidates = Vec::new(); + + for (line0_vertex_index, line0_vertex) in line0_points.iter().copied().enumerate() { + for (line1_vertex_index, line1_vertex) in line1_points.iter().copied().enumerate() { + if connected_datum_points(existing_constraints, line0_vertex, line1_vertex) { + candidates.push(( + line0_vertex, + line0_points[1 - line0_vertex_index], + line1_points[1 - line1_vertex_index], + )); + } + } + } + + let [(vertex, point0, point1)] = candidates.as_slice() else { + return Err(KclError::new_semantic(KclErrorDetails::new( + "angle(lines = ...) requires the two lines to share exactly one endpoint".to_owned(), + vec![range], + ))); + }; + + Ok(Constraint::PointsAtAngle(*vertex, *point0, *point1, angle_kind)) +} + fn sketch_var_initial_value( sketch_vars: &[KclValue], id: crate::execution::SketchVarId, @@ -3627,26 +3717,8 @@ impl Node { }; match &constraint.kind { - SketchConstraintKind::Angle { line0, line1 } => { + SketchConstraintKind::Angle { line0, line1, mode } => { let range = self.as_source_range(); - // Line 0 is points A and B. - // Line 1 is points C and D. - let ax = line0.vars[0].x.to_constraint_id(range)?; - let ay = line0.vars[0].y.to_constraint_id(range)?; - let bx = line0.vars[1].x.to_constraint_id(range)?; - let by = line0.vars[1].y.to_constraint_id(range)?; - let cx = line1.vars[0].x.to_constraint_id(range)?; - let cy = line1.vars[0].y.to_constraint_id(range)?; - let dx = line1.vars[1].x.to_constraint_id(range)?; - let dy = line1.vars[1].y.to_constraint_id(range)?; - let solver_line0 = ezpz::datatypes::inputs::DatumLineSegment::new( - ezpz::datatypes::inputs::DatumPoint::new_xy(ax, ay), - ezpz::datatypes::inputs::DatumPoint::new_xy(bx, by), - ); - let solver_line1 = ezpz::datatypes::inputs::DatumLineSegment::new( - ezpz::datatypes::inputs::DatumPoint::new_xy(cx, cy), - ezpz::datatypes::inputs::DatumPoint::new_xy(dx, dy), - ); let desired_angle = match n.ty { NumericType::Known(crate::exec::UnitType::Angle(kcmc::units::UnitAngle::Degrees)) | NumericType::Default { @@ -3669,11 +3741,30 @@ impl Node { return Err(internal_err(message, self)); } }; - let solver_constraint = Constraint::LinesAtAngle( - solver_line0, - solver_line1, - ezpz::datatypes::AngleKind::Other(desired_angle), - ); + let angle_kind = ezpz::datatypes::AngleKind::Other(desired_angle); + let solver_constraint = match mode { + AngleConstraintMode::LinesAtAngle => Constraint::LinesAtAngle( + datum_line_from_constrainable(line0, range)?, + datum_line_from_constrainable(line1, range)?, + angle_kind, + ), + AngleConstraintMode::PointsAtAngle => { + let Some(sketch_block_state) = &exec_state.mod_local.sketch_block else { + let message = + "Being inside a sketch block should have already been checked above" + .to_owned(); + debug_assert!(false, "{}", &message); + return Err(internal_err(message, self)); + }; + points_at_angle_constraint( + line0, + line1, + &sketch_block_state.solver_constraints, + angle_kind, + range, + )? + } + }; let constraint_id = exec_state.next_object_id(); let Some(sketch_block_state) = &mut exec_state.mod_local.sketch_block else { let message = @@ -5672,7 +5763,197 @@ mod test { use crate::errors::Severity; use crate::exec::UnitType; use crate::execution::ContextType; + use crate::execution::SketchVarId; use crate::execution::parse_execute; + use crate::front::ObjectId; + + fn test_line(object_id: usize, start: [usize; 2], end: [usize; 2]) -> ConstrainableLine2d { + ConstrainableLine2d { + vars: [ + crate::front::Point2d { + x: SketchVarId(start[0]), + y: SketchVarId(start[1]), + }, + crate::front::Point2d { + x: SketchVarId(end[0]), + y: SketchVarId(end[1]), + }, + ], + object_id: ObjectId(object_id), + } + } + + fn test_point(ids: [usize; 2]) -> DatumPoint { + DatumPoint::new_xy(ids[0].try_into().unwrap(), ids[1].try_into().unwrap()) + } + + fn assert_datum_point(point: DatumPoint, ids: [usize; 2]) { + assert_eq!(point.x_id, ids[0] as ezpz::Id); + assert_eq!(point.y_id, ids[1] as ezpz::Id); + } + + #[test] + fn points_at_angle_constraint_uses_shared_endpoint() { + let line0 = test_line(0, [0, 1], [2, 3]); + let line1 = test_line(1, [0, 1], [4, 5]); + + let constraint = points_at_angle_constraint( + &line0, + &line1, + &[], + ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), + SourceRange::default(), + ) + .unwrap(); + + let Constraint::PointsAtAngle(vertex, point0, point1, _) = constraint else { + panic!("expected PointsAtAngle"); + }; + assert_datum_point(vertex, [0, 1]); + assert_datum_point(point0, [2, 3]); + assert_datum_point(point1, [4, 5]); + } + + #[test] + fn points_at_angle_constraint_uses_coincident_endpoint() { + let line0 = test_line(0, [0, 1], [2, 3]); + let line1 = test_line(1, [4, 5], [6, 7]); + let existing_constraints = [Constraint::PointsCoincident(test_point([0, 1]), test_point([4, 5]))]; + + let constraint = points_at_angle_constraint( + &line0, + &line1, + &existing_constraints, + ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), + SourceRange::default(), + ) + .unwrap(); + + let Constraint::PointsAtAngle(vertex, point0, point1, _) = constraint else { + panic!("expected PointsAtAngle"); + }; + assert_datum_point(vertex, [0, 1]); + assert_datum_point(point0, [2, 3]); + assert_datum_point(point1, [6, 7]); + } + + #[test] + fn points_at_angle_constraint_requires_unique_shared_endpoint() { + let line0 = test_line(0, [0, 1], [2, 3]); + let line1 = test_line(1, [4, 5], [6, 7]); + + let no_shared_endpoint = points_at_angle_constraint( + &line0, + &line1, + &[], + ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), + SourceRange::default(), + ); + assert!(no_shared_endpoint.is_err()); + + let existing_constraints = [ + Constraint::PointsCoincident(test_point([0, 1]), test_point([4, 5])), + Constraint::PointsCoincident(test_point([2, 3]), test_point([6, 7])), + ]; + let ambiguous = points_at_angle_constraint( + &line0, + &line1, + &existing_constraints, + ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), + SourceRange::default(), + ); + assert!(ambiguous.is_err()); + } + + #[tokio::test(flavor = "multi_thread")] + async fn angle_unlabeled_keeps_legacy_lines_at_angle() { + parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) + lines = [line1, line2] + angle(lines) == 60deg +} +"#, + ) + .await + .unwrap(); + } + + #[tokio::test(flavor = "multi_thread")] + async fn angle_labelled_lines_allows_missing_unlabeled_input() { + parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 4mm, var 0mm], end = [var 2mm, var 3mm]) + coincident([line1.end, line2.start]) + angle(lines = [line1, line2]) == 60deg +} +"#, + ) + .await + .unwrap(); + } + + #[tokio::test(flavor = "multi_thread")] + async fn angle_labelled_lines_requires_unique_shared_endpoint() { + let err = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) + angle(lines = [line1, line2]) == 60deg +} +"#, + ) + .await + .unwrap_err(); + + assert!( + err.to_string() + .contains("angle(lines = ...) requires the two lines to share exactly one endpoint"), + "unexpected error: {err:?}" + ); + } + + #[tokio::test(flavor = "multi_thread")] + async fn angle_labelled_lines_wins_when_both_are_supplied() { + let err = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 4mm, var 0mm], end = [var 2mm, var 3mm]) + line3 = line(start = [var 0mm, var 1mm], end = [var 1mm, var 1mm]) + line4 = line(start = [var 0mm, var 2mm], end = [var 1mm, var 2mm]) + coincident([line1.end, line2.start]) + angle([line1, line2], lines = [line3, line4]) == 60deg +} +"#, + ) + .await + .unwrap_err(); + + assert!( + err.to_string() + .contains("angle(lines = ...) requires the two lines to share exactly one endpoint"), + "unexpected error: {err:?}" + ); + } + + #[tokio::test(flavor = "multi_thread")] + async fn angle_requires_unlabeled_or_labelled_lines() { + parse_execute( + r#" +sketch(on = XY) { + angle() == 60deg +} +"#, + ) + .await + .unwrap_err(); + } #[tokio::test(flavor = "multi_thread")] async fn ascription() { diff --git a/rust/kcl-lib/src/execution/fn_call.rs b/rust/kcl-lib/src/execution/fn_call.rs index b3dbc2ab00d..16cf5d4aa9b 100644 --- a/rust/kcl-lib/src/execution/fn_call.rs +++ b/rust/kcl-lib/src/execution/fn_call.rs @@ -61,7 +61,7 @@ impl ArgsStatus for Sugary {} // Invariants guaranteed by the `Desugared` status: // - There is either 0 or 1 unlabeled arguments // - Any lableled args are in the labeled map, and not the unlabeled Vec. -// - The arguments match the type signature of the function exactly +// - The arguments match the type signature of the function, allowing omitted optional args // - pipe_value.is_none() #[derive(Debug, Clone)] pub struct Desugared; @@ -774,6 +774,7 @@ fn type_check_params_kw( if let Some(l) = l && fn_def.named_args.contains_key(l) && !args.labeled.contains_key(l) + && !(fn_name == Some("angle") && l == "lines") { true } else { @@ -786,7 +787,7 @@ fn type_check_params_kw( debug_assert!(previous.is_none()); } - if let Some((name, ty)) = &fn_def.input_arg { + if let Some((name, ty, default_value)) = &fn_def.input_arg { // Expecting an input arg if args.unlabeled.is_empty() { @@ -807,6 +808,8 @@ fn type_check_params_kw( ), )); result.unlabeled = vec![(Some(name.clone()), arg)]; + } else if default_value.is_some() { + // Optional @input was omitted. } else { // Just missing return Err(KclError::new_argument(KclErrorDetails::new( @@ -1013,19 +1016,25 @@ fn assign_args_to_params_kw( } } - if let Some((param_name, _)) = &fn_def.input_arg { - let Some(unlabeled) = args.unlabeled_kw_arg_unconverted() else { + if let Some((param_name, _, default_value)) = &fn_def.input_arg { + if let Some(unlabeled) = args.unlabeled_kw_arg_unconverted() { + exec_state.mut_stack().add( + param_name.clone(), + unlabeled.value.clone(), + unlabeled.source_ranges().pop().unwrap_or(SourceRange::synthetic()), + )?; + } else if let Some(default_value) = default_value { + let value = KclValue::from_default_param(default_value.clone(), exec_state); + exec_state + .mut_stack() + .add(param_name.clone(), value, default_value.source_range())?; + } else { debug_assert!(false, "Bad args"); return Err(KclError::new_internal(KclErrorDetails::new( "Desugared arguments are inconsistent".to_owned(), source_ranges, ))); - }; - exec_state.mut_stack().add( - param_name.clone(), - unlabeled.value.clone(), - unlabeled.source_ranges().pop().unwrap_or(SourceRange::synthetic()), - )?; + } } Ok(()) diff --git a/rust/kcl-lib/src/execution/geometry.rs b/rust/kcl-lib/src/execution/geometry.rs index 9a19fb64902..119257e212d 100644 --- a/rust/kcl-lib/src/execution/geometry.rs +++ b/rust/kcl-lib/src/execution/geometry.rs @@ -2344,6 +2344,12 @@ pub struct SketchConstraint { pub meta: Vec, } +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AngleConstraintMode { + LinesAtAngle, + PointsAtAngle, +} + #[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)] #[ts(export_to = "Geometry.ts")] #[serde(rename_all = "camelCase")] @@ -2351,6 +2357,9 @@ pub enum SketchConstraintKind { Angle { line0: ConstrainableLine2d, line1: ConstrainableLine2d, + #[serde(skip)] + #[ts(skip)] + mode: AngleConstraintMode, }, Distance { points: [ConstrainablePoint2dOrOrigin; 2], diff --git a/rust/kcl-lib/src/execution/kcl_value.rs b/rust/kcl-lib/src/execution/kcl_value.rs index 25fa1a5300a..977106ee1e4 100644 --- a/rust/kcl-lib/src/execution/kcl_value.rs +++ b/rust/kcl-lib/src/execution/kcl_value.rs @@ -177,7 +177,7 @@ pub struct NamedParam { #[derive(Debug, Clone, PartialEq)] pub struct FunctionSource { - pub input_arg: Option<(String, Option)>, + pub input_arg: Option<(String, Option, Option)>, pub named_args: IndexMap, pub return_type: Option>, pub deprecated: bool, @@ -243,7 +243,12 @@ impl FunctionSource { } #[expect(clippy::type_complexity)] - fn args_from_ast(ast: &FunctionExpression) -> (Option<(String, Option)>, IndexMap) { + fn args_from_ast( + ast: &FunctionExpression, + ) -> ( + Option<(String, Option, Option)>, + IndexMap, + ) { let mut input_arg = None; let mut named_args = IndexMap::new(); for p in &ast.params { @@ -251,6 +256,7 @@ impl FunctionSource { input_arg = Some(( p.identifier.name.clone(), p.param_type.as_ref().map(|t| t.inner.clone()), + p.default_value.clone(), )); continue; } diff --git a/rust/kcl-lib/src/std/constraints.rs b/rust/kcl-lib/src/std/constraints.rs index 465d188a8bf..d29baf7937b 100644 --- a/rust/kcl-lib/src/std/constraints.rs +++ b/rust/kcl-lib/src/std/constraints.rs @@ -13,6 +13,7 @@ use kittycad_modeling_cmds as kcmc; use crate::errors::KclError; use crate::errors::KclErrorDetails; use crate::execution::AbstractSegment; +use crate::execution::AngleConstraintMode; use crate::execution::Artifact; use crate::execution::CodeRef; use crate::execution::ConstrainableLine2d; @@ -263,6 +264,27 @@ fn constrainable_line_from_unsolved_segment( } } +fn constrainable_line_from_kcl_value( + value: &KclValue, + function_name: &str, + range: crate::SourceRange, +) -> Result { + let KclValue::Segment { value } = value else { + return Err(KclError::new_semantic(KclErrorDetails::new( + format!("{function_name}() expected a line segment"), + vec![range], + ))); + }; + let SegmentRepr::Unsolved { segment } = &value.repr else { + return Err(KclError::new_internal(KclErrorDetails::new( + format!("{function_name}() expected an unsolved segment"), + vec![range], + ))); + }; + + constrainable_line_from_unsolved_segment(segment, function_name, range) +} + fn constrainable_point_from_exprs( position: &[UnsolvedExpr; 2], object_id: ObjectId, @@ -4841,142 +4863,28 @@ fn axis_constraint_points( } pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result { - let lines: Vec = args.get_unlabeled_kw_arg( - "lines", - &RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)), - exec_state, - )?; + let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); + let (lines, mode): (Vec, AngleConstraintMode) = + if let Some(lines) = args.get_kw_arg_opt("lines", &line_array_ty, exec_state)? { + (lines, AngleConstraintMode::PointsAtAngle) + } else { + ( + args.get_unlabeled_kw_arg("lines", &line_array_ty, exec_state)?, + AngleConstraintMode::LinesAtAngle, + ) + }; + let [line0, line1]: [KclValue; 2] = lines.try_into().map_err(|_| { KclError::new_semantic(KclErrorDetails::new( "must have two input lines".to_owned(), vec![args.source_range], )) })?; - let KclValue::Segment { value: segment0 } = &line0 else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line argument must be a Segment".to_owned(), - vec![args.source_range], - ))); - }; - let SegmentRepr::Unsolved { segment: unsolved0 } = &segment0.repr else { - return Err(KclError::new_internal(KclErrorDetails::new( - "line must be an unsolved Segment".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedSegmentKind::Line { - start: start0, - end: end0, - .. - } = &unsolved0.kind - else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line argument must be a line, no other type of Segment".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line0_p0_x) = &start0[0] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's start x coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line0_p0_y) = &start0[1] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's start y coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line0_p1_x) = &end0[0] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's end x coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line0_p1_y) = &end0[1] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's end y coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let KclValue::Segment { value: segment1 } = &line1 else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line argument must be a Segment".to_owned(), - vec![args.source_range], - ))); - }; - let SegmentRepr::Unsolved { segment: unsolved1 } = &segment1.repr else { - return Err(KclError::new_internal(KclErrorDetails::new( - "line must be an unsolved Segment".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedSegmentKind::Line { - start: start1, - end: end1, - .. - } = &unsolved1.kind - else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line argument must be a line, no other type of Segment".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line1_p0_x) = &start1[0] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's start x coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line1_p0_y) = &start1[1] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's start y coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line1_p1_x) = &end1[0] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's end x coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; - let UnsolvedExpr::Unknown(line1_p1_y) = &end1[1] else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "line's end y coordinate must be a var".to_owned(), - vec![args.source_range], - ))); - }; + let line0 = constrainable_line_from_kcl_value(&line0, "angle", args.source_range)?; + let line1 = constrainable_line_from_kcl_value(&line1, "angle", args.source_range)?; - // All coordinates are sketch vars. Proceed. let sketch_constraint = SketchConstraint { - kind: SketchConstraintKind::Angle { - line0: crate::execution::ConstrainableLine2d { - object_id: unsolved0.object_id, - vars: [ - crate::front::Point2d { - x: *line0_p0_x, - y: *line0_p0_y, - }, - crate::front::Point2d { - x: *line0_p1_x, - y: *line0_p1_y, - }, - ], - }, - line1: crate::execution::ConstrainableLine2d { - object_id: unsolved1.object_id, - vars: [ - crate::front::Point2d { - x: *line1_p0_x, - y: *line1_p0_y, - }, - crate::front::Point2d { - x: *line1_p1_x, - y: *line1_p1_y, - }, - ], - }, - }, + kind: SketchConstraintKind::Angle { line0, line1, mode }, meta: vec![args.source_range.into()], }; Ok(KclValue::SketchConstraint { diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index 3aa987c147e..5b02c6b698c 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -445,7 +445,9 @@ export fn perpendicular( @(impl = std_rust_constraint, feature_tree = true) export fn angle( /// The two line segments whose relative angle should match the value set with `==`. - @input: [Segment; 2], + @input?: [Segment; 2], + /// The two line segments whose oriented relative angle should match the value set with `==`. + lines?: [Segment; 2], ) {} /// Constrain two segments to be tangent. From 028127a92d86d9dc88752f9250298a853ad75918 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 3 Jun 2026 15:50:57 +0200 Subject: [PATCH 02/78] wip rays, sector --- rust/kcl-lib/src/execution/exec_ast.rs | 506 +++++++++++------- rust/kcl-lib/src/execution/geometry.rs | 17 +- rust/kcl-lib/src/frontend.rs | 4 + rust/kcl-lib/src/frontend/sketch.rs | 22 + rust/kcl-lib/src/std/constraints.rs | 55 +- rust/kcl-lib/std/solver.kcl | 4 + .../AngleConstraintBuilder.test.ts | 268 ++++++++++ .../constraints/AngleConstraintBuilder.ts | 154 ++++++ 8 files changed, 832 insertions(+), 198 deletions(-) create mode 100644 src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 966ffb2504f..c91858bcced 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -15,6 +15,8 @@ use crate::errors::KclErrorDetails; use crate::exec::Sketch; use crate::execution::AbstractSegment; use crate::execution::AngleConstraintMode; +use crate::execution::AngleRayDirection; +use crate::execution::AngleSector; use crate::execution::Artifact; use crate::execution::ArtifactId; use crate::execution::BodyType; @@ -77,6 +79,8 @@ use crate::front::Object; use crate::front::ObjectId; use crate::front::ObjectKind; use crate::front::PointCtor; +use crate::frontend::sketch::AngleRayDirection as FrontAngleRayDirection; +use crate::frontend::sketch::AngleSector as FrontAngleSector; use crate::modules::ModuleExecutionOutcome; use crate::modules::ModuleId; use crate::modules::ModulePath; @@ -200,91 +204,161 @@ fn datum_line_from_constrainable( )) } -fn datum_points_from_constrainable_line( - line: &ConstrainableLine2d, +fn push_hidden_sketch_point( + sketch_block_state: &mut SketchBlockState, + sketch_var_ty: NumericType, + initial: [f64; 2], range: SourceRange, -) -> Result<[DatumPoint; 2], KclError> { - Ok([ - DatumPoint::new_xy( - line.vars[0].x.to_constraint_id(range)?, - line.vars[0].y.to_constraint_id(range)?, - ), - DatumPoint::new_xy( - line.vars[1].x.to_constraint_id(range)?, - line.vars[1].y.to_constraint_id(range)?, - ), - ]) +) -> Result { + let x_id = sketch_block_state.next_sketch_var_id(); + sketch_block_state.sketch_vars.push(KclValue::SketchVar { + value: Box::new(crate::execution::SketchVar { + id: x_id, + initial_value: initial[0], + ty: sketch_var_ty, + node_path: None, + meta: vec![], + }), + }); + let y_id = sketch_block_state.next_sketch_var_id(); + sketch_block_state.sketch_vars.push(KclValue::SketchVar { + value: Box::new(crate::execution::SketchVar { + id: y_id, + initial_value: initial[1], + ty: sketch_var_ty, + node_path: None, + meta: vec![], + }), + }); + + Ok(DatumPoint::new_xy( + x_id.to_constraint_id(range)?, + y_id.to_constraint_id(range)?, + )) +} + +fn vec2_sub(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { + [a[0] - b[0], a[1] - b[1]] +} + +fn vec2_add(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { + [a[0] + b[0], a[1] + b[1]] } -fn same_datum_point(point0: DatumPoint, point1: DatumPoint) -> bool { - point0.x_id == point1.x_id && point0.y_id == point1.y_id +fn vec2_scale(a: [f64; 2], scale: f64) -> [f64; 2] { + [a[0] * scale, a[1] * scale] } -fn connected_datum_points(existing_constraints: &[Constraint], point0: DatumPoint, point1: DatumPoint) -> bool { - if same_datum_point(point0, point1) { - return true; +fn vec2_cross(a: [f64; 2], b: [f64; 2]) -> f64 { + a[0] * b[1] - a[1] * b[0] +} + +fn vec2_len(a: [f64; 2]) -> f64 { + libm::hypot(a[0], a[1]) +} + +fn vec2_normalized(a: [f64; 2], range: SourceRange, description: &str) -> Result<[f64; 2], KclError> { + let len = vec2_len(a); + if len <= 1e-9 { + return Err(KclError::new_semantic(KclErrorDetails::new( + format!("angle() {description} must not be degenerate"), + vec![range], + ))); } - let mut visited = vec![point0]; - let mut index = 0; - while let Some(current) = visited.get(index).copied() { - index += 1; + Ok([a[0] / len, a[1] / len]) +} - for constraint in existing_constraints { - let Constraint::PointsCoincident(a, b) = constraint else { - continue; - }; - let next = if same_datum_point(current, *a) { - *b - } else if same_datum_point(current, *b) { - *a - } else { - continue; - }; +fn intersection_of_initial_lines( + line0: ([f64; 2], [f64; 2]), + line1: ([f64; 2], [f64; 2]), + range: SourceRange, +) -> Result<[f64; 2], KclError> { + let p = line0.0; + let r = vec2_sub(line0.1, line0.0); + let q = line1.0; + let s = vec2_sub(line1.1, line1.0); + let denom = vec2_cross(r, s); + if denom.abs() <= 1e-9 { + return Err(KclError::new_semantic(KclErrorDetails::new( + "angle(lines = ..., rays = ...) requires non-parallel lines".to_owned(), + vec![range], + ))); + } - if same_datum_point(next, point1) { - return true; - } - if !visited.iter().any(|point| same_datum_point(*point, next)) { - visited.push(next); - } - } + let t = vec2_cross(vec2_sub(q, p), s) / denom; + Ok(vec2_add(p, vec2_scale(r, t))) +} + +fn front_angle_ray_direction(ray: AngleRayDirection) -> FrontAngleRayDirection { + match ray { + AngleRayDirection::Forward => FrontAngleRayDirection::Forward, + AngleRayDirection::Reverse => FrontAngleRayDirection::Reverse, + } +} + +fn front_angle_sector(sector: AngleSector) -> FrontAngleSector { + match sector { + AngleSector::Primary => FrontAngleSector::Primary, + AngleSector::Opposite => FrontAngleSector::Opposite, } +} - false +fn angle_ray_initial( + vertex: [f64; 2], + line: ([f64; 2], [f64; 2]), + ray: AngleRayDirection, + distance: f64, + range: SourceRange, +) -> Result<[f64; 2], KclError> { + let direction = vec2_normalized(vec2_sub(line.1, line.0), range, "line")?; + let sign = match ray { + AngleRayDirection::Forward => 1.0, + AngleRayDirection::Reverse => -1.0, + }; + Ok(vec2_add(vertex, vec2_scale(direction, sign * distance))) } -fn points_at_angle_constraint( +fn push_points_at_angle_for_line_rays( + sketch_block_state: &mut SketchBlockState, + sketch_var_ty: NumericType, line0: &ConstrainableLine2d, line1: &ConstrainableLine2d, - existing_constraints: &[Constraint], + initial_vertex: [f64; 2], + initial_ray_points: [[f64; 2]; 2], + ray_distance: f64, angle_kind: ezpz::datatypes::AngleKind, range: SourceRange, -) -> Result { - let line0_points = datum_points_from_constrainable_line(line0, range)?; - let line1_points = datum_points_from_constrainable_line(line1, range)?; - let mut candidates = Vec::new(); - - for (line0_vertex_index, line0_vertex) in line0_points.iter().copied().enumerate() { - for (line1_vertex_index, line1_vertex) in line1_points.iter().copied().enumerate() { - if connected_datum_points(existing_constraints, line0_vertex, line1_vertex) { - candidates.push(( - line0_vertex, - line0_points[1 - line0_vertex_index], - line1_points[1 - line1_vertex_index], - )); - } - } - } +) -> Result<(), KclError> { + let solver_line0 = datum_line_from_constrainable(line0, range)?; + let solver_line1 = datum_line_from_constrainable(line1, range)?; + let vertex = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_vertex, range)?; + let ray0 = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_ray_points[0], range)?; + let ray1 = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_ray_points[1], range)?; - let [(vertex, point0, point1)] = candidates.as_slice() else { - return Err(KclError::new_semantic(KclErrorDetails::new( - "angle(lines = ...) requires the two lines to share exactly one endpoint".to_owned(), - vec![range], - ))); - }; + sketch_block_state + .solver_constraints + .push(Constraint::PointLineDistance(vertex, solver_line0, 0.0)); + sketch_block_state + .solver_constraints + .push(Constraint::PointLineDistance(vertex, solver_line1, 0.0)); + sketch_block_state + .solver_constraints + .push(Constraint::PointLineDistance(ray0, solver_line0, 0.0)); + sketch_block_state + .solver_constraints + .push(Constraint::PointLineDistance(ray1, solver_line1, 0.0)); + sketch_block_state + .solver_constraints + .push(Constraint::Distance(vertex, ray0, ray_distance)); + sketch_block_state + .solver_constraints + .push(Constraint::Distance(vertex, ray1, ray_distance)); + sketch_block_state + .solver_constraints + .push(Constraint::PointsAtAngle(vertex, ray0, ray1, angle_kind)); - Ok(Constraint::PointsAtAngle(*vertex, *point0, *point1, angle_kind)) + Ok(()) } fn sketch_var_initial_value( @@ -3774,30 +3848,64 @@ impl Node { return Err(internal_err(message, self)); } }; - let angle_kind = ezpz::datatypes::AngleKind::Other(desired_angle); - let solver_constraint = match mode { - AngleConstraintMode::LinesAtAngle => Constraint::LinesAtAngle( - datum_line_from_constrainable(line0, range)?, - datum_line_from_constrainable(line1, range)?, - angle_kind, - ), - AngleConstraintMode::PointsAtAngle => { - let Some(sketch_block_state) = &exec_state.mod_local.sketch_block else { - let message = - "Being inside a sketch block should have already been checked above" - .to_owned(); - debug_assert!(false, "{}", &message); - return Err(internal_err(message, self)); - }; - points_at_angle_constraint( + let points_at_angle_data = match *mode { + AngleConstraintMode::LinesAtAngle => None, + AngleConstraintMode::PointsAtAngle { rays, .. } => { + let sketch_vars = exec_state + .mod_local + .sketch_block + .as_ref() + .ok_or_else(|| { + internal_err( + "Being inside a sketch block should have already been checked above", + self, + ) + })? + .sketch_vars + .clone(); + let initial_line0 = constrainable_line_initial_positions( + &sketch_vars, line0, + exec_state, + range, + "angle line0", + )?; + let initial_line1 = constrainable_line_initial_positions( + &sketch_vars, line1, - &sketch_block_state.solver_constraints, - angle_kind, + exec_state, range, - )? + "angle line1", + )?; + let initial_vertex = + intersection_of_initial_lines(initial_line0, initial_line1, range)?; + let line0_length = vec2_len(vec2_sub(initial_line0.1, initial_line0.0)); + let line1_length = vec2_len(vec2_sub(initial_line1.1, initial_line1.0)); + let ray_distance = (line0_length.min(line1_length) * 0.25).max(1.0); + Some(( + initial_vertex, + [ + angle_ray_initial( + initial_vertex, + initial_line0, + rays[0], + ray_distance, + range, + )?, + angle_ray_initial( + initial_vertex, + initial_line1, + rays[1], + ray_distance, + range, + )?, + ], + ray_distance, + ezpz::datatypes::AngleKind::Other(desired_angle), + )) } }; + let sketch_var_ty = solver_numeric_type(exec_state); let constraint_id = exec_state.next_object_id(); let Some(sketch_block_state) = &mut exec_state.mod_local.sketch_block else { let message = @@ -3805,7 +3913,34 @@ impl Node { debug_assert!(false, "{}", &message); return Err(internal_err(message, self)); }; - sketch_block_state.solver_constraints.push(solver_constraint); + match (*mode, points_at_angle_data) { + (AngleConstraintMode::LinesAtAngle, None) => { + sketch_block_state.solver_constraints.push(Constraint::LinesAtAngle( + datum_line_from_constrainable(line0, range)?, + datum_line_from_constrainable(line1, range)?, + ezpz::datatypes::AngleKind::Other(desired_angle), + )); + } + ( + AngleConstraintMode::PointsAtAngle { .. }, + Some((initial_vertex, initial_ray_points, ray_distance, angle_kind)), + ) => push_points_at_angle_for_line_rays( + sketch_block_state, + sketch_var_ty, + line0, + line1, + initial_vertex, + initial_ray_points, + ray_distance, + angle_kind, + range, + )?, + _ => { + let message = "Invalid angle constraint lowering state".to_owned(); + debug_assert!(false, "{}", &message); + return Err(internal_err(message, self)); + } + } use crate::execution::Artifact; use crate::execution::CodeRef; use crate::execution::SketchBlockConstraint; @@ -3818,11 +3953,20 @@ impl Node { debug_assert!(false, "{}", &message); return Err(KclError::new_internal(KclErrorDetails::new(message, vec![range]))); }; + let (rays, sector) = match *mode { + AngleConstraintMode::LinesAtAngle => (None, None), + AngleConstraintMode::PointsAtAngle { rays, sector } => ( + Some([front_angle_ray_direction(rays[0]), front_angle_ray_direction(rays[1])]), + Some(front_angle_sector(sector)), + ), + }; let sketch_constraint = crate::front::Constraint::Angle(Angle { lines: vec![line0.object_id, line1.object_id], angle: n.try_into().map_err(|_| { internal_err("Failed to convert angle units numeric suffix:", range) })?, + rays, + sector, source, }); sketch_block_state.sketch_constraints.push(constraint_id); @@ -5822,148 +5966,122 @@ mod test { use crate::errors::Severity; use crate::exec::UnitType; use crate::execution::ContextType; - use crate::execution::SketchVarId; use crate::execution::parse_execute; - use crate::front::ObjectId; - - fn test_line(object_id: usize, start: [usize; 2], end: [usize; 2]) -> ConstrainableLine2d { - ConstrainableLine2d { - vars: [ - crate::front::Point2d { - x: SketchVarId(start[0]), - y: SketchVarId(start[1]), - }, - crate::front::Point2d { - x: SketchVarId(end[0]), - y: SketchVarId(end[1]), - }, - ], - object_id: ObjectId(object_id), - } - } - - fn test_point(ids: [usize; 2]) -> DatumPoint { - DatumPoint::new_xy(ids[0].try_into().unwrap(), ids[1].try_into().unwrap()) - } - - fn assert_datum_point(point: DatumPoint, ids: [usize; 2]) { - assert_eq!(point.x_id, ids[0] as ezpz::Id); - assert_eq!(point.y_id, ids[1] as ezpz::Id); - } - - #[test] - fn points_at_angle_constraint_uses_shared_endpoint() { - let line0 = test_line(0, [0, 1], [2, 3]); - let line1 = test_line(1, [0, 1], [4, 5]); - let constraint = points_at_angle_constraint( - &line0, - &line1, - &[], - ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), - SourceRange::default(), + #[tokio::test(flavor = "multi_thread")] + async fn angle_unlabeled_keeps_legacy_lines_at_angle() { + parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) + lines = [line1, line2] + angle(lines) == 60deg +} +"#, ) + .await .unwrap(); - - let Constraint::PointsAtAngle(vertex, point0, point1, _) = constraint else { - panic!("expected PointsAtAngle"); - }; - assert_datum_point(vertex, [0, 1]); - assert_datum_point(point0, [2, 3]); - assert_datum_point(point1, [4, 5]); } - #[test] - fn points_at_angle_constraint_uses_coincident_endpoint() { - let line0 = test_line(0, [0, 1], [2, 3]); - let line1 = test_line(1, [4, 5], [6, 7]); - let existing_constraints = [Constraint::PointsCoincident(test_point([0, 1]), test_point([4, 5]))]; - - let constraint = points_at_angle_constraint( - &line0, - &line1, - &existing_constraints, - ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), - SourceRange::default(), + #[tokio::test(flavor = "multi_thread")] + async fn angle_labelled_lines_with_rays_allows_missing_unlabeled_input() { + parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) + angle(lines = [line1, line2], rays = [1, -1]) == 60deg +} +"#, ) + .await .unwrap(); - - let Constraint::PointsAtAngle(vertex, point0, point1, _) = constraint else { - panic!("expected PointsAtAngle"); - }; - assert_datum_point(vertex, [0, 1]); - assert_datum_point(point0, [2, 3]); - assert_datum_point(point1, [6, 7]); } - #[test] - fn points_at_angle_constraint_requires_unique_shared_endpoint() { - let line0 = test_line(0, [0, 1], [2, 3]); - let line1 = test_line(1, [4, 5], [6, 7]); - - let no_shared_endpoint = points_at_angle_constraint( - &line0, - &line1, - &[], - ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), - SourceRange::default(), - ); - assert!(no_shared_endpoint.is_err()); - - let existing_constraints = [ - Constraint::PointsCoincident(test_point([0, 1]), test_point([4, 5])), - Constraint::PointsCoincident(test_point([2, 3]), test_point([6, 7])), - ]; - let ambiguous = points_at_angle_constraint( - &line0, - &line1, - &existing_constraints, - ezpz::datatypes::AngleKind::Other(ezpz::datatypes::Angle::from_degrees(60.0)), - SourceRange::default(), + #[tokio::test(flavor = "multi_thread")] + async fn angle_labelled_lines_accepts_opposite_sector() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var -3.464mm]) + angle(lines = [line1, line2], rays = [1, 1], sector = "opposite") == 360deg - 60deg +} +"#, + ) + .await + .unwrap(); + let angle = result + .exec_state + .global + .root_module_artifacts + .scene_objects + .iter() + .find_map(|object| match &object.kind { + ObjectKind::Constraint { + constraint: crate::front::Constraint::Angle(angle), + } => Some(angle), + _ => None, + }) + .unwrap(); + assert_eq!( + angle.rays, + Some([FrontAngleRayDirection::Forward, FrontAngleRayDirection::Forward]) ); - assert!(ambiguous.is_err()); + assert_eq!(angle.sector, Some(FrontAngleSector::Opposite)); } #[tokio::test(flavor = "multi_thread")] - async fn angle_unlabeled_keeps_legacy_lines_at_angle() { - parse_execute( + async fn angle_labelled_lines_requires_rays() { + let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - lines = [line1, line2] - angle(lines) == 60deg + angle(lines = [line1, line2]) == 60deg } "#, ) .await - .unwrap(); + .unwrap_err(); + + assert!( + err.to_string().contains("requires a keyword argument `rays`"), + "unexpected error: {err:?}" + ); } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_allows_missing_unlabeled_input() { - parse_execute( + async fn angle_labelled_lines_wins_when_both_are_supplied() { + let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 4mm, var 0mm], end = [var 2mm, var 3mm]) - coincident([line1.end, line2.start]) - angle(lines = [line1, line2]) == 60deg + line3 = line(start = [var 0mm, var 1mm], end = [var 1mm, var 1mm]) + line4 = line(start = [var 0mm, var 2mm], end = [var 1mm, var 3mm]) + angle([line1, line2], lines = [line3, line4], rays = [1, 0]) == 60deg } "#, ) .await - .unwrap(); + .unwrap_err(); + + assert!( + err.to_string().contains("angle() rays must be either 1 or -1"), + "unexpected error: {err:?}" + ); } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_requires_unique_shared_endpoint() { + async fn angle_labelled_lines_rejects_invalid_sector() { let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle(lines = [line1, line2]) == 60deg + angle(lines = [line1, line2], rays = [1, -1], sector = "side") == 60deg } "#, ) @@ -5971,23 +6089,19 @@ sketch(on = XY) { .unwrap_err(); assert!( - err.to_string() - .contains("angle(lines = ...) requires the two lines to share exactly one endpoint"), + err.to_string().contains("angle() sector must be either"), "unexpected error: {err:?}" ); } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_wins_when_both_are_supplied() { + async fn angle_labelled_lines_rejects_parallel_lines() { let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) - line2 = line(start = [var 4mm, var 0mm], end = [var 2mm, var 3mm]) - line3 = line(start = [var 0mm, var 1mm], end = [var 1mm, var 1mm]) - line4 = line(start = [var 0mm, var 2mm], end = [var 1mm, var 2mm]) - coincident([line1.end, line2.start]) - angle([line1, line2], lines = [line3, line4]) == 60deg + line2 = line(start = [var 0mm, var 1mm], end = [var 4mm, var 1mm]) + angle(lines = [line1, line2], rays = [1, -1]) == 60deg } "#, ) @@ -5996,7 +6110,7 @@ sketch(on = XY) { assert!( err.to_string() - .contains("angle(lines = ...) requires the two lines to share exactly one endpoint"), + .contains("angle(lines = ..., rays = ...) requires non-parallel lines"), "unexpected error: {err:?}" ); } diff --git a/rust/kcl-lib/src/execution/geometry.rs b/rust/kcl-lib/src/execution/geometry.rs index 836eaede55e..b296ddda25a 100644 --- a/rust/kcl-lib/src/execution/geometry.rs +++ b/rust/kcl-lib/src/execution/geometry.rs @@ -2359,10 +2359,25 @@ pub struct SketchConstraint { pub meta: Vec, } +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AngleRayDirection { + Forward, + Reverse, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AngleSector { + Primary, + Opposite, +} + #[derive(Debug, Clone, Copy, PartialEq)] pub enum AngleConstraintMode { LinesAtAngle, - PointsAtAngle, + PointsAtAngle { + rays: [AngleRayDirection; 2], + sector: AngleSector, + }, } #[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)] diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index b54a4641d63..831bce299d8 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -12468,6 +12468,8 @@ splineSketch = sketch(on = XY) { value: 30.0, units: NumericSuffix::Deg, }, + rays: None, + sector: None, source: Default::default(), }); let (src_delta, _) = frontend @@ -13189,6 +13191,8 @@ sketch(on = XY) { value: 30.0, units: NumericSuffix::Deg, }, + rays: None, + sector: None, source: Default::default(), }); let (src_delta, scene_delta) = frontend diff --git a/rust/kcl-lib/src/frontend/sketch.rs b/rust/kcl-lib/src/frontend/sketch.rs index 8bc70c69018..a088ec740b3 100644 --- a/rust/kcl-lib/src/frontend/sketch.rs +++ b/rust/kcl-lib/src/frontend/sketch.rs @@ -561,9 +561,31 @@ impl Distance { pub struct Angle { pub lines: Vec, pub angle: Number, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub rays: Option<[AngleRayDirection; 2]>, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub sector: Option, pub source: ConstraintSource, } +#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize, ts_rs::TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "FrontendApi.ts")] +pub enum AngleRayDirection { + Forward, + Reverse, +} + +#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize, ts_rs::TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "FrontendApi.ts")] +pub enum AngleSector { + Primary, + Opposite, +} + #[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize, ts_rs::TS)] #[ts(export, export_to = "FrontendApi.ts")] pub struct ConstraintSource { diff --git a/rust/kcl-lib/src/std/constraints.rs b/rust/kcl-lib/src/std/constraints.rs index a73ba7cc2fd..19deefad64c 100644 --- a/rust/kcl-lib/src/std/constraints.rs +++ b/rust/kcl-lib/src/std/constraints.rs @@ -16,6 +16,8 @@ use crate::errors::KclError; use crate::errors::KclErrorDetails; use crate::execution::AbstractSegment; use crate::execution::AngleConstraintMode; +use crate::execution::AngleRayDirection; +use crate::execution::AngleSector; use crate::execution::Artifact; use crate::execution::CodeRef; use crate::execution::ConstrainableLine2d; @@ -444,6 +446,30 @@ fn constrainable_line_from_kcl_value( constrainable_line_from_unsolved_segment(segment, function_name, range) } +fn angle_ray_direction(ray: TyF64, range: crate::SourceRange) -> Result { + if ray.n == 1.0 { + Ok(AngleRayDirection::Forward) + } else if ray.n == -1.0 { + Ok(AngleRayDirection::Reverse) + } else { + Err(KclError::new_semantic(KclErrorDetails::new( + "angle() rays must be either 1 or -1".to_owned(), + vec![range], + ))) + } +} + +fn angle_sector(sector: &str, range: crate::SourceRange) -> Result { + match sector { + "primary" => Ok(AngleSector::Primary), + "opposite" => Ok(AngleSector::Opposite), + _ => Err(KclError::new_semantic(KclErrorDetails::new( + "angle() sector must be either \"primary\" or \"opposite\"".to_owned(), + vec![range], + ))), + } +} + fn constrainable_point_from_exprs( position: &[UnsolvedExpr; 2], object_id: ObjectId, @@ -5129,10 +5155,37 @@ fn axis_constraint_points( pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result { let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); + let ray_array_ty = RuntimeType::Array(Box::new(RuntimeType::count()), ArrayLen::Known(2)); let (lines, mode): (Vec, AngleConstraintMode) = if let Some(lines) = args.get_kw_arg_opt("lines", &line_array_ty, exec_state)? { - (lines, AngleConstraintMode::PointsAtAngle) + let rays: [TyF64; 2] = args.get_kw_arg("rays", &ray_array_ty, exec_state)?; + let [ray0, ray1] = rays; + let sector = args + .get_kw_arg_opt::("sector", &RuntimeType::string(), exec_state)? + .unwrap_or_else(|| "primary".to_owned()); + ( + lines, + AngleConstraintMode::PointsAtAngle { + rays: [ + angle_ray_direction(ray0, args.source_range)?, + angle_ray_direction(ray1, args.source_range)?, + ], + sector: angle_sector(§or, args.source_range)?, + }, + ) } else { + if args + .get_kw_arg_opt::<[TyF64; 2]>("rays", &ray_array_ty, exec_state)? + .is_some() + || args + .get_kw_arg_opt::("sector", &RuntimeType::string(), exec_state)? + .is_some() + { + return Err(KclError::new_semantic(KclErrorDetails::new( + "angle() rays and sector require the labelled lines argument".to_owned(), + vec![args.source_range], + ))); + } ( args.get_unlabeled_kw_arg("lines", &line_array_ty, exec_state)?, AngleConstraintMode::LinesAtAngle, diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index a508c61cf98..f235cd10bc7 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -448,6 +448,10 @@ export fn angle( @input?: [Segment; 2], /// The two line segments whose oriented relative angle should match the value set with `==`. lines?: [Segment; 2], + /// Which ray to use for each line: `1` for start-to-end, `-1` for end-to-start. + rays?: [number(Count); 2], + /// Which angle sector to constrain: "primary" or "opposite". + sector?: string = "primary", ) {} /// Constrain two segments to be tangent. diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts new file mode 100644 index 00000000000..30a54e95ad8 --- /dev/null +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts @@ -0,0 +1,268 @@ +import type { ApiObject } from '@rust/kcl-lib/bindings/FrontendApi' +import { calculateArcRenderInput } from '@src/machines/sketchSolve/constraints/AngleConstraintBuilder' +import { + createLineApiObject, + createPointApiObject, +} from '@src/machines/sketchSolve/tools/sketchToolTestUtils' +import { describe, expect, it } from 'vitest' + +function createObjectsArray(objects: ApiObject[]) { + const array: ApiObject[] = [] + for (const object of objects) { + array[object.id] = object + } + return array +} + +function createAngleConstraintApiObject({ + id, + lines, + angle, + rays, + sector, +}: { + id: number + lines: [number, number] + angle: number + rays?: ['forward' | 'reverse', 'forward' | 'reverse'] + sector?: 'primary' | 'opposite' | 'Primary' | 'Opposite' +}): ApiObject { + return { + id, + kind: { + type: 'Constraint', + constraint: { + type: 'Angle', + lines, + angle: { value: angle, units: 'Deg' }, + rays, + sector: sector as 'primary' | 'opposite' | undefined, + source: { expr: `${angle}deg`, is_literal: true }, + }, + }, + label: '', + comments: '', + artifact_id: '0', + source: { type: 'Simple', range: [0, 0, 0], node_path: null }, + } +} + +function normalize([x, y]: [number, number]): [number, number] { + const length = Math.hypot(x, y) + return [x / length, y / length] +} + +function cross(a: [number, number], b: [number, number]) { + return a[0] * b[1] - a[1] * b[0] +} + +function dot(a: [number, number], b: [number, number]) { + return a[0] * b[0] + a[1] * b[1] +} + +describe('calculateArcRenderInput', () => { + it('uses angle rays and opposite sector for deterministic rendering', () => { + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const east = createPointApiObject({ id: 2, x: 10, y: 0 }) + const north = createPointApiObject({ id: 3, x: 0, y: 10 }) + const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) + const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 270, + rays: ['forward', 'forward'], + sector: 'opposite', + }) + const objects = createObjectsArray([ + origin, + east, + north, + horizontalLine, + verticalLine, + angleConstraint, + ]) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput).not.toBeNull() + expect(renderInput?.line1).toEqual([ + [0, 0], + [0, 10], + ]) + expect(renderInput?.line2).toEqual([ + [0, 0], + [10, 0], + ]) + expect(renderInput?.startAngle).toBeCloseTo(Math.PI / 2) + expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + }) + + it('accepts runtime-capitalized opposite sector metadata', () => { + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const east = createPointApiObject({ id: 2, x: 10, y: 0 }) + const north = createPointApiObject({ id: 3, x: 0, y: 10 }) + const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) + const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 270, + rays: ['forward', 'forward'], + sector: 'Opposite', + }) + const objects = createObjectsArray([ + origin, + east, + north, + horizontalLine, + verticalLine, + angleConstraint, + ]) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + }) + + it('uses the major angle value even if sector metadata is primary', () => { + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const east = createPointApiObject({ id: 2, x: 10, y: 0 }) + const north = createPointApiObject({ id: 3, x: 0, y: 10 }) + const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) + const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 270, + rays: ['forward', 'forward'], + sector: 'primary', + }) + const objects = createObjectsArray([ + origin, + east, + north, + horizontalLine, + verticalLine, + angleConstraint, + ]) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + }) + + it('uses the minor angle value even if sector metadata is opposite', () => { + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const east = createPointApiObject({ id: 2, x: 10, y: 0 }) + const north = createPointApiObject({ id: 3, x: 0, y: 10 }) + const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) + const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 90, + rays: ['forward', 'forward'], + sector: 'opposite', + }) + const objects = createObjectsArray([ + origin, + east, + north, + horizontalLine, + verticalLine, + angleConstraint, + ]) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 2) + }) + + it('keeps the opposite-sector endpoint on the second selected ray', () => { + const line1StartCoords: [number, number] = [-3.33, -5.54] + const line1EndCoords: [number, number] = [-2.38, 5.02] + const line2StartCoords: [number, number] = [-3.79, -3.55] + const line2EndCoords: [number, number] = [6.06, 0.95] + const line1Start = createPointApiObject({ + id: 1, + x: line1StartCoords[0], + y: line1StartCoords[1], + }) + const line1End = createPointApiObject({ + id: 2, + x: line1EndCoords[0], + y: line1EndCoords[1], + }) + const line2Start = createPointApiObject({ + id: 3, + x: line2StartCoords[0], + y: line2StartCoords[1], + }) + const line2End = createPointApiObject({ + id: 4, + x: line2EndCoords[0], + y: line2EndCoords[1], + }) + const line1 = createLineApiObject({ id: 10, start: 1, end: 2 }) + const line2 = createLineApiObject({ id: 11, start: 3, end: 4 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [11, 10], + angle: 360 - 60.28, + rays: ['forward', 'forward'], + sector: 'opposite', + }) + const objects = createObjectsArray([ + line1Start, + line1End, + line2Start, + line2End, + line1, + line2, + angleConstraint, + ]) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + expect(renderInput).not.toBeNull() + if (!renderInput) { + return + } + + const endAngle = renderInput.startAngle + renderInput.sweepAngle + const endDirection = normalize([Math.cos(endAngle), Math.sin(endAngle)]) + const expectedEndDirection = normalize([ + line2EndCoords[0] - line2StartCoords[0], + line2EndCoords[1] - line2StartCoords[1], + ]) + + expect(cross(endDirection, expectedEndDirection)).toBeCloseTo(0) + expect(dot(endDirection, expectedEndDirection)).toBeGreaterThan(0) + }) + + it('uses the major angle value if sector metadata is missing', () => { + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const east = createPointApiObject({ id: 2, x: 10, y: 0 }) + const north = createPointApiObject({ id: 3, x: 0, y: 10 }) + const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) + const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 270, + rays: ['forward', 'forward'], + }) + const objects = createObjectsArray([ + origin, + east, + north, + horizontalLine, + verticalLine, + angleConstraint, + ]) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + }) +}) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index bb430becbd1..7dfeaf27a45 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -124,6 +124,19 @@ export function calculateArcRenderInput( const line1Dir = normalizeVec(subVec(line1[1], line1[0])) const line2Dir = normalizeVec(subVec(line2[1], line2[0])) + const explicitRenderInput = calculateExplicitArcRenderInput( + obj, + line1, + line2, + line1Dir, + line2Dir, + center, + scale + ) + if (explicitRenderInput) { + return explicitRenderInput + } + // The distances of the line segment end points from the intersection (center) const line1SignedDistances = [ dot2d(subVec(line1[0], center), line1Dir), @@ -188,6 +201,147 @@ export function isMajorConstraintAngle(angle: ApiNumber) { return normalizeAngleRad(angle) > Math.PI } +function calculateExplicitArcRenderInput( + obj: AngleConstraint, + line1: LineSegment, + line2: LineSegment, + line1Dir: Coords2d, + line2Dir: Coords2d, + center: Coords2d, + scale: number +): ArcLineInfo | null { + const { rays, sector } = obj.kind.constraint + if (!rays) { + return null + } + + const ray1Dir = angleRayDirection(line1Dir, rays[0]) + const ray2Dir = angleRayDirection(line2Dir, rays[1]) + const primarySweep = ccwSweepBetweenDirections(ray1Dir, ray2Dir) + const oppositeSweep = ccwSweepBetweenDirections(ray2Dir, ray1Dir) + const renderSector = + angleSectorFromSweep( + normalizeAngleRad(obj.kind.constraint.angle), + primarySweep, + oppositeSweep + ) ?? + explicitAngleSector(sector) ?? + 'primary' + const start = + renderSector === 'opposite' + ? { line: line2, dir: ray2Dir } + : { line: line1, dir: ray1Dir } + const end = + renderSector === 'opposite' + ? { line: line1, dir: ray1Dir } + : { line: line2, dir: ray2Dir } + const radius = calculateExplicitArcRadius( + start.line, + end.line, + start.dir, + end.dir, + center, + scale + ) + const startVector = scaleVec(start.dir, radius) + const startAngle = Math.atan2(startVector[1], startVector[0]) + const sweepAngle = + renderSector === 'opposite' ? oppositeSweep : primarySweep + const labelPosition = addVec(center, rotateVec2d(startVector, sweepAngle / 2)) + + return { + line1: start.line, + line2: end.line, + labelPosition, + center, + radius, + startAngle, + sweepAngle, + } +} + +function angleRayDirection(lineDir: Coords2d, ray: 'forward' | 'reverse') { + return ray === 'reverse' ? scaleVec(lineDir, -1) : lineDir +} + +function explicitAngleSector(sector: unknown) { + if (sector === 'opposite' || sector === 'Opposite') { + return 'opposite' + } + if (sector === 'primary' || sector === 'Primary') { + return 'primary' + } + return null +} + +function angleSectorFromSweep( + desiredSweep: number, + primarySweep: number, + oppositeSweep: number +) { + const primaryDelta = Math.abs(desiredSweep - primarySweep) + const oppositeDelta = Math.abs(desiredSweep - oppositeSweep) + if (primaryDelta === oppositeDelta) { + return null + } + return oppositeDelta < primaryDelta ? 'opposite' : 'primary' +} + +function ccwSweepBetweenDirections(start: Coords2d, end: Coords2d) { + const startAngle = Math.atan2(start[1], start[0]) + const endAngle = Math.atan2(end[1], end[0]) + return (((endAngle - startAngle) % TAU) + TAU) % TAU +} + +function calculateExplicitArcRadius( + line1: LineSegment, + line2: LineSegment, + line1Dir: Coords2d, + line2Dir: Coords2d, + center: Coords2d, + scale: number +) { + const line1Range = projectionRange(line1, center, line1Dir) + const line2Range = projectionRange(line2, center, line2Dir) + const commonLineRange = intersectRanges(line1Range, line2Range) + const commonRayRange = commonLineRange + ? intersectRanges(commonLineRange, [0, Number.POSITIVE_INFINITY]) + : null + const radius = commonRayRange + ? findShortestRadiusFromRange(commonRayRange) + : findFallbackRayRadius([line1Range, line2Range]) + const shouldApplyNonOverlapFallback = + !commonRayRange || + Math.abs(commonRayRange[1] - commonRayRange[0]) < OVERLAP_EPSILON + return shouldApplyNonOverlapFallback + ? withMinimumMagnitude( + radius, + MIN_NON_OVERLAP_ANGLE_CONSTRAINT_RADIUS_PX * scale + ) + : radius +} + +function projectionRange( + line: LineSegment, + center: Coords2d, + direction: Coords2d +): [number, number] { + const distances = [ + dot2d(subVec(line[0], center), direction), + dot2d(subVec(line[1], center), direction), + ] + return [Math.min(...distances), Math.max(...distances)] +} + +function findFallbackRayRadius(ranges: [number, number][]) { + return ( + ranges + .flat() + .filter((distance) => distance > OVERLAP_EPSILON) + .sort((a, b) => a - b)[1] ?? 0 + ) +} + // finds the shortest radius on the range of projected distances of the 2 lines. function findShortestRadiusFromRange(range: [number, number]) { // Try the point at 15% and 85% of the interval, see which one is closer to center. From 611fe9a95a354b029e99a5073eec3ec53fee2ffb Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 3 Jun 2026 15:51:17 +0200 Subject: [PATCH 03/78] fmt --- src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index 7dfeaf27a45..cd5826302bc 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -245,8 +245,7 @@ function calculateExplicitArcRenderInput( ) const startVector = scaleVec(start.dir, radius) const startAngle = Math.atan2(startVector[1], startVector[0]) - const sweepAngle = - renderSector === 'opposite' ? oppositeSweep : primarySweep + const sweepAngle = renderSector === 'opposite' ? oppositeSweep : primarySweep const labelPosition = addVec(center, rotateVec2d(startVector, sweepAngle / 2)) return { From 56556cfae2b4ca556b914ad5f1bd9fcd938b64c4 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 3 Jun 2026 17:05:50 +0200 Subject: [PATCH 04/78] use 4 sectors and an optional reflex instead of rays --- rust/kcl-lib/src/execution/exec_ast.rs | 215 ++++++++++--- rust/kcl-lib/src/execution/geometry.rs | 11 +- rust/kcl-lib/src/frontend.rs | 4 +- rust/kcl-lib/src/frontend/sketch.rs | 20 +- rust/kcl-lib/src/std/constraints.rs | 50 ++- rust/kcl-lib/std/solver.kcl | 10 +- .../AngleConstraintBuilder.test.ts | 294 +++++++----------- .../constraints/AngleConstraintBuilder.ts | 87 +++--- 8 files changed, 354 insertions(+), 337 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index c91858bcced..fc6d03a2c0e 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -79,8 +79,6 @@ use crate::front::Object; use crate::front::ObjectId; use crate::front::ObjectKind; use crate::front::PointCtor; -use crate::frontend::sketch::AngleRayDirection as FrontAngleRayDirection; -use crate::frontend::sketch::AngleSector as FrontAngleSector; use crate::modules::ModuleExecutionOutcome; use crate::modules::ModuleId; use crate::modules::ModulePath; @@ -281,7 +279,7 @@ fn intersection_of_initial_lines( let denom = vec2_cross(r, s); if denom.abs() <= 1e-9 { return Err(KclError::new_semantic(KclErrorDetails::new( - "angle(lines = ..., rays = ...) requires non-parallel lines".to_owned(), + "angle(lines = ..., sector = ...) requires non-parallel lines".to_owned(), vec![range], ))); } @@ -290,18 +288,65 @@ fn intersection_of_initial_lines( Ok(vec2_add(p, vec2_scale(r, t))) } -fn front_angle_ray_direction(ray: AngleRayDirection) -> FrontAngleRayDirection { - match ray { - AngleRayDirection::Forward => FrontAngleRayDirection::Forward, - AngleRayDirection::Reverse => FrontAngleRayDirection::Reverse, +fn front_angle_sector(sector: AngleSector) -> u8 { + match sector { + AngleSector::One => 1, + AngleSector::Two => 2, + AngleSector::Three => 3, + AngleSector::Four => 4, } } -fn front_angle_sector(sector: AngleSector) -> FrontAngleSector { - match sector { - AngleSector::Primary => FrontAngleSector::Primary, - AngleSector::Opposite => FrontAngleSector::Opposite, - } +#[derive(Clone, Copy)] +struct AngleSectorRay { + line_index: usize, + direction: AngleRayDirection, +} + +fn angle_sector_rays(sector: AngleSector, is_reflex: bool) -> [AngleSectorRay; 2] { + let rays = match sector { + AngleSector::One => [ + AngleSectorRay { + line_index: 0, + direction: AngleRayDirection::Forward, + }, + AngleSectorRay { + line_index: 1, + direction: AngleRayDirection::Forward, + }, + ], + AngleSector::Two => [ + AngleSectorRay { + line_index: 1, + direction: AngleRayDirection::Forward, + }, + AngleSectorRay { + line_index: 0, + direction: AngleRayDirection::Reverse, + }, + ], + AngleSector::Three => [ + AngleSectorRay { + line_index: 0, + direction: AngleRayDirection::Reverse, + }, + AngleSectorRay { + line_index: 1, + direction: AngleRayDirection::Reverse, + }, + ], + AngleSector::Four => [ + AngleSectorRay { + line_index: 1, + direction: AngleRayDirection::Reverse, + }, + AngleSectorRay { + line_index: 0, + direction: AngleRayDirection::Forward, + }, + ], + }; + if is_reflex { [rays[1], rays[0]] } else { rays } } fn angle_ray_initial( @@ -324,6 +369,7 @@ fn push_points_at_angle_for_line_rays( sketch_var_ty: NumericType, line0: &ConstrainableLine2d, line1: &ConstrainableLine2d, + ray_line_indices: [usize; 2], initial_vertex: [f64; 2], initial_ray_points: [[f64; 2]; 2], ray_distance: f64, @@ -332,6 +378,18 @@ fn push_points_at_angle_for_line_rays( ) -> Result<(), KclError> { let solver_line0 = datum_line_from_constrainable(line0, range)?; let solver_line1 = datum_line_from_constrainable(line1, range)?; + let solver_ray_lines = [ + match ray_line_indices[0] { + 0 => solver_line0, + 1 => solver_line1, + _ => return Err(internal_err("Invalid angle sector line index", range)), + }, + match ray_line_indices[1] { + 0 => solver_line0, + 1 => solver_line1, + _ => return Err(internal_err("Invalid angle sector line index", range)), + }, + ]; let vertex = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_vertex, range)?; let ray0 = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_ray_points[0], range)?; let ray1 = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_ray_points[1], range)?; @@ -344,10 +402,10 @@ fn push_points_at_angle_for_line_rays( .push(Constraint::PointLineDistance(vertex, solver_line1, 0.0)); sketch_block_state .solver_constraints - .push(Constraint::PointLineDistance(ray0, solver_line0, 0.0)); + .push(Constraint::PointLineDistance(ray0, solver_ray_lines[0], 0.0)); sketch_block_state .solver_constraints - .push(Constraint::PointLineDistance(ray1, solver_line1, 0.0)); + .push(Constraint::PointLineDistance(ray1, solver_ray_lines[1], 0.0)); sketch_block_state .solver_constraints .push(Constraint::Distance(vertex, ray0, ray_distance)); @@ -3850,7 +3908,7 @@ impl Node { }; let points_at_angle_data = match *mode { AngleConstraintMode::LinesAtAngle => None, - AngleConstraintMode::PointsAtAngle { rays, .. } => { + AngleConstraintMode::PointsAtAngle { sector, reflex } => { let sketch_vars = exec_state .mod_local .sketch_block @@ -3882,24 +3940,27 @@ impl Node { let line0_length = vec2_len(vec2_sub(initial_line0.1, initial_line0.0)); let line1_length = vec2_len(vec2_sub(initial_line1.1, initial_line1.0)); let ray_distance = (line0_length.min(line1_length) * 0.25).max(1.0); + let sector_rays = angle_sector_rays(sector, reflex); + let initial_lines = [initial_line0, initial_line1]; Some(( initial_vertex, [ angle_ray_initial( initial_vertex, - initial_line0, - rays[0], + initial_lines[sector_rays[0].line_index], + sector_rays[0].direction, ray_distance, range, )?, angle_ray_initial( initial_vertex, - initial_line1, - rays[1], + initial_lines[sector_rays[1].line_index], + sector_rays[1].direction, ray_distance, range, )?, ], + [sector_rays[0].line_index, sector_rays[1].line_index], ray_distance, ezpz::datatypes::AngleKind::Other(desired_angle), )) @@ -3923,12 +3984,19 @@ impl Node { } ( AngleConstraintMode::PointsAtAngle { .. }, - Some((initial_vertex, initial_ray_points, ray_distance, angle_kind)), + Some(( + initial_vertex, + initial_ray_points, + ray_line_indices, + ray_distance, + angle_kind, + )), ) => push_points_at_angle_for_line_rays( sketch_block_state, sketch_var_ty, line0, line1, + ray_line_indices, initial_vertex, initial_ray_points, ray_distance, @@ -3953,20 +4021,19 @@ impl Node { debug_assert!(false, "{}", &message); return Err(KclError::new_internal(KclErrorDetails::new(message, vec![range]))); }; - let (rays, sector) = match *mode { + let (sector, reflex) = match *mode { AngleConstraintMode::LinesAtAngle => (None, None), - AngleConstraintMode::PointsAtAngle { rays, sector } => ( - Some([front_angle_ray_direction(rays[0]), front_angle_ray_direction(rays[1])]), - Some(front_angle_sector(sector)), - ), + AngleConstraintMode::PointsAtAngle { sector, reflex } => { + (Some(front_angle_sector(sector)), Some(reflex)) + } }; let sketch_constraint = crate::front::Constraint::Angle(Angle { lines: vec![line0.object_id, line1.object_id], angle: n.try_into().map_err(|_| { internal_err("Failed to convert angle units numeric suffix:", range) })?, - rays, sector, + reflex, source, }); sketch_block_state.sketch_constraints.push(constraint_id); @@ -5985,13 +6052,13 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_with_rays_allows_missing_unlabeled_input() { + async fn angle_labelled_lines_with_sector_allows_missing_unlabeled_input() { parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle(lines = [line1, line2], rays = [1, -1]) == 60deg + angle(lines = [line1, line2], sector = 2) == 60deg } "#, ) @@ -6000,13 +6067,13 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_accepts_opposite_sector() { + async fn angle_labelled_lines_defaults_to_sector_one() { let result = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) - line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var -3.464mm]) - angle(lines = [line1, line2], rays = [1, 1], sector = "opposite") == 360deg - 60deg + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle(lines = [line1, line2]) == 60deg } "#, ) @@ -6025,31 +6092,56 @@ sketch(on = XY) { _ => None, }) .unwrap(); - assert_eq!( - angle.rays, - Some([FrontAngleRayDirection::Forward, FrontAngleRayDirection::Forward]) - ); - assert_eq!(angle.sector, Some(FrontAngleSector::Opposite)); + assert_eq!(angle.sector, Some(1)); + assert_eq!(angle.reflex, Some(false)); } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_requires_rays() { - let err = parse_execute( + async fn angle_labelled_lines_accepts_all_four_sectors() { + parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) - line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle(lines = [line1, line2]) == 60deg + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle(lines = [line1, line2], sector = 1) == 60deg + angle(lines = [line1, line2], sector = 2) == 120deg + angle(lines = [line1, line2], sector = 3) == 60deg + angle(lines = [line1, line2], sector = 4) == 120deg } "#, ) .await - .unwrap_err(); + .unwrap(); + } - assert!( - err.to_string().contains("requires a keyword argument `rays`"), - "unexpected error: {err:?}" - ); + #[tokio::test(flavor = "multi_thread")] + async fn angle_labelled_lines_accepts_reflex_angle_for_sector() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle(lines = [line1, line2], sector = 1, reflex = true) == 360deg - 60deg +} +"#, + ) + .await + .unwrap(); + let angle = result + .exec_state + .global + .root_module_artifacts + .scene_objects + .iter() + .find_map(|object| match &object.kind { + ObjectKind::Constraint { + constraint: crate::front::Constraint::Angle(angle), + } => Some(angle), + _ => None, + }) + .unwrap(); + assert_eq!(angle.sector, Some(1)); + assert_eq!(angle.reflex, Some(true)); } #[tokio::test(flavor = "multi_thread")] @@ -6061,7 +6153,7 @@ sketch(on = XY) { line2 = line(start = [var 4mm, var 0mm], end = [var 2mm, var 3mm]) line3 = line(start = [var 0mm, var 1mm], end = [var 1mm, var 1mm]) line4 = line(start = [var 0mm, var 2mm], end = [var 1mm, var 3mm]) - angle([line1, line2], lines = [line3, line4], rays = [1, 0]) == 60deg + angle([line1, line2], lines = [line3, line4], sector = 5) == 60deg } "#, ) @@ -6069,7 +6161,7 @@ sketch(on = XY) { .unwrap_err(); assert!( - err.to_string().contains("angle() rays must be either 1 or -1"), + err.to_string().contains("angle() sector must be 1, 2, 3, or 4"), "unexpected error: {err:?}" ); } @@ -6081,7 +6173,7 @@ sketch(on = XY) { sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle(lines = [line1, line2], rays = [1, -1], sector = "side") == 60deg + angle(lines = [line1, line2], sector = 5) == 60deg } "#, ) @@ -6089,7 +6181,7 @@ sketch(on = XY) { .unwrap_err(); assert!( - err.to_string().contains("angle() sector must be either"), + err.to_string().contains("angle() sector must be 1, 2, 3, or 4"), "unexpected error: {err:?}" ); } @@ -6101,7 +6193,28 @@ sketch(on = XY) { sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 4mm, var 1mm]) - angle(lines = [line1, line2], rays = [1, -1]) == 60deg + angle(lines = [line1, line2], sector = 2) == 60deg +} +"#, + ) + .await + .unwrap_err(); + + assert!( + err.to_string() + .contains("angle(lines = ..., sector = ...) requires non-parallel lines"), + "unexpected error: {err:?}" + ); + } + + #[tokio::test(flavor = "multi_thread")] + async fn angle_sector_requires_labelled_lines() { + let err = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) + angle([line1, line2], sector = 2) == 60deg } "#, ) @@ -6110,7 +6223,7 @@ sketch(on = XY) { assert!( err.to_string() - .contains("angle(lines = ..., rays = ...) requires non-parallel lines"), + .contains("angle() sector and reflex require the labelled lines argument"), "unexpected error: {err:?}" ); } diff --git a/rust/kcl-lib/src/execution/geometry.rs b/rust/kcl-lib/src/execution/geometry.rs index b296ddda25a..93995d38069 100644 --- a/rust/kcl-lib/src/execution/geometry.rs +++ b/rust/kcl-lib/src/execution/geometry.rs @@ -2367,17 +2367,16 @@ pub enum AngleRayDirection { #[derive(Debug, Clone, Copy, PartialEq)] pub enum AngleSector { - Primary, - Opposite, + One, + Two, + Three, + Four, } #[derive(Debug, Clone, Copy, PartialEq)] pub enum AngleConstraintMode { LinesAtAngle, - PointsAtAngle { - rays: [AngleRayDirection; 2], - sector: AngleSector, - }, + PointsAtAngle { sector: AngleSector, reflex: bool }, } #[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)] diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index 831bce299d8..3df5d52854e 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -12468,8 +12468,8 @@ splineSketch = sketch(on = XY) { value: 30.0, units: NumericSuffix::Deg, }, - rays: None, sector: None, + reflex: None, source: Default::default(), }); let (src_delta, _) = frontend @@ -13191,8 +13191,8 @@ sketch(on = XY) { value: 30.0, units: NumericSuffix::Deg, }, - rays: None, sector: None, + reflex: None, source: Default::default(), }); let (src_delta, scene_delta) = frontend diff --git a/rust/kcl-lib/src/frontend/sketch.rs b/rust/kcl-lib/src/frontend/sketch.rs index a088ec740b3..3a3de50a643 100644 --- a/rust/kcl-lib/src/frontend/sketch.rs +++ b/rust/kcl-lib/src/frontend/sketch.rs @@ -563,29 +563,13 @@ pub struct Angle { pub angle: Number, #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(optional)] - pub rays: Option<[AngleRayDirection; 2]>, + pub sector: Option, #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(optional)] - pub sector: Option, + pub reflex: Option, pub source: ConstraintSource, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize, ts_rs::TS)] -#[serde(rename_all = "camelCase")] -#[ts(export, export_to = "FrontendApi.ts")] -pub enum AngleRayDirection { - Forward, - Reverse, -} - -#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize, ts_rs::TS)] -#[serde(rename_all = "camelCase")] -#[ts(export, export_to = "FrontendApi.ts")] -pub enum AngleSector { - Primary, - Opposite, -} - #[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize, ts_rs::TS)] #[ts(export, export_to = "FrontendApi.ts")] pub struct ConstraintSource { diff --git a/rust/kcl-lib/src/std/constraints.rs b/rust/kcl-lib/src/std/constraints.rs index 19deefad64c..24fe2f023b9 100644 --- a/rust/kcl-lib/src/std/constraints.rs +++ b/rust/kcl-lib/src/std/constraints.rs @@ -16,7 +16,6 @@ use crate::errors::KclError; use crate::errors::KclErrorDetails; use crate::execution::AbstractSegment; use crate::execution::AngleConstraintMode; -use crate::execution::AngleRayDirection; use crate::execution::AngleSector; use crate::execution::Artifact; use crate::execution::CodeRef; @@ -446,25 +445,14 @@ fn constrainable_line_from_kcl_value( constrainable_line_from_unsolved_segment(segment, function_name, range) } -fn angle_ray_direction(ray: TyF64, range: crate::SourceRange) -> Result { - if ray.n == 1.0 { - Ok(AngleRayDirection::Forward) - } else if ray.n == -1.0 { - Ok(AngleRayDirection::Reverse) - } else { - Err(KclError::new_semantic(KclErrorDetails::new( - "angle() rays must be either 1 or -1".to_owned(), - vec![range], - ))) - } -} - -fn angle_sector(sector: &str, range: crate::SourceRange) -> Result { - match sector { - "primary" => Ok(AngleSector::Primary), - "opposite" => Ok(AngleSector::Opposite), +fn angle_sector(sector: TyF64, range: crate::SourceRange) -> Result { + match sector.n { + 1.0 => Ok(AngleSector::One), + 2.0 => Ok(AngleSector::Two), + 3.0 => Ok(AngleSector::Three), + 4.0 => Ok(AngleSector::Four), _ => Err(KclError::new_semantic(KclErrorDetails::new( - "angle() sector must be either \"primary\" or \"opposite\"".to_owned(), + "angle() sector must be 1, 2, 3, or 4".to_owned(), vec![range], ))), } @@ -5155,34 +5143,32 @@ fn axis_constraint_points( pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result { let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); - let ray_array_ty = RuntimeType::Array(Box::new(RuntimeType::count()), ArrayLen::Known(2)); + let sector_ty = RuntimeType::count(); let (lines, mode): (Vec, AngleConstraintMode) = if let Some(lines) = args.get_kw_arg_opt("lines", &line_array_ty, exec_state)? { - let rays: [TyF64; 2] = args.get_kw_arg("rays", &ray_array_ty, exec_state)?; - let [ray0, ray1] = rays; let sector = args - .get_kw_arg_opt::("sector", &RuntimeType::string(), exec_state)? - .unwrap_or_else(|| "primary".to_owned()); + .get_kw_arg_opt::("sector", §or_ty, exec_state)? + .unwrap_or_else(|| TyF64::count(1.0)); + let reflex = args + .get_kw_arg_opt::("reflex", &RuntimeType::bool(), exec_state)? + .unwrap_or(false); ( lines, AngleConstraintMode::PointsAtAngle { - rays: [ - angle_ray_direction(ray0, args.source_range)?, - angle_ray_direction(ray1, args.source_range)?, - ], - sector: angle_sector(§or, args.source_range)?, + sector: angle_sector(sector, args.source_range)?, + reflex, }, ) } else { if args - .get_kw_arg_opt::<[TyF64; 2]>("rays", &ray_array_ty, exec_state)? + .get_kw_arg_opt::("sector", §or_ty, exec_state)? .is_some() || args - .get_kw_arg_opt::("sector", &RuntimeType::string(), exec_state)? + .get_kw_arg_opt::("reflex", &RuntimeType::bool(), exec_state)? .is_some() { return Err(KclError::new_semantic(KclErrorDetails::new( - "angle() rays and sector require the labelled lines argument".to_owned(), + "angle() sector and reflex require the labelled lines argument".to_owned(), vec![args.source_range], ))); } diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index f235cd10bc7..9e312958173 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -446,12 +446,12 @@ export fn perpendicular( export fn angle( /// The two line segments whose relative angle should match the value set with `==`. @input?: [Segment; 2], - /// The two line segments whose oriented relative angle should match the value set with `==`. + /// The two line segments whose selected angle sector should match the value set with `==`. lines?: [Segment; 2], - /// Which ray to use for each line: `1` for start-to-end, `-1` for end-to-start. - rays?: [number(Count); 2], - /// Which angle sector to constrain: "primary" or "opposite". - sector?: string = "primary", + /// Which of the four angle sectors to constrain, numbered around the line intersection. + sector?: number(Count) = 1, + /// Whether to constrain the reflex complement of the selected sector. + reflex?: bool = false, ) {} /// Constrain two segments to be tangent. diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts index 30a54e95ad8..54df2600662 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts @@ -18,14 +18,14 @@ function createAngleConstraintApiObject({ id, lines, angle, - rays, sector, + reflex, }: { id: number lines: [number, number] angle: number - rays?: ['forward' | 'reverse', 'forward' | 'reverse'] - sector?: 'primary' | 'opposite' | 'Primary' | 'Opposite' + sector?: 1 | 2 | 3 | 4 + reflex?: boolean }): ApiObject { return { id, @@ -35,8 +35,8 @@ function createAngleConstraintApiObject({ type: 'Angle', lines, angle: { value: angle, units: 'Deg' }, - rays, - sector: sector as 'primary' | 'opposite' | undefined, + sector, + reflex, source: { expr: `${angle}deg`, is_literal: true }, }, }, @@ -47,222 +47,156 @@ function createAngleConstraintApiObject({ } } -function normalize([x, y]: [number, number]): [number, number] { - const length = Math.hypot(x, y) - return [x / length, y / length] -} - -function cross(a: [number, number], b: [number, number]) { - return a[0] * b[1] - a[1] * b[0] -} - -function dot(a: [number, number], b: [number, number]) { - return a[0] * b[0] + a[1] * b[1] -} +function createSectorTestObjects( + sector: 1 | 2 | 3 | 4, + angle = 60, + reflex = false +) { + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const east = createPointApiObject({ id: 2, x: 10, y: 0 }) + const sixtyDegrees = createPointApiObject({ + id: 3, + x: 5, + y: 5 * Math.sqrt(3), + }) + const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) + const angledLine = createLineApiObject({ id: 11, start: 1, end: 3 }) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle, + sector, + reflex, + }) -describe('calculateArcRenderInput', () => { - it('uses angle rays and opposite sector for deterministic rendering', () => { - const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) - const east = createPointApiObject({ id: 2, x: 10, y: 0 }) - const north = createPointApiObject({ id: 3, x: 0, y: 10 }) - const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) - const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) - const angleConstraint = createAngleConstraintApiObject({ - id: 20, - lines: [10, 11], - angle: 270, - rays: ['forward', 'forward'], - sector: 'opposite', - }) - const objects = createObjectsArray([ + return { + angleConstraint, + objects: createObjectsArray([ origin, east, - north, + sixtyDegrees, horizontalLine, - verticalLine, + angledLine, angleConstraint, + ]), + } +} + +describe('calculateArcRenderInput', () => { + it('renders sector 1 from line0 forward to line1 forward', () => { + const { angleConstraint, objects } = createSectorTestObjects(1) + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.line1).toEqual([ + [0, 0], + [10, 0], ]) + expect(renderInput?.line2).toEqual([ + [0, 0], + [5, 5 * Math.sqrt(3)], + ]) + expect(renderInput?.startAngle).toBeCloseTo(0) + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + }) + + it('renders a reflex angle as the inverse of the selected sector', () => { + const { angleConstraint, objects } = createSectorTestObjects(1, 300, true) const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput).not.toBeNull() expect(renderInput?.line1).toEqual([ [0, 0], - [0, 10], + [5, 5 * Math.sqrt(3)], ]) expect(renderInput?.line2).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.startAngle).toBeCloseTo(Math.PI / 2) - expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + expect(renderInput?.startAngle).toBeCloseTo(Math.PI / 3) + expect(renderInput?.sweepAngle).toBeCloseTo((5 * Math.PI) / 3) }) - it('accepts runtime-capitalized opposite sector metadata', () => { - const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) - const east = createPointApiObject({ id: 2, x: 10, y: 0 }) - const north = createPointApiObject({ id: 3, x: 0, y: 10 }) - const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) - const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) - const angleConstraint = createAngleConstraintApiObject({ - id: 20, - lines: [10, 11], - angle: 270, - rays: ['forward', 'forward'], - sector: 'Opposite', - }) - const objects = createObjectsArray([ - origin, - east, - north, - horizontalLine, - verticalLine, - angleConstraint, - ]) + it('does not infer reflex rendering from a major angle value', () => { + const { angleConstraint, objects } = createSectorTestObjects(1, 300) const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + expect(renderInput?.line1).toEqual([ + [0, 0], + [10, 0], + ]) + expect(renderInput?.line2).toEqual([ + [0, 0], + [5, 5 * Math.sqrt(3)], + ]) + expect(renderInput?.startAngle).toBeCloseTo(0) + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) - it('uses the major angle value even if sector metadata is primary', () => { - const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) - const east = createPointApiObject({ id: 2, x: 10, y: 0 }) - const north = createPointApiObject({ id: 3, x: 0, y: 10 }) - const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) - const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) - const angleConstraint = createAngleConstraintApiObject({ - id: 20, - lines: [10, 11], - angle: 270, - rays: ['forward', 'forward'], - sector: 'primary', - }) - const objects = createObjectsArray([ - origin, - east, - north, - horizontalLine, - verticalLine, - angleConstraint, - ]) + it('renders sector 2 from line1 forward to line0 reverse', () => { + const { angleConstraint, objects } = createSectorTestObjects(2, 120) const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + expect(renderInput?.line1).toEqual([ + [0, 0], + [5, 5 * Math.sqrt(3)], + ]) + expect(renderInput?.line2).toEqual([ + [0, 0], + [10, 0], + ]) + expect(renderInput?.startAngle).toBeCloseTo(Math.PI / 3) + expect(renderInput?.sweepAngle).toBeCloseTo((2 * Math.PI) / 3) }) - it('uses the minor angle value even if sector metadata is opposite', () => { - const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) - const east = createPointApiObject({ id: 2, x: 10, y: 0 }) - const north = createPointApiObject({ id: 3, x: 0, y: 10 }) - const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) - const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) - const angleConstraint = createAngleConstraintApiObject({ - id: 20, - lines: [10, 11], - angle: 90, - rays: ['forward', 'forward'], - sector: 'opposite', - }) - const objects = createObjectsArray([ - origin, - east, - north, - horizontalLine, - verticalLine, - angleConstraint, - ]) + it('renders sector 3 from line0 reverse to line1 reverse', () => { + const { angleConstraint, objects } = createSectorTestObjects(3) const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 2) + expect(renderInput?.line1).toEqual([ + [0, 0], + [10, 0], + ]) + expect(renderInput?.line2).toEqual([ + [0, 0], + [5, 5 * Math.sqrt(3)], + ]) + expect(renderInput?.startAngle).toBeCloseTo(-Math.PI) + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) - it('keeps the opposite-sector endpoint on the second selected ray', () => { - const line1StartCoords: [number, number] = [-3.33, -5.54] - const line1EndCoords: [number, number] = [-2.38, 5.02] - const line2StartCoords: [number, number] = [-3.79, -3.55] - const line2EndCoords: [number, number] = [6.06, 0.95] - const line1Start = createPointApiObject({ - id: 1, - x: line1StartCoords[0], - y: line1StartCoords[1], - }) - const line1End = createPointApiObject({ - id: 2, - x: line1EndCoords[0], - y: line1EndCoords[1], - }) - const line2Start = createPointApiObject({ - id: 3, - x: line2StartCoords[0], - y: line2StartCoords[1], - }) - const line2End = createPointApiObject({ - id: 4, - x: line2EndCoords[0], - y: line2EndCoords[1], - }) - const line1 = createLineApiObject({ id: 10, start: 1, end: 2 }) - const line2 = createLineApiObject({ id: 11, start: 3, end: 4 }) - const angleConstraint = createAngleConstraintApiObject({ - id: 20, - lines: [11, 10], - angle: 360 - 60.28, - rays: ['forward', 'forward'], - sector: 'opposite', - }) - const objects = createObjectsArray([ - line1Start, - line1End, - line2Start, - line2End, - line1, - line2, - angleConstraint, - ]) + it('renders sector 4 from line1 reverse to line0 forward', () => { + const { angleConstraint, objects } = createSectorTestObjects(4, 120) const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput).not.toBeNull() - if (!renderInput) { - return - } - const endAngle = renderInput.startAngle + renderInput.sweepAngle - const endDirection = normalize([Math.cos(endAngle), Math.sin(endAngle)]) - const expectedEndDirection = normalize([ - line2EndCoords[0] - line2StartCoords[0], - line2EndCoords[1] - line2StartCoords[1], + expect(renderInput?.line1).toEqual([ + [0, 0], + [5, 5 * Math.sqrt(3)], ]) - - expect(cross(endDirection, expectedEndDirection)).toBeCloseTo(0) - expect(dot(endDirection, expectedEndDirection)).toBeGreaterThan(0) + expect(renderInput?.line2).toEqual([ + [0, 0], + [10, 0], + ]) + expect(renderInput?.startAngle).toBeCloseTo((-2 * Math.PI) / 3) + expect(renderInput?.sweepAngle).toBeCloseTo((2 * Math.PI) / 3) }) - it('uses the major angle value if sector metadata is missing', () => { - const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) - const east = createPointApiObject({ id: 2, x: 10, y: 0 }) - const north = createPointApiObject({ id: 3, x: 0, y: 10 }) - const horizontalLine = createLineApiObject({ id: 10, start: 1, end: 2 }) - const verticalLine = createLineApiObject({ id: 11, start: 1, end: 3 }) - const angleConstraint = createAngleConstraintApiObject({ - id: 20, - lines: [10, 11], - angle: 270, - rays: ['forward', 'forward'], - }) - const objects = createObjectsArray([ - origin, - east, - north, - horizontalLine, - verticalLine, - angleConstraint, - ]) + it('uses the legacy heuristic when sector metadata is absent', () => { + const { angleConstraint, objects } = createSectorTestObjects(1) + if ( + angleConstraint.kind.type === 'Constraint' && + angleConstraint.kind.constraint.type === 'Angle' + ) { + delete angleConstraint.kind.constraint.sector + } const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.sweepAngle).toBeCloseTo((3 * Math.PI) / 2) + expect(renderInput?.startAngle).toBeCloseTo(0) + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) }) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index cd5826302bc..0e526b43559 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -210,31 +210,22 @@ function calculateExplicitArcRenderInput( center: Coords2d, scale: number ): ArcLineInfo | null { - const { rays, sector } = obj.kind.constraint - if (!rays) { + const sector = explicitAngleSector(obj.kind.constraint.sector) + if (!sector) { return null } - const ray1Dir = angleRayDirection(line1Dir, rays[0]) - const ray2Dir = angleRayDirection(line2Dir, rays[1]) - const primarySweep = ccwSweepBetweenDirections(ray1Dir, ray2Dir) - const oppositeSweep = ccwSweepBetweenDirections(ray2Dir, ray1Dir) - const renderSector = - angleSectorFromSweep( - normalizeAngleRad(obj.kind.constraint.angle), - primarySweep, - oppositeSweep - ) ?? - explicitAngleSector(sector) ?? - 'primary' - const start = - renderSector === 'opposite' - ? { line: line2, dir: ray2Dir } - : { line: line1, dir: ray1Dir } - const end = - renderSector === 'opposite' - ? { line: line1, dir: ray1Dir } - : { line: line2, dir: ray2Dir } + const sectorBoundaries = angleSectorBoundaries( + sector, + line1, + line2, + line1Dir, + line2Dir + ) + const [start, end] = + obj.kind.constraint.reflex === true + ? [sectorBoundaries[1], sectorBoundaries[0]] + : sectorBoundaries const radius = calculateExplicitArcRadius( start.line, end.line, @@ -245,7 +236,7 @@ function calculateExplicitArcRenderInput( ) const startVector = scaleVec(start.dir, radius) const startAngle = Math.atan2(startVector[1], startVector[0]) - const sweepAngle = renderSector === 'opposite' ? oppositeSweep : primarySweep + const sweepAngle = ccwSweepBetweenDirections(start.dir, end.dir) const labelPosition = addVec(center, rotateVec2d(startVector, sweepAngle / 2)) return { @@ -259,31 +250,41 @@ function calculateExplicitArcRenderInput( } } -function angleRayDirection(lineDir: Coords2d, ray: 'forward' | 'reverse') { - return ray === 'reverse' ? scaleVec(lineDir, -1) : lineDir -} - function explicitAngleSector(sector: unknown) { - if (sector === 'opposite' || sector === 'Opposite') { - return 'opposite' - } - if (sector === 'primary' || sector === 'Primary') { - return 'primary' - } - return null + return sector === 1 || sector === 2 || sector === 3 || sector === 4 + ? sector + : null } -function angleSectorFromSweep( - desiredSweep: number, - primarySweep: number, - oppositeSweep: number +function angleSectorBoundaries( + sector: 1 | 2 | 3 | 4, + line1: LineSegment, + line2: LineSegment, + line1Dir: Coords2d, + line2Dir: Coords2d ) { - const primaryDelta = Math.abs(desiredSweep - primarySweep) - const oppositeDelta = Math.abs(desiredSweep - oppositeSweep) - if (primaryDelta === oppositeDelta) { - return null + switch (sector) { + case 1: + return [ + { line: line1, dir: line1Dir }, + { line: line2, dir: line2Dir }, + ] as const + case 2: + return [ + { line: line2, dir: line2Dir }, + { line: line1, dir: scaleVec(line1Dir, -1) }, + ] as const + case 3: + return [ + { line: line1, dir: scaleVec(line1Dir, -1) }, + { line: line2, dir: scaleVec(line2Dir, -1) }, + ] as const + case 4: + return [ + { line: line2, dir: scaleVec(line2Dir, -1) }, + { line: line1, dir: line1Dir }, + ] as const } - return oppositeDelta < primaryDelta ? 'opposite' : 'primary' } function ccwSweepBetweenDirections(start: Coords2d, end: Coords2d) { From fe906e6d37d757a2d0c704a9e0bef5968b0de346 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 3 Jun 2026 17:36:48 +0200 Subject: [PATCH 05/78] render overdrawn arc if labelposition doesnt lie on rendered arc --- rust/kcl-lib/src/execution/exec_ast.rs | 39 +++++++- rust/kcl-lib/src/execution/geometry.rs | 5 ++ rust/kcl-lib/src/frontend.rs | 12 ++- rust/kcl-lib/src/frontend/sketch.rs | 5 ++ rust/kcl-lib/src/std/constraints.rs | 8 +- rust/kcl-lib/std/solver.kcl | 2 + .../AngleConstraintBuilder.test.ts | 47 ++++++++++ .../constraints/AngleConstraintBuilder.ts | 57 +++++++++++- .../constraints/ArcDimensionLine.test.ts | 48 ++++++++++ .../constraints/ArcDimensionLine.ts | 90 ++++++++++++++++--- 10 files changed, 296 insertions(+), 17 deletions(-) create mode 100644 src/machines/sketchSolve/constraints/ArcDimensionLine.test.ts diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index fc6d03a2c0e..e93466752f2 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -3882,7 +3882,12 @@ impl Node { }; match &constraint.kind { - SketchConstraintKind::Angle { line0, line1, mode } => { + SketchConstraintKind::Angle { + line0, + line1, + mode, + label_position, + } => { let range = self.as_source_range(); let desired_angle = match n.ty { NumericType::Known(crate::exec::UnitType::Angle(kcmc::units::UnitAngle::Degrees)) @@ -4034,6 +4039,7 @@ impl Node { })?, sector, reflex, + label_position: label_position.clone(), source, }); sketch_block_state.sketch_constraints.push(constraint_id); @@ -6096,6 +6102,37 @@ sketch(on = XY) { assert_eq!(angle.reflex, Some(false)); } + #[tokio::test(flavor = "multi_thread")] + async fn angle_accepts_label_position() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle(lines = [line1, line2], sector = 1, labelPosition = [10mm, 11mm]) == 60deg +} +"#, + ) + .await + .unwrap(); + let angle = result + .exec_state + .global + .root_module_artifacts + .scene_objects + .iter() + .find_map(|object| match &object.kind { + ObjectKind::Constraint { + constraint: crate::front::Constraint::Angle(angle), + } => Some(angle), + _ => None, + }) + .unwrap(); + let label_position = angle.label_position.as_ref().unwrap(); + assert_eq!(label_position.x.value, 10.0); + assert_eq!(label_position.y.value, 11.0); + } + #[tokio::test(flavor = "multi_thread")] async fn angle_labelled_lines_accepts_all_four_sectors() { parse_execute( diff --git a/rust/kcl-lib/src/execution/geometry.rs b/rust/kcl-lib/src/execution/geometry.rs index 93995d38069..a0fc3cb3287 100644 --- a/rust/kcl-lib/src/execution/geometry.rs +++ b/rust/kcl-lib/src/execution/geometry.rs @@ -2389,6 +2389,11 @@ pub enum SketchConstraintKind { #[serde(skip)] #[ts(skip)] mode: AngleConstraintMode, + #[serde(rename = "labelPosition")] + #[serde(skip_serializing_if = "Option::is_none")] + #[ts(rename = "labelPosition")] + #[ts(optional)] + label_position: Option>, }, Distance { points: [ConstrainablePoint2dOrOrigin; 2], diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index 3df5d52854e..0fb5e60a568 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -3765,6 +3765,14 @@ impl FrontendState { }; let l1_ast = self.line_id_to_ast_reference(l1_id, new_ast)?; + let arguments = match &angle.label_position { + Some(label_position) => vec![ast::LabeledArg { + label: Some(ast::Identifier::new(LABEL_POSITION_PARAM)), + arg: to_ast_point2d_number(label_position).map_err(|err| KclError::refactor(err.to_string()))?, + }], + None => Default::default(), + }; + // Create the angle() call. let angle_call_ast = ast::BinaryPart::CallExpressionKw(Box::new(ast::Node::no_src(ast::CallExpressionKw { callee: ast::Node::no_src(ast_sketch2_name(ANGLE_FN)), @@ -3775,7 +3783,7 @@ impl FrontendState { non_code_meta: Default::default(), }, )))), - arguments: Default::default(), + arguments, digest: None, non_code_meta: Default::default(), }))); @@ -12470,6 +12478,7 @@ splineSketch = sketch(on = XY) { }, sector: None, reflex: None, + label_position: None, source: Default::default(), }); let (src_delta, _) = frontend @@ -13193,6 +13202,7 @@ sketch(on = XY) { }, sector: None, reflex: None, + label_position: None, source: Default::default(), }); let (src_delta, scene_delta) = frontend diff --git a/rust/kcl-lib/src/frontend/sketch.rs b/rust/kcl-lib/src/frontend/sketch.rs index 3a3de50a643..42133f6afad 100644 --- a/rust/kcl-lib/src/frontend/sketch.rs +++ b/rust/kcl-lib/src/frontend/sketch.rs @@ -567,6 +567,11 @@ pub struct Angle { #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(optional)] pub reflex: Option, + #[serde(rename = "labelPosition")] + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(rename = "labelPosition")] + #[ts(optional)] + pub label_position: Option>, pub source: ConstraintSource, } diff --git a/rust/kcl-lib/src/std/constraints.rs b/rust/kcl-lib/src/std/constraints.rs index 24fe2f023b9..5c86c606424 100644 --- a/rust/kcl-lib/src/std/constraints.rs +++ b/rust/kcl-lib/src/std/constraints.rs @@ -5144,6 +5144,7 @@ fn axis_constraint_points( pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result { let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); let sector_ty = RuntimeType::count(); + let label_position = get_constraint_label_position(exec_state, &args, "angle")?; let (lines, mode): (Vec, AngleConstraintMode) = if let Some(lines) = args.get_kw_arg_opt("lines", &line_array_ty, exec_state)? { let sector = args @@ -5188,7 +5189,12 @@ pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result { expect(renderInput?.sweepAngle).toBeCloseTo((5 * Math.PI) / 3) }) + it('uses explicit label position for sector angle rendering', () => { + const { objects } = createSectorTestObjects(1) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 60, + sector: 1, + labelPosition: [20, 30], + }) + objects[20] = angleConstraint + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.labelPosition).toEqual([20, 30]) + expect(renderInput?.labelAngle).toBeCloseTo(Math.atan2(30, 20)) + expect(renderInput?.radius).toBeCloseTo(Math.hypot(20, 30)) + expect(renderInput?.startAngle).toBeCloseTo(0) + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + }) + it('does not infer reflex rendering from a major angle value', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300) @@ -199,4 +227,23 @@ describe('calculateArcRenderInput', () => { expect(renderInput?.startAngle).toBeCloseTo(0) expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) + + it('uses explicit label position for legacy angle rendering', () => { + const { objects } = createSectorTestObjects(1) + const angleConstraint = createAngleConstraintApiObject({ + id: 20, + lines: [10, 11], + angle: 60, + labelPosition: [21, 31], + }) + objects[20] = angleConstraint + + const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + + expect(renderInput?.labelPosition).toEqual([21, 31]) + expect(renderInput?.labelAngle).toBeCloseTo(Math.atan2(31, 21)) + expect(renderInput?.radius).toBeCloseTo(Math.hypot(21, 31)) + expect(renderInput?.startAngle).toBeCloseTo(0) + expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + }) }) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index 0e526b43559..177de7a2b2e 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -8,7 +8,9 @@ import type { Coords2d } from '@src/lang/util' import { TAU, addVec, + distance2d, dot2d, + getPolarAngle2d, intersectRanges, lerp, normalizeVec, @@ -171,19 +173,28 @@ export function calculateArcRenderInput( //const signedAngle = getSignedAngleBetweenVec(line1Dir, line2Dir) const signedAngle = normalizeAngleRad(obj.kind.constraint.angle) + const explicitLabelPosition = getAngleLabelPosition(obj) + const defaultRadius = Math.abs(adjustedRadiusSigned) + const radius = getAngleArcRadius( + explicitLabelPosition, + center, + defaultRadius + ) const startVector = scaleVec(normalizeVec(line1Dir), adjustedRadiusSigned) const startAngle = Math.atan2(startVector[1], startVector[0]) - const labelPosition = addVec( + const defaultLabelPosition = addVec( center, rotateVec2d(startVector, signedAngle / 2) ) + const labelPosition = explicitLabelPosition ?? defaultLabelPosition return { line1, line2, labelPosition, + labelAngle: getAngleLabelAngle(explicitLabelPosition, center), center, - radius: Math.abs(adjustedRadiusSigned), + radius, startAngle, sweepAngle: signedAngle, } @@ -226,7 +237,8 @@ function calculateExplicitArcRenderInput( obj.kind.constraint.reflex === true ? [sectorBoundaries[1], sectorBoundaries[0]] : sectorBoundaries - const radius = calculateExplicitArcRadius( + const explicitLabelPosition = getAngleLabelPosition(obj) + const defaultRadius = calculateExplicitArcRadius( start.line, end.line, start.dir, @@ -234,15 +246,25 @@ function calculateExplicitArcRenderInput( center, scale ) + const radius = getAngleArcRadius( + explicitLabelPosition, + center, + defaultRadius + ) const startVector = scaleVec(start.dir, radius) const startAngle = Math.atan2(startVector[1], startVector[0]) const sweepAngle = ccwSweepBetweenDirections(start.dir, end.dir) - const labelPosition = addVec(center, rotateVec2d(startVector, sweepAngle / 2)) + const defaultLabelPosition = addVec( + center, + rotateVec2d(startVector, sweepAngle / 2) + ) + const labelPosition = explicitLabelPosition ?? defaultLabelPosition return { line1: start.line, line2: end.line, labelPosition, + labelAngle: getAngleLabelAngle(explicitLabelPosition, center), center, radius, startAngle, @@ -250,6 +272,33 @@ function calculateExplicitArcRenderInput( } } +function getAngleLabelPosition(obj: AngleConstraint): Coords2d | null { + const labelPosition = obj.kind.constraint.labelPosition + return labelPosition + ? [labelPosition.x.value, labelPosition.y.value] + : null +} + +function getAngleArcRadius( + labelPosition: Coords2d | null, + center: Coords2d, + fallbackRadius: number +) { + if (!labelPosition) { + return fallbackRadius + } + + const labelRadius = distance2d(labelPosition, center) + return labelRadius > OVERLAP_EPSILON ? labelRadius : fallbackRadius +} + +function getAngleLabelAngle( + labelPosition: Coords2d | null, + center: Coords2d +) { + return labelPosition ? getPolarAngle2d(center, labelPosition) : undefined +} + function explicitAngleSector(sector: unknown) { return sector === 1 || sector === 2 || sector === 3 || sector === 4 ? sector diff --git a/src/machines/sketchSolve/constraints/ArcDimensionLine.test.ts b/src/machines/sketchSolve/constraints/ArcDimensionLine.test.ts new file mode 100644 index 00000000000..60a5bda4ca5 --- /dev/null +++ b/src/machines/sketchSolve/constraints/ArcDimensionLine.test.ts @@ -0,0 +1,48 @@ +import { + getArcBodySections, + getArcLabelOffset, +} from '@src/machines/sketchSolve/constraints/ArcDimensionLine' +import { describe, expect, it } from 'vitest' + +describe('angle arc body sections', () => { + it('splits the measured arc around an in-angle label', () => { + const sweep = Math.PI / 3 + const halfGap = 0.1 + const labelOffset = getArcLabelOffset(0, sweep, Math.PI / 6) + + const sections = getArcBodySections(0, sweep, labelOffset, halfGap) + + expect(labelOffset).toBeCloseTo(Math.PI / 6) + expect(sections).toHaveLength(2) + expect(sections[0][0]).toBeCloseTo(0) + expect(sections[0][1]).toBeCloseTo(Math.PI / 6 - halfGap) + expect(sections[1][0]).toBeCloseTo(Math.PI / 6 + halfGap) + expect(sections[1][1]).toBeCloseTo(sweep) + }) + + it('overdraws before the measured start when the label is before the arc', () => { + const sweep = Math.PI / 3 + const halfGap = 0.1 + const labelOffset = getArcLabelOffset(0, sweep, -Math.PI / 6) + + const sections = getArcBodySections(0, sweep, labelOffset, halfGap) + + expect(labelOffset).toBeCloseTo(-Math.PI / 6) + expect(sections).toHaveLength(1) + expect(sections[0][0]).toBeCloseTo(-Math.PI / 6 + halfGap) + expect(sections[0][1]).toBeCloseTo(sweep) + }) + + it('overdraws after the measured end when the label is after the arc', () => { + const sweep = Math.PI / 3 + const halfGap = 0.1 + const labelOffset = getArcLabelOffset(0, sweep, Math.PI / 2) + + const sections = getArcBodySections(0, sweep, labelOffset, halfGap) + + expect(labelOffset).toBeCloseTo(Math.PI / 2) + expect(sections).toHaveLength(1) + expect(sections[0][0]).toBeCloseTo(0) + expect(sections[0][1]).toBeCloseTo(Math.PI / 2 - halfGap) + }) +}) diff --git a/src/machines/sketchSolve/constraints/ArcDimensionLine.ts b/src/machines/sketchSolve/constraints/ArcDimensionLine.ts index 745cb6d61af..687ab10d392 100644 --- a/src/machines/sketchSolve/constraints/ArcDimensionLine.ts +++ b/src/machines/sketchSolve/constraints/ArcDimensionLine.ts @@ -10,7 +10,7 @@ import { import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { Coords2d } from '@src/lang/util' import { getResolvedTheme } from '@src/lib/theme' -import { dot2d, polar2d, subVec } from '@src/lib/utils2d' +import { TAU, dot2d, polar2d, subVec } from '@src/lib/utils2d' import { createArcPositions } from '@src/machines/sketchSolve/arcPositions' import { CONSTRAINT_COLOR, @@ -24,6 +24,7 @@ import type { Line2 } from 'three/examples/jsm/lines/Line2' export const ANGLE_CONSTRAINT_ARC_BODY_ROLE = 'angle-constraint-arc-body' export const ANGLE_CONSTRAINT_GUIDE_BODY_ROLE = 'angle-constraint-guide-body' const ARROW_LENGTH_PX = 10 +const ANGLE_EPSILON = 1e-8 export type LineSegment = readonly [Coords2d, Coords2d] @@ -31,6 +32,7 @@ export type ArcLineInfo = { line1: LineSegment line2: LineSegment labelPosition: Coords2d + labelAngle?: number center: Coords2d radius: number startAngle: number @@ -46,8 +48,6 @@ export function updateArcDimensionLine( angleValue: ApiNumber ) { const { center, radius, startAngle, sweepAngle: sweep } = renderInput - const arcLengthPx = (radius * sweep) / scale - const label = group.children.find(isSpriteLabel) if (!label) { return @@ -69,8 +69,17 @@ export function updateArcDimensionLine( ) const arrowSpanPx = ARROW_LENGTH_PX * 2 const gapWidthPx = labelTextWidthPx + const labelOffset = getArcLabelOffset( + startAngle, + sweep, + renderInput.labelAngle + ) + const renderedSweep = Math.max(sweep, labelOffset) - Math.min(0, labelOffset) + const arcLengthPx = (radius * renderedSweep) / scale + const hasExplicitLabelPosition = renderInput.labelAngle !== undefined const showArrows = arcLengthPx >= arrowSpanPx - const showGap = arcLengthPx >= gapWidthPx + arrowSpanPx + const showGap = + hasExplicitLabelPosition || arcLengthPx >= gapWidthPx + arrowSpanPx // Set visibility for (const child of group.children) { @@ -84,10 +93,6 @@ export function updateArcDimensionLine( } const halfGapAngle = showGap ? (gapWidthPx * 0.5 * scale) / radius : 0 - - const labelOffset = sweep * 0.5 - const section1EndAngle = startAngle + labelOffset - halfGapAngle - const section2StartAngle = startAngle + labelOffset + halfGapAngle const endAngle = startAngle + sweep const arcLines = group.children.filter( @@ -95,8 +100,22 @@ export function updateArcDimensionLine( child.userData.type === DISTANCE_CONSTRAINT_BODY && child.userData.role === ANGLE_CONSTRAINT_ARC_BODY_ROLE ) as Line2[] - updateArc(arcLines[0], center, radius, startAngle, section1EndAngle) - updateArc(arcLines[1], center, radius, section2StartAngle, endAngle) + const bodySections = getArcBodySections( + startAngle, + sweep, + labelOffset, + halfGapAngle + ) + for (let i = 0; i < arcLines.length; i++) { + const section = bodySections[i] + if (!section) { + arcLines[i].visible = false + continue + } + + arcLines[i].visible = true + updateArc(arcLines[i], center, radius, section[0], section[1]) + } const startPoint = polar2d(center, radius, startAngle) const endPoint = polar2d(center, radius, endAngle) @@ -137,6 +156,57 @@ export function updateArcDimensionLine( updateGuideLine(guideLines[1], renderInput.line2, endPoint) } +export function getArcLabelOffset( + startAngle: number, + sweep: number, + labelAngle?: number +) { + if (labelAngle === undefined) { + return sweep * 0.5 + } + + const offset = normalizePositiveAngle(labelAngle - startAngle) + if (offset <= sweep + ANGLE_EPSILON) { + return Math.min(offset, sweep) + } + + const overdrawAfterEnd = offset - sweep + const overdrawBeforeStart = TAU - offset + return overdrawBeforeStart < overdrawAfterEnd ? offset - TAU : offset +} + +export function getArcBodySections( + startAngle: number, + sweep: number, + labelOffset: number, + halfGapAngle: number +): [number, number][] { + const endAngle = startAngle + sweep + const gapStartAngle = startAngle + labelOffset - halfGapAngle + const gapEndAngle = startAngle + labelOffset + halfGapAngle + + if (labelOffset < 0) { + return compactArcSections([[gapEndAngle, endAngle]]) + } + + if (labelOffset > sweep) { + return compactArcSections([[startAngle, gapStartAngle]]) + } + + return compactArcSections([ + [startAngle, Math.max(startAngle, gapStartAngle)], + [Math.min(endAngle, gapEndAngle), endAngle], + ]) +} + +function compactArcSections(sections: [number, number][]) { + return sections.filter(([start, end]) => end - start > ANGLE_EPSILON) +} + +function normalizePositiveAngle(angle: number) { + return ((angle % TAU) + TAU) % TAU +} + function updateArc( arc: Line2, center: Coords2d, From 06c9a1bb45a7b636c40a877d4c4434dfae5be550 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 3 Jun 2026 17:37:23 +0200 Subject: [PATCH 06/78] fmt --- .../constraints/AngleConstraintBuilder.ts | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index 177de7a2b2e..4ae35f695c9 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -175,11 +175,7 @@ export function calculateArcRenderInput( const explicitLabelPosition = getAngleLabelPosition(obj) const defaultRadius = Math.abs(adjustedRadiusSigned) - const radius = getAngleArcRadius( - explicitLabelPosition, - center, - defaultRadius - ) + const radius = getAngleArcRadius(explicitLabelPosition, center, defaultRadius) const startVector = scaleVec(normalizeVec(line1Dir), adjustedRadiusSigned) const startAngle = Math.atan2(startVector[1], startVector[0]) const defaultLabelPosition = addVec( @@ -246,11 +242,7 @@ function calculateExplicitArcRenderInput( center, scale ) - const radius = getAngleArcRadius( - explicitLabelPosition, - center, - defaultRadius - ) + const radius = getAngleArcRadius(explicitLabelPosition, center, defaultRadius) const startVector = scaleVec(start.dir, radius) const startAngle = Math.atan2(startVector[1], startVector[0]) const sweepAngle = ccwSweepBetweenDirections(start.dir, end.dir) @@ -274,9 +266,7 @@ function calculateExplicitArcRenderInput( function getAngleLabelPosition(obj: AngleConstraint): Coords2d | null { const labelPosition = obj.kind.constraint.labelPosition - return labelPosition - ? [labelPosition.x.value, labelPosition.y.value] - : null + return labelPosition ? [labelPosition.x.value, labelPosition.y.value] : null } function getAngleArcRadius( @@ -292,10 +282,7 @@ function getAngleArcRadius( return labelRadius > OVERLAP_EPSILON ? labelRadius : fallbackRadius } -function getAngleLabelAngle( - labelPosition: Coords2d | null, - center: Coords2d -) { +function getAngleLabelAngle(labelPosition: Coords2d | null, center: Coords2d) { return labelPosition ? getPolarAngle2d(center, labelPosition) : undefined } From 919ab58e54d6b5b97bc9de8833c6588f4ba37a48 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 3 Jun 2026 17:53:26 +0200 Subject: [PATCH 07/78] allow dragging angle label position --- rust/kcl-lib/src/frontend.rs | 72 ++++++- .../tools/moveTool/moveTool.spec.ts | 194 ++++++++++-------- .../sketchSolve/tools/moveTool/moveTool.ts | 4 +- 3 files changed, 178 insertions(+), 92 deletions(-) diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index 0fb5e60a568..eadfe6e5a11 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -1531,7 +1531,8 @@ impl SketchApi for FrontendState { | Constraint::HorizontalDistance(_) | Constraint::VerticalDistance(_) | Constraint::Radius(_) - | Constraint::Diameter(_), + | Constraint::Diameter(_) + | Constraint::Angle(_), } ) { return Err(KclErrorWithOutputs::no_outputs(KclError::refactor(format!( @@ -6085,7 +6086,7 @@ fn process(ctx: &AstMutateContext, node: NodeMut) -> TraversalReturn vec![ast::LabeledArg { + let lines_ast = ast::Expr::ArrayExpression(Box::new(ast::Node::no_src(ast::ArrayExpression { + elements: vec![l0_ast, l1_ast], + digest: None, + non_code_meta: Default::default(), + }))); + + let has_explicit_angle_mode = angle.sector.is_some() || angle.reflex.is_some(); + let mut arguments = if has_explicit_angle_mode { + vec![ast::LabeledArg { + label: Some(ast::Identifier::new(ANGLE_LINES_PARAM)), + arg: lines_ast.clone(), + }] + } else { + Default::default() + }; + + if let Some(sector) = angle.sector { + arguments.push(ast::LabeledArg { + label: Some(ast::Identifier::new(ANGLE_SECTOR_PARAM)), + arg: ast::Expr::Literal(Box::new(ast::Node::no_src(ast::Literal { + value: ast::LiteralValue::Number { + value: f64::from(sector), + suffix: NumericSuffix::None, + }, + raw: sector.to_string(), + digest: None, + }))), + }); + } + + if let Some(reflex) = angle.reflex { + arguments.push(ast::LabeledArg { + label: Some(ast::Identifier::new(ANGLE_REFLEX_PARAM)), + arg: ast::Expr::Literal(Box::new(ast::Node::no_src(ast::Literal { + value: ast::LiteralValue::Bool(reflex), + raw: reflex.to_string(), + digest: None, + }))), + }); + } + + if let Some(label_position) = &angle.label_position { + arguments.push(ast::LabeledArg { label: Some(ast::Identifier::new(LABEL_POSITION_PARAM)), arg: to_ast_point2d_number(label_position).map_err(|err| KclError::refactor(err.to_string()))?, - }], - None => Default::default(), - }; + }); + } // Create the angle() call. let angle_call_ast = ast::BinaryPart::CallExpressionKw(Box::new(ast::Node::no_src(ast::CallExpressionKw { callee: ast::Node::no_src(ast_sketch2_name(ANGLE_FN)), - unlabeled: Some(ast::Expr::ArrayExpression(Box::new(ast::Node::no_src( - ast::ArrayExpression { - elements: vec![l0_ast, l1_ast], - digest: None, - non_code_meta: Default::default(), - }, - )))), + unlabeled: (!has_explicit_angle_mode).then_some(lines_ast), arguments, digest: None, non_code_meta: Default::default(), @@ -13299,6 +13336,74 @@ sketch(on = XY) { mock_ctx.close().await; } + #[tokio::test(flavor = "multi_thread")] + async fn test_lines_angle_with_sector_uses_labelled_lines() { + let initial_source = "\ +sketch(on = XY) { + line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line(start = [var 0mm, var 0mm], end = [var 0mm, var 4mm]) +} +"; + + let program = Program::parse(initial_source).unwrap().0.unwrap(); + + let mut frontend = FrontendState::new(); + + let mock_ctx = ExecutorContext::new_mock(None).await; + let version = Version(0); + + frontend.program = program.clone(); + let outcome = mock_ctx.run_mock(&program, &MockConfig::default()).await.unwrap(); + frontend.update_state_after_exec(outcome, true); + let sketch_object = find_first_sketch_object(&frontend.scene_graph).unwrap(); + let sketch_id = sketch_object.id; + let sketch = expect_sketch(sketch_object); + let line1_id = *sketch.segments.get(2).unwrap(); + let line2_id = *sketch.segments.get(5).unwrap(); + + let constraint = Constraint::Angle(Angle { + lines: vec![line1_id, line2_id], + angle: Number { + value: 270.0, + units: NumericSuffix::Deg, + }, + sector: Some(1), + reflex: Some(true), + label_position: Some(Point2d { + x: Number { + value: -0.73, + units: NumericSuffix::Mm, + }, + y: Number { + value: 0.75, + units: NumericSuffix::Mm, + }, + }), + source: Default::default(), + }); + let (src_delta, _) = frontend + .add_constraint(&mock_ctx, version, sketch_id, constraint) + .await + .unwrap(); + assert_eq!( + src_delta.text.as_str(), + "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 0mm, var 4mm]) + angle( + lines = [line1, line2], + sector = 1, + reflex = true, + labelPosition = [-0.73mm, 0.75mm], +) == 270deg +} +" + ); + + mock_ctx.close().await; + } + #[tokio::test(flavor = "multi_thread")] async fn test_segments_tangent() { let initial_source = "\ diff --git a/src/machines/sketchSolve/sketchSolveDiagram.ts b/src/machines/sketchSolve/sketchSolveDiagram.ts index 6b4fd9f6e87..8ec93246dc4 100644 --- a/src/machines/sketchSolve/sketchSolveDiagram.ts +++ b/src/machines/sketchSolve/sketchSolveDiagram.ts @@ -591,6 +591,15 @@ export const sketchSolveMachine = setup({ context.kclManager.fileSettings.defaultLengthUnit ) + if (currentSelections.length === 0) { + sendToActorIfActive(self, { + type: 'equip tool', + data: { tool: 'dimensionTool' }, + keepSelection, + }) + return + } + if (currentSelections.length === 2) { const first = currentSelections[0] const second = currentSelections[1] diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts new file mode 100644 index 00000000000..58513b5e1d7 --- /dev/null +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -0,0 +1,309 @@ +import type { + ApiConstraint, + ApiObject, +} from '@rust/kcl-lib/bindings/FrontendApi' +import type { Coords2d } from '@src/lang/util' +import { + type DimensionAngleDraftContext, + buildDimensionAngleConstraint, + machine as dimensionTool, + getDimensionAngleSelection, +} from '@src/machines/sketchSolve/tools/dimensionTool' +import { + createLineApiObject, + createMockKclManager, + createMockRustContext, + createMockSceneInfra, + createPointApiObject, + createSceneGraphDelta, +} from '@src/machines/sketchSolve/tools/sketchToolTestUtils' +import { describe, expect, it, vi } from 'vitest' +import { assign, createActor, setup, waitFor } from 'xstate' + +function createSketchApiObject({ id }: { id: number }): ApiObject { + return { + id, + kind: { + type: 'Sketch', + args: { on: { default: 'xy' } }, + plane: 0, + segments: [], + constraints: [], + }, + label: '', + comments: '', + artifact_id: '0', + source: { type: 'Simple', range: [0, 0, 0], node_path: null }, + } +} + +function createAngleConstraintObject({ + id, + constraint, +}: { + id: number + constraint: ApiConstraint +}): ApiObject { + return { + id, + kind: { + type: 'Constraint', + constraint, + }, + label: '', + comments: '', + artifact_id: '0', + source: { type: 'Simple', range: [0, 0, 0], node_path: null }, + } +} + +function createMouseEvent(point: Coords2d) { + return { + mouseEvent: { + which: 1, + detail: 1, + }, + intersectionPoint: { + twoD: { + x: point[0], + y: point[1], + }, + }, + } +} + +function createParentHarness(objects: ApiObject[]) { + const sceneInfra = createMockSceneInfra() + const rustContext = createMockRustContext() + const kclManager = createMockKclManager() + const events: Array<{ type: string; data?: unknown }> = [] + let nextConstraintId = 30 + + rustContext.addConstraint = vi.fn(async (_version, _sketchId, constraint) => { + const constraintId = nextConstraintId++ + const resultObjects = [ + ...objects, + createAngleConstraintObject({ id: constraintId, constraint }), + ] + + return { + kclSource: { text: '' }, + sceneGraphDelta: createSceneGraphDelta(resultObjects, [constraintId]), + checkpointId: null, + } + }) as typeof rustContext.addConstraint + rustContext.deleteObjects = vi.fn(async () => ({ + kclSource: { text: '' }, + sceneGraphDelta: createSceneGraphDelta(objects), + checkpointId: null, + })) as typeof rustContext.deleteObjects + + const sceneGraphDelta = createSceneGraphDelta(objects) + const parentMachine = setup({ + types: { + context: {} as { + sceneGraphDelta: typeof sceneGraphDelta + }, + events: {} as + | { type: 'update selected ids'; data: unknown } + | { type: 'update hovered id'; data: unknown } + | { + type: 'update sketch outcome' + data: { sceneGraphDelta: typeof sceneGraphDelta } + } + | { type: 'set draft entities'; data: unknown } + | { type: 'clear draft entities' } + | { type: 'delete draft entities' }, + input: {}, + }, + actors: { + childTool: dimensionTool, + }, + actions: { + 'record event': assign(({ context, event }) => { + events.push(event) + if (event.type !== 'update sketch outcome') { + return {} + } + + return { + sceneGraphDelta: event.data.sceneGraphDelta, + } + }), + }, + }).createMachine({ + context: { + sceneGraphDelta, + }, + initial: 'running', + on: { + 'update selected ids': { actions: 'record event' }, + 'update hovered id': { actions: 'record event' }, + 'update sketch outcome': { actions: 'record event' }, + 'set draft entities': { actions: 'record event' }, + 'clear draft entities': { actions: 'record event' }, + 'delete draft entities': { actions: 'record event' }, + }, + states: { + running: { + invoke: { + id: 'childTool', + src: 'childTool', + input: { + sceneInfra, + rustContext, + kclManager, + sketchId: 0, + initialObjects: sceneGraphDelta.new_graph.objects, + }, + }, + }, + }, + }) + + const actor = createActor(parentMachine, { input: {} }).start() + return { + actor, + sceneInfra, + rustContext, + events, + } +} + +describe('dimensionTool angle selection', () => { + const lineDirections = { + line0Direction: [1, 0] as Coords2d, + line1Direction: [Math.cos(Math.PI / 3), Math.sin(Math.PI / 3)] as Coords2d, + } + const angleContext: DimensionAngleDraftContext = { + line0Id: 10, + line1Id: 11, + ...lineDirections, + vertex: [0, 0], + baseWedgeIndex: 0, + } + + it('maps cursor sectors relative to the clicked rays', () => { + expect(getDimensionAngleSelection([1, 0.25], angleContext)).toEqual({ + sector: 1, + reflex: false, + }) + expect(getDimensionAngleSelection([0, 10], angleContext)).toEqual({ + sector: 2, + reflex: false, + }) + expect(getDimensionAngleSelection([1, -1], angleContext)).toEqual({ + sector: 4, + reflex: false, + }) + expect(getDimensionAngleSelection([-1, -0.6], angleContext)).toEqual({ + sector: 1, + reflex: true, + }) + }) + + it('uses reflex when the visual wedge is opposite the directed KCL sector', () => { + const clockwiseContext: DimensionAngleDraftContext = { + line0Id: 10, + line1Id: 11, + line0Direction: [ + Math.cos(Math.PI / 3), + Math.sin(Math.PI / 3), + ] as Coords2d, + line1Direction: [1, 0], + vertex: [0, 0], + baseWedgeIndex: 0, + } + + expect(getDimensionAngleSelection([1, 0.25], clockwiseContext)).toEqual({ + sector: 1, + reflex: true, + }) + expect(getDimensionAngleSelection([0, 10], clockwiseContext)).toEqual({ + sector: 4, + reflex: true, + }) + expect(getDimensionAngleSelection([1, -1], clockwiseContext)).toEqual({ + sector: 2, + reflex: true, + }) + expect(getDimensionAngleSelection([-1, -0.3], clockwiseContext)).toEqual({ + sector: 1, + reflex: false, + }) + }) + + it('builds the labelled angle constraint with sector, reflex, and label position', () => { + const constraint = buildDimensionAngleConstraint( + angleContext, + [-1, -0.6], + 'Mm' + ) + + expect(constraint).toEqual({ + type: 'Angle', + lines: [10, 11], + angle: { value: 300, units: 'Deg' }, + sector: 1, + reflex: true, + labelPosition: { + x: { value: -1, units: 'Mm' }, + y: { value: -0.6, units: 'Mm' }, + }, + source: { + expr: '300deg', + is_literal: true, + }, + }) + }) +}) + +describe('dimensionTool', () => { + it('creates a draft labelled angle constraint after selecting two lines', async () => { + const sketch = createSketchApiObject({ id: 0 }) + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const line0End = createPointApiObject({ id: 2, x: 10, y: 0 }) + const line1End = createPointApiObject({ + id: 3, + x: 5, + y: 8.660254037844386, + }) + const line0 = createLineApiObject({ id: 10, start: 1, end: 2 }) + const line1 = createLineApiObject({ id: 11, start: 1, end: 3 }) + const objects = [sketch, origin, line0End, line1End, line0, line1] + const { actor, sceneInfra, rustContext, events } = + createParentHarness(objects) + const callbacks = (sceneInfra.setCallbacks as any).mock.calls[0][0] + + callbacks.onClick(createMouseEvent([8, 0])) + callbacks.onClick(createMouseEvent([5, 8.660254037844386])) + + await waitFor( + actor, + () => (rustContext.addConstraint as any).mock.calls.length === 1 + ) + + expect((rustContext.addConstraint as any).mock.calls[0][2]).toEqual({ + type: 'Angle', + lines: [10, 11], + angle: { value: 60, units: 'Deg' }, + sector: 1, + reflex: false, + labelPosition: { + x: { value: 5, units: 'Mm' }, + y: { value: 8.66, units: 'Mm' }, + }, + source: { + expr: '60deg', + is_literal: true, + }, + }) + expect(events).toContainEqual({ + type: 'set draft entities', + data: { + segmentIds: [], + constraintIds: [30], + }, + }) + }) +}) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 4514d1fa195..2469d4282c5 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -1,101 +1,960 @@ -import type { SceneGraphDelta } from '@rust/kcl-lib/bindings/FrontendApi' +import type { + ApiConstraint, + ApiObject, + SceneGraphDelta, + SourceDelta, +} from '@rust/kcl-lib/bindings/FrontendApi' +import type { NumericSuffix } from '@rust/kcl-lib/bindings/NumericSuffix' import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { KclManager } from '@src/lang/KclManager' +import type { Coords2d } from '@src/lang/util' +import { baseUnitToNumericSuffix } from '@src/lang/wasm' +import { SKETCH_FILE_VERSION } from '@src/lib/constants' import type RustContext from '@src/lib/rustContext' +import { jsAppSettings } from '@src/lib/settings/settingsUtils' +import { roundOff } from '@src/lib/utils' +import { + TAU, + dot2d, + length2d, + normalizeVec, + scaleVec, + subVec, +} from '@src/lib/utils2d' +import { + getLinePoints, + isLineSegment, +} from '@src/machines/sketchSolve/constraints/constraintUtils' +import { findClosestApiObjects } from '@src/machines/sketchSolve/interaction/interactionHelpers' +import { getCurrentSketchObjectsById } from '@src/machines/sketchSolve/sceneGraphUtils' import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' +import type { SketchSolveSelectionId } from '@src/machines/sketchSolve/sketchSolveSelection' import type { BaseToolEvent } from '@src/machines/sketchSolve/tools/sharedToolTypes' -import { createMachine, setup } from 'xstate' +import { setup } from 'xstate' -type DimensionToolEvent = BaseToolEvent +type DimensionToolContext = { + sceneInfra: SceneInfra + rustContext: RustContext + kclManager: KclManager + sketchId: number + initialObjects: ApiObject[] +} + +type DimensionToolInput = { + sceneInfra: SceneInfra + rustContext: RustContext + kclManager: KclManager + sketchId: number + initialSelectionIds?: SketchSolveSelectionId[] + initialObjects?: ApiObject[] + sceneGraphDelta?: SceneGraphDelta +} + +type DimensionToolEvent = + | BaseToolEvent + | { + type: 'done' + } + +type ParentSketchSolveEvent = + | { + type: 'update selected ids' + data: { + selectedIds?: SketchSolveSelectionId[] + duringAreaSelectIds?: number[] + replaceExistingSelection?: boolean + } + } + | { + type: 'update hovered id' + data: { + hoveredId: SketchSolveSelectionId | null + } + } + | { + type: 'update sketch outcome' + data: { + sourceDelta: SourceDelta + sceneGraphDelta: SceneGraphDelta + checkpointId?: number | null + updateEditor?: boolean + writeToDisk?: boolean + addToHistory?: boolean + suppressExecOutcomeIssues?: boolean + } + } + | { + type: 'set draft entities' + data: { + segmentIds: number[] + constraintIds: number[] + } + } + | { + type: 'clear draft entities' + } + | { + type: 'delete draft entities' + } + +type LineSelection = { + id: number + clickPoint: Coords2d +} + +type RayDirection = 'forward' | 'reverse' +export type AngleSector = 1 | 2 | 3 | 4 +type AngleRayKey = + | 'line0Forward' + | 'line0Reverse' + | 'line1Forward' + | 'line1Reverse' + +export type DimensionAngleDraftContext = { + line0Id: number + line1Id: number + line0Direction: Coords2d + line1Direction: Coords2d + vertex: Coords2d + baseWedgeIndex: number +} + +type DimensionAngleSelection = { + sector: AngleSector + reflex: boolean +} + +type AngleRay = { + key: AngleRayKey + direction: Coords2d +} + +type AngleWedge = { + start: AngleRay + end: AngleRay + selection: DimensionAngleSelection +} + +type DraftRuntime = { + firstSelection: LineSelection | null + angleContext: DimensionAngleDraftContext | null + draftConstraintId: number | null + lastDraftKey: string | null + previewInFlight: boolean + queuedMousePoint: Coords2d | null +} + +const LINE_INTERSECTION_EPSILON = 1e-8 +const SECTOR_EPSILON = 1e-9 + +function getDefaultLengthUnit(kclManager: KclManager): NumericSuffix { + return baseUnitToNumericSuffix( + kclManager.fileSettings.defaultLengthUnit ?? 'mm' + ) +} + +function sendParent( + self: { _parent?: { send: (event: unknown) => void } }, + event: ParentSketchSolveEvent +) { + self._parent?.send(event) +} + +function createRuntime(): DraftRuntime { + return { + firstSelection: null, + angleContext: null, + draftConstraintId: null, + lastDraftKey: null, + previewInFlight: false, + queuedMousePoint: null, + } +} + +function getObjects(context: DimensionToolContext) { + return context.initialObjects +} + +function getLineIntersection( + line0Points: readonly [Coords2d, Coords2d], + line1Points: readonly [Coords2d, Coords2d] +): Coords2d | null { + const [p0, p1] = line0Points + const [p2, p3] = line1Points + const line0Direction = subVec(p1, p0) + const line1Direction = subVec(p3, p2) + const denominator = + line0Direction[0] * line1Direction[1] - + line0Direction[1] * line1Direction[0] + + if (Math.abs(denominator) < LINE_INTERSECTION_EPSILON) { + return null + } + + const delta = subVec(p2, p0) + const t = + (delta[0] * line1Direction[1] - delta[1] * line1Direction[0]) / denominator + + return [p0[0] + t * line0Direction[0], p0[1] + t * line0Direction[1]] +} + +function getClickedRayDirection( + linePoints: readonly [Coords2d, Coords2d], + vertex: Coords2d, + clickPoint: Coords2d +): RayDirection { + const lineDirection = normalizeVec(subVec(linePoints[1], linePoints[0])) + const clickDirection = subVec(clickPoint, vertex) + return dot2d(clickDirection, lineDirection) >= 0 ? 'forward' : 'reverse' +} + +export function getBaseAngleSector( + line0Ray: RayDirection, + line1Ray: RayDirection +): AngleSector { + if (line0Ray === 'forward' && line1Ray === 'forward') { + return 1 + } + if (line0Ray === 'reverse' && line1Ray === 'forward') { + return 2 + } + if (line0Ray === 'reverse' && line1Ray === 'reverse') { + return 3 + } + return 4 +} + +function getDimensionAngleContext( + firstSelection: LineSelection, + secondSelection: LineSelection, + objects: ApiObject[] +): DimensionAngleDraftContext | null { + const line0 = objects[firstSelection.id] + const line1 = objects[secondSelection.id] + const line0Points = getLinePoints(line0, objects) + const line1Points = getLinePoints(line1, objects) + if (!line0Points || !line1Points) { + return null + } + + const line0Vector = subVec(line0Points[1], line0Points[0]) + const line1Vector = subVec(line1Points[1], line1Points[0]) + if (length2d(line0Vector) === 0 || length2d(line1Vector) === 0) { + return null + } + + const vertex = getLineIntersection(line0Points, line1Points) + if (!vertex) { + return null + } + + const line0Ray = getClickedRayDirection( + line0Points, + vertex, + firstSelection.clickPoint + ) + const line1Ray = getClickedRayDirection( + line1Points, + vertex, + secondSelection.clickPoint + ) + + const angleContext = { + line0Id: firstSelection.id, + line1Id: secondSelection.id, + line0Direction: normalizeVec(line0Vector), + line1Direction: normalizeVec(line1Vector), + vertex, + baseWedgeIndex: 0, + } + angleContext.baseWedgeIndex = findWedgeIndexForRays( + angleContext, + getClickedRayKey(0, line0Ray), + getClickedRayKey(1, line1Ray) + ) + return angleContext +} + +function normalizeAngle(angle: number) { + return ((angle % TAU) + TAU) % TAU +} + +function getCcwSweep(start: Coords2d, end: Coords2d) { + return normalizeAngle( + Math.atan2(end[1], end[0]) - Math.atan2(start[1], start[0]) + ) +} + +function isDirectionInSector( + direction: Coords2d, + start: Coords2d, + end: Coords2d +) { + return ( + getCcwSweep(start, direction) <= getCcwSweep(start, end) + SECTOR_EPSILON + ) +} + +function reverseDirection(direction: Coords2d): Coords2d { + return scaleVec(direction, -1) +} + +function getClickedRayKey( + lineIndex: 0 | 1, + direction: RayDirection +): AngleRayKey { + if (lineIndex === 0) { + return direction === 'forward' ? 'line0Forward' : 'line0Reverse' + } + return direction === 'forward' ? 'line1Forward' : 'line1Reverse' +} + +export function getAngleSectorRays( + angleContext: Pick< + DimensionAngleDraftContext, + 'line0Direction' | 'line1Direction' + >, + sector: AngleSector +): [Coords2d, Coords2d] { + switch (sector) { + case 1: + return [angleContext.line0Direction, angleContext.line1Direction] + case 2: + return [ + angleContext.line1Direction, + reverseDirection(angleContext.line0Direction), + ] + case 3: + return [ + reverseDirection(angleContext.line0Direction), + reverseDirection(angleContext.line1Direction), + ] + case 4: + return [ + reverseDirection(angleContext.line1Direction), + angleContext.line0Direction, + ] + } +} + +const DIRECT_SECTOR_BOUNDARIES = [ + { + sector: 1, + startKey: 'line0Forward', + endKey: 'line1Forward', + }, + { + sector: 2, + startKey: 'line1Forward', + endKey: 'line0Reverse', + }, + { + sector: 3, + startKey: 'line0Reverse', + endKey: 'line1Reverse', + }, + { + sector: 4, + startKey: 'line1Reverse', + endKey: 'line0Forward', + }, +] as const satisfies ReadonlyArray<{ + sector: AngleSector + startKey: AngleRayKey + endKey: AngleRayKey +}> + +function getAngleRays( + angleContext: Pick< + DimensionAngleDraftContext, + 'line0Direction' | 'line1Direction' + > +): AngleRay[] { + const rays: AngleRay[] = [ + { key: 'line0Forward', direction: angleContext.line0Direction }, + { + key: 'line0Reverse', + direction: reverseDirection(angleContext.line0Direction), + }, + { key: 'line1Forward', direction: angleContext.line1Direction }, + { + key: 'line1Reverse', + direction: reverseDirection(angleContext.line1Direction), + }, + ] + + return rays.sort( + (left, right) => + normalizeAngle(Math.atan2(left.direction[1], left.direction[0])) - + normalizeAngle(Math.atan2(right.direction[1], right.direction[0])) + ) +} + +function getSelectionForWedge(startKey: AngleRayKey, endKey: AngleRayKey) { + for (const boundary of DIRECT_SECTOR_BOUNDARIES) { + if (boundary.startKey === startKey && boundary.endKey === endKey) { + return { + sector: boundary.sector, + reflex: false, + } + } + + if (boundary.startKey === endKey && boundary.endKey === startKey) { + return { + sector: boundary.sector, + reflex: true, + } + } + } +} + +function getAngleWedges( + angleContext: Pick< + DimensionAngleDraftContext, + 'line0Direction' | 'line1Direction' + > +): AngleWedge[] { + const rays = getAngleRays(angleContext) + const wedges: AngleWedge[] = [] + + for (let index = 0; index < rays.length; index++) { + const start = rays[index] + const end = rays[(index + 1) % rays.length] + const selection = getSelectionForWedge(start.key, end.key) + if (selection) { + wedges.push({ start, end, selection }) + } + } + + return wedges +} + +function findWedgeIndexForRays( + angleContext: Pick< + DimensionAngleDraftContext, + 'line0Direction' | 'line1Direction' + >, + line0Ray: AngleRayKey, + line1Ray: AngleRayKey +) { + const wedges = getAngleWedges(angleContext) + return Math.max( + wedges.findIndex( + (wedge) => + (wedge.start.key === line0Ray && wedge.end.key === line1Ray) || + (wedge.start.key === line1Ray && wedge.end.key === line0Ray) + ), + 0 + ) +} + +function getBaseWedgeIndex(angleContext: DimensionAngleDraftContext): number { + return angleContext.baseWedgeIndex +} + +function getHoveredWedgeIndex( + mousePoint: Coords2d, + angleContext: DimensionAngleDraftContext +): number { + const mouseDirection = subVec(mousePoint, angleContext.vertex) + if (length2d(mouseDirection) === 0) { + return getBaseWedgeIndex(angleContext) + } + + const wedges = getAngleWedges(angleContext) + const hoveredIndex = wedges.findIndex((wedge) => + isDirectionInSector( + mouseDirection, + wedge.start.direction, + wedge.end.direction + ) + ) + if (hoveredIndex !== -1) { + return hoveredIndex + } + + return getBaseWedgeIndex(angleContext) +} + +function invertAngleSelection( + selection: DimensionAngleSelection +): DimensionAngleSelection { + return { + sector: selection.sector, + reflex: !selection.reflex, + } +} + +function getOppositeWedgeIndex(wedgeIndex: number) { + return (wedgeIndex + 2) % 4 +} + +function getWedgeSelection( + angleContext: DimensionAngleDraftContext, + wedgeIndex: number +) { + const wedges = getAngleWedges(angleContext) + return ( + wedges[wedgeIndex]?.selection ?? + wedges[getBaseWedgeIndex(angleContext)]?.selection + ) +} + +export function getDimensionAngleSelection( + mousePoint: Coords2d, + angleContext: DimensionAngleDraftContext +): DimensionAngleSelection { + const baseWedgeIndex = getBaseWedgeIndex(angleContext) + const hoveredWedgeIndex = getHoveredWedgeIndex(mousePoint, angleContext) + const baseSelection = getWedgeSelection(angleContext, baseWedgeIndex) + + if ( + baseSelection && + hoveredWedgeIndex === getOppositeWedgeIndex(baseWedgeIndex) + ) { + return invertAngleSelection(baseSelection) + } + + const hoveredSelection = getWedgeSelection(angleContext, hoveredWedgeIndex) + if (hoveredSelection) { + return hoveredSelection + } + + return { + sector: 1, + reflex: false, + } +} + +function getDimensionAngleDegrees( + angleContext: DimensionAngleDraftContext, + selection: DimensionAngleSelection +) { + let [start, end] = getAngleSectorRays(angleContext, selection.sector) + if (selection.reflex) { + ;[start, end] = [end, start] + } + + return roundOff((getCcwSweep(start, end) * 180) / Math.PI) +} + +function toNumber(value: number, units: NumericSuffix) { + return { + value: roundOff(value), + units, + } +} + +export function buildDimensionAngleConstraint( + angleContext: DimensionAngleDraftContext, + mousePoint: Coords2d, + units: NumericSuffix +): ApiConstraint { + const selection = getDimensionAngleSelection(mousePoint, angleContext) + const angle = getDimensionAngleDegrees(angleContext, selection) + + return { + type: 'Angle', + lines: [angleContext.line0Id, angleContext.line1Id], + angle: { value: angle, units: 'Deg' }, + sector: selection.sector, + reflex: selection.reflex, + labelPosition: { + x: toNumber(mousePoint[0], units), + y: toNumber(mousePoint[1], units), + }, + source: { + expr: `${angle}deg`, + is_literal: true, + }, + } +} + +function getConstraintIdFromResult(result: { + sceneGraphDelta: SceneGraphDelta +}): number | null { + return ( + [...result.sceneGraphDelta.new_objects].reverse().find((objectId) => { + const object = result.sceneGraphDelta.new_graph.objects[objectId] + return ( + object?.kind.type === 'Constraint' && + object.kind.constraint.type === 'Angle' + ) + }) ?? null + ) +} + +function getDraftKey(constraint: ApiConstraint) { + if (constraint.type !== 'Angle') { + return '' + } + + return [ + constraint.lines.join(','), + constraint.angle.value, + constraint.sector ?? '', + constraint.reflex === true ? 'reflex' : 'direct', + constraint.labelPosition?.x.value ?? '', + constraint.labelPosition?.y.value ?? '', + ].join(':') +} + +async function deleteDraftConstraint( + runtime: DraftRuntime, + context: DimensionToolContext +) { + if (runtime.draftConstraintId === null) { + return + } + + await context.rustContext.deleteObjects( + SKETCH_FILE_VERSION, + context.sketchId, + [runtime.draftConstraintId], + [], + jsAppSettings(context.rustContext.settingsActor), + false + ) + runtime.draftConstraintId = null +} + +function sendPreviewResultToParent( + self: { _parent?: { send: (event: unknown) => void } }, + result: { + kclSource: SourceDelta + sceneGraphDelta: SceneGraphDelta + checkpointId?: number | null + } +) { + sendParent(self, { + type: 'update sketch outcome', + data: { + sourceDelta: result.kclSource, + sceneGraphDelta: result.sceneGraphDelta, + checkpointId: result.checkpointId ?? null, + writeToDisk: false, + addToHistory: false, + suppressExecOutcomeIssues: true, + }, + }) +} + +function sendFinalResultToParent( + self: { _parent?: { send: (event: unknown) => void } }, + result: { + kclSource: SourceDelta + sceneGraphDelta: SceneGraphDelta + checkpointId?: number | null + } +) { + sendParent(self, { + type: 'update sketch outcome', + data: { + sourceDelta: result.kclSource, + sceneGraphDelta: result.sceneGraphDelta, + checkpointId: result.checkpointId ?? null, + }, + }) +} + +async function replaceDraftAngleConstraint( + runtime: DraftRuntime, + context: DimensionToolContext, + self: { _parent?: { send: (event: unknown) => void } }, + mousePoint: Coords2d +) { + if (!runtime.angleContext) { + return + } + + const constraint = buildDimensionAngleConstraint( + runtime.angleContext, + mousePoint, + getDefaultLengthUnit(context.kclManager) + ) + const draftKey = getDraftKey(constraint) + if (draftKey === runtime.lastDraftKey) { + return + } + + await deleteDraftConstraint(runtime, context) + + const result = await context.rustContext.addConstraint( + SKETCH_FILE_VERSION, + context.sketchId, + constraint, + jsAppSettings(context.rustContext.settingsActor), + false + ) + const constraintId = getConstraintIdFromResult(result) + if (constraintId === null) { + return + } + + runtime.draftConstraintId = constraintId + runtime.lastDraftKey = draftKey + + sendPreviewResultToParent(self, result) + sendParent(self, { + type: 'set draft entities', + data: { + segmentIds: [], + constraintIds: [constraintId], + }, + }) +} + +function requestDraftPreview( + runtime: DraftRuntime, + context: DimensionToolContext, + self: { _parent?: { send: (event: unknown) => void } }, + mousePoint: Coords2d +) { + runtime.queuedMousePoint = mousePoint + if (runtime.previewInFlight) { + return + } + + runtime.previewInFlight = true + void (async () => { + try { + while (runtime.queuedMousePoint) { + const nextMousePoint = runtime.queuedMousePoint + runtime.queuedMousePoint = null + await replaceDraftAngleConstraint( + runtime, + context, + self, + nextMousePoint + ) + } + } catch (error) { + toastSketchSolveError(error) + } finally { + runtime.previewInFlight = false + } + })() +} + +async function commitDraftAngleConstraint( + runtime: DraftRuntime, + context: DimensionToolContext, + self: { + _parent?: { send: (event: unknown) => void } + send: (event: DimensionToolEvent) => void + }, + mousePoint: Coords2d +) { + if (!runtime.angleContext) { + return + } + + const constraint = buildDimensionAngleConstraint( + runtime.angleContext, + mousePoint, + getDefaultLengthUnit(context.kclManager) + ) + + try { + await deleteDraftConstraint(runtime, context) + const result = await context.rustContext.addConstraint( + SKETCH_FILE_VERSION, + context.sketchId, + constraint, + jsAppSettings(context.rustContext.settingsActor), + true + ) + + sendFinalResultToParent(self, result) + sendParent(self, { type: 'clear draft entities' }) + self.send({ type: 'done' }) + } catch (error) { + toastSketchSolveError(error) + } +} + +function getClosestLineSelection( + mousePoint: Coords2d, + context: DimensionToolContext +): LineSelection | null { + const objects = getObjects(context) + const currentSketchObjects = getCurrentSketchObjectsById( + objects, + context.sketchId + ) + const closestLine = findClosestApiObjects( + mousePoint, + currentSketchObjects, + context.sceneInfra + ).find(({ apiObject }) => isLineSegment(apiObject)) + + if (!closestLine) { + return null + } + + return { + id: closestLine.apiObject.id, + clickPoint: mousePoint, + } +} + +function addDimensionListener({ + context, + self, +}: { + context: DimensionToolContext + self: { + _parent?: { send: (event: unknown) => void } + send: (event: DimensionToolEvent) => void + } +}) { + const runtime = createRuntime() + + context.sceneInfra.setCallbacks({ + onClick: (args) => { + if (!args || args.mouseEvent.which !== 1) { + return + } + + const twoD = args.intersectionPoint?.twoD + if (!twoD) { + return + } + + const mousePoint: Coords2d = [twoD.x, twoD.y] + if (runtime.angleContext) { + void commitDraftAngleConstraint(runtime, context, self, mousePoint) + return + } + + const lineSelection = getClosestLineSelection(mousePoint, context) + if (!lineSelection) { + return + } + + if (!runtime.firstSelection) { + runtime.firstSelection = lineSelection + sendParent(self, { + type: 'update selected ids', + data: { + selectedIds: [lineSelection.id], + replaceExistingSelection: true, + }, + }) + return + } + + if (lineSelection.id === runtime.firstSelection.id) { + return + } + + const angleContext = getDimensionAngleContext( + runtime.firstSelection, + lineSelection, + getObjects(context) + ) + if (!angleContext) { + return + } + + runtime.angleContext = angleContext + sendParent(self, { + type: 'update selected ids', + data: { + selectedIds: [runtime.firstSelection.id, lineSelection.id], + replaceExistingSelection: true, + }, + }) + requestDraftPreview(runtime, context, self, mousePoint) + }, + onMove: (args) => { + const twoD = args?.intersectionPoint?.twoD + if (!twoD) { + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: null }, + }) + return + } + + const mousePoint: Coords2d = [twoD.x, twoD.y] + if (runtime.angleContext) { + requestDraftPreview(runtime, context, self, mousePoint) + return + } + + const lineSelection = getClosestLineSelection(mousePoint, context) + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: lineSelection?.id ?? null }, + }) + }, + }) +} + +function removeDimensionListener({ + context, +}: { context: DimensionToolContext }) { + context.sceneInfra.setCallbacks({ + onClick: () => {}, + onMove: () => {}, + }) +} + +function deleteDraftEntities(self: { + _parent?: { send: (event: unknown) => void } +}) { + sendParent(self, { type: 'delete draft entities' }) +} export const machine = setup({ types: { - context: {}, + context: {} as DimensionToolContext, events: {} as DimensionToolEvent, - input: {} as { - sceneInfra: SceneInfra - rustContext: RustContext - kclManager: KclManager - sketchId: number - sceneGraphDelta?: SceneGraphDelta - }, + input: {} as DimensionToolInput, }, actions: { - 'add point listener': () => { - console.log('tool successfully equipped') - // Add your action code here - // ... - }, - 'show draft geometry': () => { - // Add your action code here - // ... - }, - 'remove point listener': () => { - // Add your action code here - // ... - }, + 'add dimension listener': addDimensionListener, + 'remove dimension listener': removeDimensionListener, + 'delete draft entities': ({ self }) => deleteDraftEntities(self), 'toast sketch solve error': ({ event }) => { toastSketchSolveError(event) }, }, - actors: { - askUserForDimensionValues: createMachine({ - /* ... */ - }), - }, }).createMachine({ - /** @xstate-layout N4IgpgJg5mDOIC5QBECWBbMA7WqD2WABAC554A2AxAK5ZgCO1qADgNoAMAuoqM3rsXxYeIAB6J2AGhABPCQF950tJhxCSZcgDoAhgHcdqQViiEAZqgBOsYoT6osxSjogQ7eB8Q7ckIPgKERcQQANgAWMK0AZgB2AFYYgE4ADhD2AEYQqIzpOQQo9PStGOT00rCQxMqAJijkuMVlDGxcAg0KXQMjQlgwAGMCN3tHZ1d3T28RfyNA32DwyNiElLTM7PTcxDC45K1qkLKQ5OqYqLj09iiwxpAVFvVSDoBhAgtLdAdTCGa1AlhKCAEMBaBwANzwAGtgXdfkRHtoXlg3h8TIRvqpWjgEGC8H0dIICN5Jr5pgThHNEHF2DE9ok4md9tUIuFkmFNghkjFqtFUiztmV9jcYZj2gjXlYUV8fpj-mBLJY8JYtMxyPizIr0FphQ9NFpEcjPmjpUJYNisOC8WSiVwpvwZgQglt2OwtCF6TFnYkomd0tU4uzStyyhF0lFEtVEuxqqzFEoQFg8BA4CJtW14baAg6KQgALRhZLsnOhorpL0xLKJeLh-NC41p3X6QzGUxvGzjRwZ+3k0DBKIHLThj0FCJxMIxMKxdm1bkxX1pEpxJnjhpx1NwhtdWy9AZYIYeDsku1kx35EI0kfsKkT9Ie8MhdkRGnHN3bdiRirR66ruvr57i96Gui9x-J2x7Zt6NJemEzp+icfr3rIiAHJEYTVDeo6ltUfqJIktYYjqHS0AwTDMMwnygbMPYSAGZwDr6VLjuElaLrG8hAA */ - context: {}, + context: ({ input }): DimensionToolContext => ({ + sceneInfra: input.sceneInfra, + rustContext: input.rustContext, + kclManager: input.kclManager, + sketchId: input.sketchId, + initialObjects: + input.initialObjects ?? input.sceneGraphDelta?.new_graph.objects ?? [], + }), id: 'Dimension tool', - initial: 'awaiting first point', + initial: 'selecting lines', on: { unequip: { target: '#Dimension tool.unequipping', - description: - "can be requested from the outside, but we want this tool to have the final say on when it's done.", + actions: 'delete draft entities', }, escape: { target: '#Dimension tool.unequipping', - description: 'ESC unequips the tool', + actions: 'delete draft entities', }, }, - description: - 'Creates dimension constraints based on two points from the user.', + description: 'Creates dimension constraints from sketch selections.', states: { - 'awaiting first point': { + 'selecting lines': { + entry: 'add dimension listener', on: { - 'add point': { - target: 'await second point', - }, - }, - entry: 'add point listener', - }, - 'await second point': { - on: { - 'add point': { - target: 'Confirming dimensions', - }, - }, - entry: 'show draft geometry', - }, - 'Confirming dimensions': { - invoke: { - input: {}, - onDone: { - target: 'unequipping', - }, - onError: { + done: { target: 'unequipping', - actions: 'toast sketch solve error', }, - src: 'askUserForDimensionValues', }, - description: - 'Show the user form fields for dimension values, allowing them to input values directly. This will add dimension-type constraints.', + exit: 'remove dimension listener', }, unequipping: { type: 'final', - entry: 'remove point listener', description: 'Any teardown logic should go here.', }, }, From 5afc61f1334b10fc140df718fe6406339b8208a0 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 4 Jun 2026 16:35:30 +0200 Subject: [PATCH 09/78] make dimension tool active during equipping --- src/lib/toolbar.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/lib/toolbar.ts b/src/lib/toolbar.ts index efdcd3c1a39..2efb5facd83 100644 --- a/src/lib/toolbar.ts +++ b/src/lib/toolbar.ts @@ -2357,11 +2357,15 @@ export function buildToolbarConfig( { id: 'Dimension', command: TOOLBAR_COMMAND_IDS.sketchSolve.dimension, - onClick: ({ modelingSend, keepSelection }) => - modelingSend({ - type: 'Dimension', - keepSelection, - }), + onClick: ({ modelingSend, isActive, keepSelection }) => + isActive + ? modelingSend({ + type: 'unequip tool', + }) + : modelingSend({ + type: 'Dimension', + keepSelection, + }), icon: 'dimension', status: 'available', title: 'Dimension', @@ -2369,7 +2373,9 @@ export function buildToolbarConfig( 'Constrain distance between points, length of lines, or radius of arcs.', extraInfo: constraintsExtraInfo, links: [], - isActive: (state) => false, + isActive: (state) => + state.matches('sketchSolveMode') && + state.context.sketchSolveToolName === 'dimensionTool', }, { id: 'HorizontalDistance', From ad21d1faa51189d4ce9193d8ec86d7aba1c65f9e Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 9 Jun 2026 17:28:32 +0200 Subject: [PATCH 10/78] WIP: 11766 Use existing line endpoints for PointsAtAngle lowering (#11984) --- rust/kcl-lib/src/execution/exec_ast.rs | 263 ++++++++++++++++--------- 1 file changed, 171 insertions(+), 92 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 7746a09e1b1..7396b3bb883 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -251,20 +251,12 @@ fn vec2_cross(a: [f64; 2], b: [f64; 2]) -> f64 { a[0] * b[1] - a[1] * b[0] } -fn vec2_len(a: [f64; 2]) -> f64 { - libm::hypot(a[0], a[1]) +fn vec2_dot(a: [f64; 2], b: [f64; 2]) -> f64 { + a[0] * b[0] + a[1] * b[1] } -fn vec2_normalized(a: [f64; 2], range: SourceRange, description: &str) -> Result<[f64; 2], KclError> { - let len = vec2_len(a); - if len <= 1e-9 { - return Err(KclError::new_semantic(KclErrorDetails::new( - format!("angle() {description} must not be degenerate"), - vec![range], - ))); - } - - Ok([a[0] / len, a[1] / len]) +fn vec2_len(a: [f64; 2]) -> f64 { + libm::hypot(a[0], a[1]) } fn intersection_of_initial_lines( @@ -349,50 +341,103 @@ fn angle_sector_rays(sector: AngleSector, is_reflex: bool) -> [AngleSectorRay; 2 if is_reflex { [rays[1], rays[0]] } else { rays } } -fn angle_ray_initial( +fn normalize_radians(angle: f64) -> f64 { + let normalized = angle % std::f64::consts::TAU; + if normalized < 0.0 { + normalized + std::f64::consts::TAU + } else { + normalized + } +} + +fn line_endpoint_datum( + line: &ConstrainableLine2d, + endpoint_index: usize, + range: SourceRange, +) -> Result { + let Some(endpoint) = line.vars.get(endpoint_index) else { + return Err(internal_err("Invalid angle line endpoint index", range)); + }; + + Ok(DatumPoint::new_xy( + endpoint.x.to_constraint_id(range)?, + endpoint.y.to_constraint_id(range)?, + )) +} + +fn representative_angle_endpoint( + line: &ConstrainableLine2d, + initial_line: ([f64; 2], [f64; 2]), vertex: [f64; 2], - line: ([f64; 2], [f64; 2]), - ray: AngleRayDirection, - distance: f64, range: SourceRange, -) -> Result<[f64; 2], KclError> { - let direction = vec2_normalized(vec2_sub(line.1, line.0), range, "line")?; - let sign = match ray { - AngleRayDirection::Forward => 1.0, - AngleRayDirection::Reverse => -1.0, +) -> Result<(DatumPoint, AngleRayDirection), KclError> { + let start_delta = vec2_sub(initial_line.0, vertex); + let end_delta = vec2_sub(initial_line.1, vertex); + let endpoint_index = if vec2_len(end_delta) >= vec2_len(start_delta) { + 1 + } else { + 0 + }; + let endpoint_delta = if endpoint_index == 1 { end_delta } else { start_delta }; + if vec2_len(endpoint_delta) <= 1e-9 { + return Err(KclError::new_semantic(KclErrorDetails::new( + "angle(lines = ..., sector = ...) requires each line to have an endpoint away from the intersection" + .to_owned(), + vec![range], + ))); + } + + let line_direction = vec2_sub(initial_line.1, initial_line.0); + let direction = if vec2_dot(endpoint_delta, line_direction) >= 0.0 { + AngleRayDirection::Forward + } else { + AngleRayDirection::Reverse + }; + + Ok((line_endpoint_datum(line, endpoint_index, range)?, direction)) +} + +fn remap_angle_for_representative_rays( + requested_rays: [AngleSectorRay; 2], + representative_directions: [AngleRayDirection; 2], + desired_angle: ezpz::datatypes::Angle, +) -> ezpz::datatypes::Angle { + let mut requested_directions = representative_directions; + for ray in requested_rays { + requested_directions[ray.line_index] = ray.direction; + } + + let sign_offset = if (requested_directions[0] != representative_directions[0]) + ^ (requested_directions[1] != representative_directions[1]) + { + std::f64::consts::PI + } else { + 0.0 + }; + + let desired = desired_angle.to_radians(); + let representative_angle = if requested_rays[0].line_index == 0 { + desired - sign_offset + } else { + -desired - sign_offset }; - Ok(vec2_add(vertex, vec2_scale(direction, sign * distance))) + + ezpz::datatypes::Angle::from_radians(normalize_radians(representative_angle)) } -fn push_points_at_angle_for_line_rays( +fn push_points_at_angle_for_lines( sketch_block_state: &mut SketchBlockState, sketch_var_ty: NumericType, line0: &ConstrainableLine2d, line1: &ConstrainableLine2d, - ray_line_indices: [usize; 2], initial_vertex: [f64; 2], - initial_ray_points: [[f64; 2]; 2], - ray_distance: f64, + representative_points: [DatumPoint; 2], angle_kind: ezpz::datatypes::AngleKind, range: SourceRange, ) -> Result<(), KclError> { let solver_line0 = datum_line_from_constrainable(line0, range)?; let solver_line1 = datum_line_from_constrainable(line1, range)?; - let solver_ray_lines = [ - match ray_line_indices[0] { - 0 => solver_line0, - 1 => solver_line1, - _ => return Err(internal_err("Invalid angle sector line index", range)), - }, - match ray_line_indices[1] { - 0 => solver_line0, - 1 => solver_line1, - _ => return Err(internal_err("Invalid angle sector line index", range)), - }, - ]; let vertex = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_vertex, range)?; - let ray0 = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_ray_points[0], range)?; - let ray1 = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_ray_points[1], range)?; sketch_block_state .solver_constraints @@ -400,21 +445,12 @@ fn push_points_at_angle_for_line_rays( sketch_block_state .solver_constraints .push(Constraint::PointLineDistance(vertex, solver_line1, 0.0)); - sketch_block_state - .solver_constraints - .push(Constraint::PointLineDistance(ray0, solver_ray_lines[0], 0.0)); - sketch_block_state - .solver_constraints - .push(Constraint::PointLineDistance(ray1, solver_ray_lines[1], 0.0)); - sketch_block_state - .solver_constraints - .push(Constraint::Distance(vertex, ray0, ray_distance)); - sketch_block_state - .solver_constraints - .push(Constraint::Distance(vertex, ray1, ray_distance)); - sketch_block_state - .solver_constraints - .push(Constraint::PointsAtAngle(vertex, ray0, ray1, angle_kind)); + sketch_block_state.solver_constraints.push(Constraint::PointsAtAngle( + vertex, + representative_points[0], + representative_points[1], + angle_kind, + )); Ok(()) } @@ -3946,33 +3982,18 @@ impl Node { )?; let initial_vertex = intersection_of_initial_lines(initial_line0, initial_line1, range)?; - let line0_length = vec2_len(vec2_sub(initial_line0.1, initial_line0.0)); - let line1_length = vec2_len(vec2_sub(initial_line1.1, initial_line1.0)); - let ray_distance = (line0_length.min(line1_length) * 0.25).max(1.0); + let (line0_representative, line0_direction) = + representative_angle_endpoint(line0, initial_line0, initial_vertex, range)?; + let (line1_representative, line1_direction) = + representative_angle_endpoint(line1, initial_line1, initial_vertex, range)?; let sector_rays = angle_sector_rays(sector, reflex); - let initial_lines = [initial_line0, initial_line1]; - Some(( - initial_vertex, - [ - angle_ray_initial( - initial_vertex, - initial_lines[sector_rays[0].line_index], - sector_rays[0].direction, - ray_distance, - range, - )?, - angle_ray_initial( - initial_vertex, - initial_lines[sector_rays[1].line_index], - sector_rays[1].direction, - ray_distance, - range, - )?, - ], - [sector_rays[0].line_index, sector_rays[1].line_index], - ray_distance, - ezpz::datatypes::AngleKind::Other(desired_angle), - )) + let angle_kind = + ezpz::datatypes::AngleKind::Other(remap_angle_for_representative_rays( + sector_rays, + [line0_direction, line1_direction], + desired_angle, + )); + Some((initial_vertex, [line0_representative, line1_representative], angle_kind)) } }; let sketch_var_ty = solver_numeric_type(exec_state); @@ -3993,22 +4014,14 @@ impl Node { } ( AngleConstraintMode::PointsAtAngle { .. }, - Some(( - initial_vertex, - initial_ray_points, - ray_line_indices, - ray_distance, - angle_kind, - )), - ) => push_points_at_angle_for_line_rays( + Some((initial_vertex, representative_points, angle_kind)), + ) => push_points_at_angle_for_lines( sketch_block_state, sketch_var_ty, line0, line1, - ray_line_indices, initial_vertex, - initial_ray_points, - ray_distance, + representative_points, angle_kind, range, )?, @@ -6045,6 +6058,72 @@ mod test { use crate::execution::ContextType; use crate::execution::parse_execute; + fn assert_angle_degrees(actual: ezpz::datatypes::Angle, expected: f64) { + assert!( + (actual.to_degrees() - expected).abs() < 1e-9, + "expected {expected}deg, got {}deg", + actual.to_degrees() + ); + } + + #[test] + fn remaps_sector_angles_to_existing_representative_endpoint_rays() { + let representative_directions = [AngleRayDirection::Forward, AngleRayDirection::Forward]; + + assert_angle_degrees( + remap_angle_for_representative_rays( + angle_sector_rays(AngleSector::One, false), + representative_directions, + ezpz::datatypes::Angle::from_degrees(60.0), + ), + 60.0, + ); + assert_angle_degrees( + remap_angle_for_representative_rays( + angle_sector_rays(AngleSector::Two, false), + representative_directions, + ezpz::datatypes::Angle::from_degrees(120.0), + ), + 60.0, + ); + assert_angle_degrees( + remap_angle_for_representative_rays( + angle_sector_rays(AngleSector::Three, false), + representative_directions, + ezpz::datatypes::Angle::from_degrees(60.0), + ), + 60.0, + ); + assert_angle_degrees( + remap_angle_for_representative_rays( + angle_sector_rays(AngleSector::Four, false), + representative_directions, + ezpz::datatypes::Angle::from_degrees(120.0), + ), + 60.0, + ); + assert_angle_degrees( + remap_angle_for_representative_rays( + angle_sector_rays(AngleSector::One, true), + representative_directions, + ezpz::datatypes::Angle::from_degrees(300.0), + ), + 60.0, + ); + } + + #[test] + fn remaps_sector_angles_when_representative_endpoint_is_on_reverse_ray() { + assert_angle_degrees( + remap_angle_for_representative_rays( + angle_sector_rays(AngleSector::One, false), + [AngleRayDirection::Forward, AngleRayDirection::Reverse], + ezpz::datatypes::Angle::from_degrees(60.0), + ), + 240.0, + ); + } + #[tokio::test(flavor = "multi_thread")] async fn angle_unlabeled_keeps_legacy_lines_at_angle() { parse_execute( From 186406785cdcbf0d81d181653d5205edfbf06032 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 11 Jun 2026 11:10:13 +0200 Subject: [PATCH 11/78] clippy --- rust/kcl-lib/src/execution/exec_ast.rs | 53 ++++++++++++++------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 7396b3bb883..de234026fcd 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -425,19 +425,22 @@ fn remap_angle_for_representative_rays( ezpz::datatypes::Angle::from_radians(normalize_radians(representative_angle)) } -fn push_points_at_angle_for_lines( - sketch_block_state: &mut SketchBlockState, - sketch_var_ty: NumericType, - line0: &ConstrainableLine2d, - line1: &ConstrainableLine2d, +struct PointsAtAngleLineData { initial_vertex: [f64; 2], representative_points: [DatumPoint; 2], angle_kind: ezpz::datatypes::AngleKind, +} + +fn push_points_at_angle_for_lines( + sketch_block_state: &mut SketchBlockState, + sketch_var_ty: NumericType, + lines: [&ConstrainableLine2d; 2], + data: PointsAtAngleLineData, range: SourceRange, ) -> Result<(), KclError> { - let solver_line0 = datum_line_from_constrainable(line0, range)?; - let solver_line1 = datum_line_from_constrainable(line1, range)?; - let vertex = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, initial_vertex, range)?; + let solver_line0 = datum_line_from_constrainable(lines[0], range)?; + let solver_line1 = datum_line_from_constrainable(lines[1], range)?; + let vertex = push_hidden_sketch_point(sketch_block_state, sketch_var_ty, data.initial_vertex, range)?; sketch_block_state .solver_constraints @@ -447,9 +450,9 @@ fn push_points_at_angle_for_lines( .push(Constraint::PointLineDistance(vertex, solver_line1, 0.0)); sketch_block_state.solver_constraints.push(Constraint::PointsAtAngle( vertex, - representative_points[0], - representative_points[1], - angle_kind, + data.representative_points[0], + data.representative_points[1], + data.angle_kind, )); Ok(()) @@ -3993,7 +3996,11 @@ impl Node { [line0_direction, line1_direction], desired_angle, )); - Some((initial_vertex, [line0_representative, line1_representative], angle_kind)) + Some(PointsAtAngleLineData { + initial_vertex, + representative_points: [line0_representative, line1_representative], + angle_kind, + }) } }; let sketch_var_ty = solver_numeric_type(exec_state); @@ -4012,19 +4019,15 @@ impl Node { ezpz::datatypes::AngleKind::Other(desired_angle), )); } - ( - AngleConstraintMode::PointsAtAngle { .. }, - Some((initial_vertex, representative_points, angle_kind)), - ) => push_points_at_angle_for_lines( - sketch_block_state, - sketch_var_ty, - line0, - line1, - initial_vertex, - representative_points, - angle_kind, - range, - )?, + (AngleConstraintMode::PointsAtAngle { .. }, Some(points_at_angle_data)) => { + push_points_at_angle_for_lines( + sketch_block_state, + sketch_var_ty, + [line0, line1], + points_at_angle_data, + range, + )? + } _ => { let message = "Invalid angle constraint lowering state".to_owned(); debug_assert!(false, "{}", &message); From 3776850c880e0351e48faed2cd4c3dc7728fedb7 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 11 Jun 2026 12:30:57 +0200 Subject: [PATCH 12/78] when equipping dimension tool with line selection, go into sector selection mode immediately --- .../sketchSolve/sketchSolveDiagram.ts | 33 ++++--- src/machines/sketchSolve/sketchSolveImpl.ts | 48 +++++++++- .../sketchSolve/sketchSolveSelection.ts | 3 + .../sketchSolve/tools/dimensionTool.spec.ts | 76 ++++++++++++++- .../sketchSolve/tools/dimensionTool.ts | 95 ++++++++++++++++++- .../tools/moveTool/moveTool.spec.ts | 6 ++ .../sketchSolve/tools/moveTool/moveTool.ts | 12 +++ 7 files changed, 253 insertions(+), 20 deletions(-) diff --git a/src/machines/sketchSolve/sketchSolveDiagram.ts b/src/machines/sketchSolve/sketchSolveDiagram.ts index 8ec93246dc4..008c09f9e4e 100644 --- a/src/machines/sketchSolve/sketchSolveDiagram.ts +++ b/src/machines/sketchSolve/sketchSolveDiagram.ts @@ -18,7 +18,6 @@ import type { OffsetPlane, } from '@src/machines/modelingSharedTypes' import { - buildAngleConstraintInput, buildCircularSizeDimensionConstraintInput, isArcSegment, isCircleSegment, @@ -457,6 +456,7 @@ export const sketchSolveMachine = setup({ }), 'clear selection': assign({ selectedIds: [], + selectionClickPoints: {}, duringAreaSelectIds: [], }), 'toggle non-visual constraints': assign(({ context }) => ({ @@ -507,6 +507,7 @@ export const sketchSolveMachine = setup({ return { sketchSolveToolName: null, selectedIds: [], + selectionClickPoints: {}, duringAreaSelectIds: [], hoveredId: null, constraintHoverPopups: [], @@ -616,22 +617,12 @@ export const sketchSolveMachine = setup({ isLineSegment(firstObject) && isLineSegment(secondObject) ) { - const angleConstraint = buildAngleConstraintInput( - firstObject, - secondObject, - objects - ) - if (angleConstraint) { - const result = await context.rustContext.addConstraint( - 0, - context.sketchId, - angleConstraint, - jsAppSettings(context.kclManager.systemDeps.settings), - true - ) - sendToolbarConstraintOutcome(self, result, keepSelection) - return - } + sendToActorIfActive(self, { + type: 'equip tool', + data: { tool: 'dimensionTool' }, + keepSelection, + }) + return } else if ( isPointSegment(firstObject) && isPointSegment(secondObject) @@ -1048,6 +1039,14 @@ export const sketchSolveMachine = setup({ }, actions: 'apply current selection with equipped constraint tool', }, + { + guard: ({ event }) => { + assertEvent(event, 'equip tool') + return event.data.tool === 'dimensionTool' + }, + target: 'using tool', + actions: 'store pending tool', + }, { guard: ({ event }) => { assertEvent(event, 'equip tool') diff --git a/src/machines/sketchSolve/sketchSolveImpl.ts b/src/machines/sketchSolve/sketchSolveImpl.ts index 8fcdef2f7fe..4c9da94c6da 100644 --- a/src/machines/sketchSolve/sketchSolveImpl.ts +++ b/src/machines/sketchSolve/sketchSolveImpl.ts @@ -24,6 +24,7 @@ import { } from '@src/machines/sketchSolve/segments' import { ORIGIN_TARGET, + type SelectionClickPoints, type SketchSolveSelectionId, getObjectSelectionIds, isObjectSelectionId, @@ -91,6 +92,7 @@ export { getObjectSelectionIds, isObjectSelectionId, ORIGIN_TARGET, + type SelectionClickPoints, type SketchSolveSelectionId, type SketchSpecialTarget, } from '@src/machines/sketchSolve/sketchSolveSelection' @@ -132,6 +134,7 @@ export type SketchSolveMachineEvent = selectedIds?: Array duringAreaSelectIds?: Array replaceExistingSelection?: boolean + selectionClickPoints?: SelectionClickPoints } } | { @@ -227,6 +230,7 @@ export type SketchSolveContext = { childTool?: ToolActorRef pendingToolName?: EquipTool selectedIds: Array + selectionClickPoints: SelectionClickPoints duringAreaSelectIds: Array hoveredId: SketchSolveSelectionId | null constraintHoverPopups: ConstraintHoverPopup[] @@ -776,6 +780,25 @@ export function cleanupSketchSolveGroup(sceneInfra: SceneInfra) { disposeGroupChildren(sketchSegments) } +function getSelectionClickPointsForIds( + selectedIds: readonly SketchSolveSelectionId[], + selectionClickPoints: SelectionClickPoints +): SelectionClickPoints { + const nextSelectionClickPoints: SelectionClickPoints = {} + for (const selectedId of selectedIds) { + if (typeof selectedId !== 'number') { + continue + } + + const clickPoint = selectionClickPoints[selectedId] + if (clickPoint) { + nextSelectionClickPoints[selectedId] = clickPoint + } + } + + return nextSelectionClickPoints +} + export function updateSelectedIds({ event, context }: SolveAssignArgs) { assertEvent(event, 'update selected ids') @@ -788,11 +811,21 @@ export function updateSelectedIds({ event, context }: SolveAssignArgs) { // Handle regular selectedIds update (for click selection, etc.) if (event.data.selectedIds !== undefined) { + const selectionClickPoints = { + ...context.selectionClickPoints, + ...(event.data.selectionClickPoints ?? {}), + } + // If empty array is provided, clear the selection if (event.data.selectedIds.length === 0) { updates.selectedIds = [] + updates.selectionClickPoints = {} } else if (event.data.replaceExistingSelection) { updates.selectedIds = event.data.selectedIds + updates.selectionClickPoints = getSelectionClickPointsForIds( + event.data.selectedIds, + selectionClickPoints + ) } else { const first = event.data.selectedIds[0] if ( @@ -801,13 +834,22 @@ export function updateSelectedIds({ event, context }: SolveAssignArgs) { context.selectedIds.includes(first) ) { // If only one ID is selected and it's already in the selection, remove only it from the selection - updates.selectedIds = context.selectedIds.filter((id) => id !== first) + const nextSelectedIds = context.selectedIds.filter((id) => id !== first) + updates.selectedIds = nextSelectedIds + updates.selectionClickPoints = getSelectionClickPointsForIds( + nextSelectedIds, + context.selectionClickPoints + ) } else { // Merge new IDs with existing selection const result = Array.from( new Set([...context.selectedIds, ...event.data.selectedIds]) ) updates.selectedIds = result + updates.selectionClickPoints = getSelectionClickPointsForIds( + result, + selectionClickPoints + ) } } } @@ -825,6 +867,7 @@ export function updateSelectedIdsFromCodeSelection({ if (!objects) { return { selectedIds: [], + selectionClickPoints: {}, duringAreaSelectIds: [], } } @@ -834,6 +877,7 @@ export function updateSelectedIdsFromCodeSelection({ getCurrentSketchObjectsById(objects, context.sketchId), event.data.ranges ), + selectionClickPoints: {}, duringAreaSelectIds: [], } } @@ -1557,6 +1601,7 @@ export function spawnTool( kclManager: context.kclManager, sketchId: context.sketchId, initialSelectionIds: context.selectedIds, + initialSelectionClickPoints: context.selectionClickPoints, initialObjects: context.sketchExecOutcome?.sceneGraphDelta.new_graph.objects || [], toolVariant: toolVariants[nameOfToolToSpawn], @@ -1597,6 +1642,7 @@ export type ToolInput = { kclManager: KclManager sketchId: number initialSelectionIds?: SketchSolveSelectionId[] + initialSelectionClickPoints?: SelectionClickPoints initialObjects?: ApiObject[] toolVariant?: string // eg. 'corner' | 'center' | 'angled' for rectTool } diff --git a/src/machines/sketchSolve/sketchSolveSelection.ts b/src/machines/sketchSolve/sketchSolveSelection.ts index 65615a2910b..ca26a1fd9f3 100644 --- a/src/machines/sketchSolve/sketchSolveSelection.ts +++ b/src/machines/sketchSolve/sketchSolveSelection.ts @@ -1,7 +1,10 @@ +import type { Coords2d } from '@src/lang/util' + export const ORIGIN_TARGET = 'origin' export type SketchSpecialTarget = typeof ORIGIN_TARGET export type SketchSolveSelectionId = number | SketchSpecialTarget +export type SelectionClickPoints = Partial> export function isObjectSelectionId( id: SketchSolveSelectionId | null | undefined diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index 58513b5e1d7..bf892603ca7 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -3,6 +3,10 @@ import type { ApiObject, } from '@rust/kcl-lib/bindings/FrontendApi' import type { Coords2d } from '@src/lang/util' +import type { + SelectionClickPoints, + SketchSolveSelectionId, +} from '@src/machines/sketchSolve/sketchSolveSelection' import { type DimensionAngleDraftContext, buildDimensionAngleConstraint, @@ -72,7 +76,13 @@ function createMouseEvent(point: Coords2d) { } } -function createParentHarness(objects: ApiObject[]) { +function createParentHarness( + objects: ApiObject[], + options: { + initialSelectionIds?: SketchSolveSelectionId[] + initialSelectionClickPoints?: SelectionClickPoints + } = {} +) { const sceneInfra = createMockSceneInfra() const rustContext = createMockRustContext() const kclManager = createMockKclManager() @@ -154,6 +164,8 @@ function createParentHarness(objects: ApiObject[]) { rustContext, kclManager, sketchId: 0, + initialSelectionIds: options.initialSelectionIds, + initialSelectionClickPoints: options.initialSelectionClickPoints, initialObjects: sceneGraphDelta.new_graph.objects, }, }, @@ -306,4 +318,66 @@ describe('dimensionTool', () => { }, }) }) + + it('starts sector selection when initialized with two selected lines', async () => { + const sketch = createSketchApiObject({ id: 0 }) + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const line0End = createPointApiObject({ id: 2, x: 10, y: 0 }) + const line1End = createPointApiObject({ + id: 3, + x: 5, + y: 8.660254037844386, + }) + const line0 = createLineApiObject({ id: 10, start: 1, end: 2 }) + const line1 = createLineApiObject({ id: 11, start: 1, end: 3 }) + const objects = [sketch, origin, line0End, line1End, line0, line1] + const { actor, sceneInfra, rustContext, events } = createParentHarness( + objects, + { + initialSelectionIds: [10, 11], + } + ) + const callbacks = (sceneInfra.setCallbacks as any).mock.calls[0][0] + + callbacks.onMove(createMouseEvent([-1, -0.6])) + + await waitFor( + actor, + () => (rustContext.addConstraint as any).mock.calls.length === 1 + ) + + expect((rustContext.addConstraint as any).mock.calls[0][2]).toEqual({ + type: 'Angle', + lines: [10, 11], + angle: { value: 300, units: 'Deg' }, + sector: 1, + reflex: true, + labelPosition: { + x: { value: -1, units: 'Mm' }, + y: { value: -0.6, units: 'Mm' }, + }, + source: { + expr: '300deg', + is_literal: true, + }, + }) + expect(events).toContainEqual({ + type: 'update selected ids', + data: { + selectedIds: [10, 11], + replaceExistingSelection: true, + selectionClickPoints: { + 10: [10, 0], + 11: [5, 8.660254037844386], + }, + }, + }) + expect(events).toContainEqual({ + type: 'set draft entities', + data: { + segmentIds: [], + constraintIds: [30], + }, + }) + }) }) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 2469d4282c5..1f9a7da5e0b 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -28,7 +28,10 @@ import { import { findClosestApiObjects } from '@src/machines/sketchSolve/interaction/interactionHelpers' import { getCurrentSketchObjectsById } from '@src/machines/sketchSolve/sceneGraphUtils' import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' -import type { SketchSolveSelectionId } from '@src/machines/sketchSolve/sketchSolveSelection' +import type { + SelectionClickPoints, + SketchSolveSelectionId, +} from '@src/machines/sketchSolve/sketchSolveSelection' import type { BaseToolEvent } from '@src/machines/sketchSolve/tools/sharedToolTypes' import { setup } from 'xstate' @@ -37,6 +40,8 @@ type DimensionToolContext = { rustContext: RustContext kclManager: KclManager sketchId: number + initialSelectionIds: SketchSolveSelectionId[] + initialSelectionClickPoints: SelectionClickPoints initialObjects: ApiObject[] } @@ -46,6 +51,7 @@ type DimensionToolInput = { kclManager: KclManager sketchId: number initialSelectionIds?: SketchSolveSelectionId[] + initialSelectionClickPoints?: SelectionClickPoints initialObjects?: ApiObject[] sceneGraphDelta?: SceneGraphDelta } @@ -63,6 +69,7 @@ type ParentSketchSolveEvent = selectedIds?: SketchSolveSelectionId[] duringAreaSelectIds?: number[] replaceExistingSelection?: boolean + selectionClickPoints?: SelectionClickPoints } } | { @@ -275,6 +282,55 @@ function getDimensionAngleContext( return angleContext } +function getFarthestLinePointFromVertex( + linePoints: readonly [Coords2d, Coords2d], + vertex: Coords2d +): Coords2d { + return length2d(subVec(linePoints[1], vertex)) >= + length2d(subVec(linePoints[0], vertex)) + ? linePoints[1] + : linePoints[0] +} + +function getInitialAngleLineSelections( + selectionIds: readonly SketchSolveSelectionId[], + selectionClickPoints: SelectionClickPoints, + objects: ApiObject[] +): [LineSelection, LineSelection] | null { + const lineIds = selectionIds.filter( + (id): id is number => typeof id === 'number' + ) + if (lineIds.length !== 2) { + return null + } + + const line0Points = getLinePoints(objects[lineIds[0]], objects) + const line1Points = getLinePoints(objects[lineIds[1]], objects) + if (!line0Points || !line1Points) { + return null + } + + const vertex = getLineIntersection(line0Points, line1Points) + if (!vertex) { + return null + } + + return [ + { + id: lineIds[0], + clickPoint: + selectionClickPoints[lineIds[0]] ?? + getFarthestLinePointFromVertex(line0Points, vertex), + }, + { + id: lineIds[1], + clickPoint: + selectionClickPoints[lineIds[1]] ?? + getFarthestLinePointFromVertex(line1Points, vertex), + }, + ] +} + function normalizeAngle(angle: number) { return ((angle % TAU) + TAU) % TAU } @@ -809,6 +865,34 @@ function addDimensionListener({ } }) { const runtime = createRuntime() + const initialLineSelections = getInitialAngleLineSelections( + context.initialSelectionIds, + context.initialSelectionClickPoints, + getObjects(context) + ) + if (initialLineSelections) { + const [firstSelection, secondSelection] = initialLineSelections + const angleContext = getDimensionAngleContext( + firstSelection, + secondSelection, + getObjects(context) + ) + if (angleContext) { + runtime.firstSelection = firstSelection + runtime.angleContext = angleContext + sendParent(self, { + type: 'update selected ids', + data: { + selectedIds: [firstSelection.id, secondSelection.id], + replaceExistingSelection: true, + selectionClickPoints: { + [firstSelection.id]: firstSelection.clickPoint, + [secondSelection.id]: secondSelection.clickPoint, + }, + }, + }) + } + } context.sceneInfra.setCallbacks({ onClick: (args) => { @@ -839,6 +923,9 @@ function addDimensionListener({ data: { selectedIds: [lineSelection.id], replaceExistingSelection: true, + selectionClickPoints: { + [lineSelection.id]: lineSelection.clickPoint, + }, }, }) return @@ -863,6 +950,10 @@ function addDimensionListener({ data: { selectedIds: [runtime.firstSelection.id, lineSelection.id], replaceExistingSelection: true, + selectionClickPoints: { + [runtime.firstSelection.id]: runtime.firstSelection.clickPoint, + [lineSelection.id]: lineSelection.clickPoint, + }, }, }) requestDraftPreview(runtime, context, self, mousePoint) @@ -927,6 +1018,8 @@ export const machine = setup({ rustContext: input.rustContext, kclManager: input.kclManager, sketchId: input.sketchId, + initialSelectionIds: input.initialSelectionIds ?? [], + initialSelectionClickPoints: input.initialSelectionClickPoints ?? {}, initialObjects: input.initialObjects ?? input.sceneGraphDelta?.new_graph.objects ?? [], }), diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts index fad03d28c22..1e87388a286 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts @@ -3670,6 +3670,9 @@ describe('createOnClickCallback', () => { expect(onUpdateSelectedIds).toHaveBeenCalledWith({ selectedIds: [5], duringAreaSelectIds: [], + selectionClickPoints: { + 5: [20, 0], + }, }) }) @@ -3704,6 +3707,9 @@ describe('createOnClickCallback', () => { expect(onUpdateSelectedIds).toHaveBeenCalledWith({ selectedIds: [11], duringAreaSelectIds: [], + selectionClickPoints: { + 11: [5, 10], + }, }) }) diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.ts index 0f5941b3b30..ed8405c081b 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.ts @@ -34,6 +34,7 @@ import { isControlPointSplineSegment, isDiameterConstraint, isDistanceConstraint, + isLineSegment, isOwnedLineSegment, isPointSegment, isRadiusConstraint, @@ -53,6 +54,7 @@ import { getCurrentSketchObjectsById } from '@src/machines/sketchSolve/sceneGrap import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' import { ORIGIN_TARGET, + type SelectionClickPoints, type SketchSolveSelectionId, type SolveActionArgs, buildSegmentCtorFromObject, @@ -978,6 +980,7 @@ export function createOnClickCallback({ selectedIds: Array duringAreaSelectIds: Array replaceExistingSelection?: boolean + selectionClickPoints?: SelectionClickPoints }) => void onEditConstraint: (constraintId: number) => void }): (arg: { @@ -1026,10 +1029,18 @@ export function createOnClickCallback({ sceneInfra ) } + const selectionClickPoints = + closestSelection && + typeof closestSelection.selectionId === 'number' && + isLineSegment(selectedApiObject) && + mousePosition + ? { [closestSelection.selectionId]: mousePosition } + : undefined onUpdateSelectedIds({ selectedIds: closestSelection ? [closestSelection.selectionId] : [], duringAreaSelectIds: [], ...(shouldReplaceSelection ? { replaceExistingSelection: true } : {}), + ...(selectionClickPoints ? { selectionClickPoints } : {}), }) } } @@ -2393,6 +2404,7 @@ export function setUpOnDragAndSelectionClickCallbacks({ selectedIds: Array duringAreaSelectIds: Array replaceExistingSelection?: boolean + selectionClickPoints?: SelectionClickPoints }) => self.send({ type: 'update selected ids', data }), onEditConstraint: (constraintId: number) => { self.send({ From b1b0b2bb0372663f4de63a6272c84d9c8c0c5f11 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 11 Jun 2026 13:27:25 +0200 Subject: [PATCH 13/78] show toolbar popup when activating dimension tool with pre-existing line selection for angle constraint --- .../sketchSolve/tools/dimensionTool.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 1f9a7da5e0b..9dfca2f446e 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -33,6 +33,7 @@ import type { SketchSolveSelectionId, } from '@src/machines/sketchSolve/sketchSolveSelection' import type { BaseToolEvent } from '@src/machines/sketchSolve/tools/sharedToolTypes' +import toast from 'react-hot-toast' import { setup } from 'xstate' type DimensionToolContext = { @@ -153,6 +154,7 @@ type DraftRuntime = { const LINE_INTERSECTION_EPSILON = 1e-8 const SECTOR_EPSILON = 1e-9 +const ANGLE_SECTOR_PROMPT_TOAST_ID = 'dimension-tool-angle-sector-prompt' function getDefaultLengthUnit(kclManager: KclManager): NumericSuffix { return baseUnitToNumericSuffix( @@ -178,6 +180,21 @@ function createRuntime(): DraftRuntime { } } +function showAngleSectorPrompt() { + toast('Choose angle sector, then click to place the label.', { + id: ANGLE_SECTOR_PROMPT_TOAST_ID, + duration: Number.POSITIVE_INFINITY, + position: 'top-center', + style: { + marginTop: '68px', + }, + }) +} + +function dismissAngleSectorPrompt() { + toast.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) +} + function getObjects(context: DimensionToolContext) { return context.initialObjects } @@ -823,6 +840,7 @@ async function commitDraftAngleConstraint( sendFinalResultToParent(self, result) sendParent(self, { type: 'clear draft entities' }) + dismissAngleSectorPrompt() self.send({ type: 'done' }) } catch (error) { toastSketchSolveError(error) @@ -880,6 +898,7 @@ function addDimensionListener({ if (angleContext) { runtime.firstSelection = firstSelection runtime.angleContext = angleContext + showAngleSectorPrompt() sendParent(self, { type: 'update selected ids', data: { @@ -986,6 +1005,7 @@ function addDimensionListener({ function removeDimensionListener({ context, }: { context: DimensionToolContext }) { + dismissAngleSectorPrompt() context.sceneInfra.setCallbacks({ onClick: () => {}, onMove: () => {}, From be0749d602bea9b258f296b1faec5ca1bf65a0df Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 11 Jun 2026 14:28:38 +0200 Subject: [PATCH 14/78] update hover during angle constraint placement --- .../sketchSolve/tools/dimensionTool.spec.ts | 18 ++++++++++++++++++ .../sketchSolve/tools/dimensionTool.ts | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index bf892603ca7..79c1971e3df 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -317,6 +317,24 @@ describe('dimensionTool', () => { constraintIds: [30], }, }) + callbacks.onClick(createMouseEvent([4, 3])) + + await waitFor( + actor, + () => (rustContext.addConstraint as any).mock.calls.length === 2 + ) + + expect(events).toContainEqual({ + type: 'update selected ids', + data: { + selectedIds: [], + duringAreaSelectIds: [], + }, + }) + expect(events).toContainEqual({ + type: 'update hovered id', + data: { hoveredId: 31 }, + }) }) it('starts sector selection when initialized with two selected lines', async () => { diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 9dfca2f446e..d06ac4e8ff1 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -838,8 +838,17 @@ async function commitDraftAngleConstraint( true ) + const constraintId = getConstraintIdFromResult(result) sendFinalResultToParent(self, result) sendParent(self, { type: 'clear draft entities' }) + sendParent(self, { + type: 'update selected ids', + data: { selectedIds: [], duringAreaSelectIds: [] }, + }) + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: constraintId }, + }) dismissAngleSectorPrompt() self.send({ type: 'done' }) } catch (error) { @@ -899,6 +908,10 @@ function addDimensionListener({ runtime.firstSelection = firstSelection runtime.angleContext = angleContext showAngleSectorPrompt() + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: null }, + }) sendParent(self, { type: 'update selected ids', data: { @@ -964,6 +977,10 @@ function addDimensionListener({ } runtime.angleContext = angleContext + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: null }, + }) sendParent(self, { type: 'update selected ids', data: { From 7d7922a67d25158bd38677a7c9abb7702dfde23a Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 11 Jun 2026 14:53:53 +0200 Subject: [PATCH 15/78] hover/drag updates: drag keeps hovered rendering, angle constraint placement doesnt render hovered state --- .../tools/moveTool/moveTool.spec.ts | 16 ++++++++++++++ .../sketchSolve/tools/moveTool/moveTool.ts | 21 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts index 1e87388a286..05b33618a28 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts @@ -177,6 +177,7 @@ function createDragSnappingDeps() { getLastGoodPreview: vi.fn(() => null), setLastGoodPreview: vi.fn(), getDragStartOutcome: vi.fn(() => null), + onClearDragSnapping: vi.fn(), } } @@ -498,6 +499,8 @@ describe('createOnDragStartCallback', () => { })) const getCurrentCommittedCheckpointId = vi.fn(() => 12) const dismissConstraintHoverPopup = vi.fn() + const getDraggedEntityId = vi.fn(() => null) + const onUpdateHoveredId = vi.fn() const callback = createOnDragStartCallback({ setLastSuccessfulDragFromPoint, @@ -508,6 +511,8 @@ describe('createOnDragStartCallback', () => { getCurrentSketchOutcome, getCurrentCommittedCheckpointId, dismissConstraintHoverPopup, + getDraggedEntityId, + onUpdateHoveredId, }) const intersectionPoint = { @@ -3946,6 +3951,7 @@ describe('setUpOnDragAndSelectionClickCallbacks constraint label dragging', () = onDragStart, onDrag, rustContext, + send, } = setUpMoveToolCallbacks({ apiObjects: [constraint], hoveredId: constraint.id, @@ -3966,6 +3972,11 @@ describe('setUpOnDragAndSelectionClickCallbacks constraint label dragging', () = intersects: [], }) + expect(send).toHaveBeenCalledWith({ + type: 'update hovered id', + data: { hoveredId: constraint.id }, + }) + await onDrag({ intersectionPoint: { twoD: new Vector2(1, 31), @@ -3990,6 +4001,11 @@ describe('setUpOnDragAndSelectionClickCallbacks constraint label dragging', () = undefined, false ) + + expect(send).not.toHaveBeenCalledWith({ + type: 'update hovered id', + data: { hoveredId: null }, + }) } ) }) diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.ts index ed8405c081b..0c5baf5eff7 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.ts @@ -885,6 +885,8 @@ type CreateOnDragStartCallbackArgs = { getCurrentCommittedCheckpointId: () => number | null // Clears transient hover UI that should not remain visible during drag. dismissConstraintHoverPopup: () => void + getDraggedEntityId: () => number | null + onUpdateHoveredId: (hoveredId: number | null) => void } /** @@ -903,6 +905,8 @@ export function createOnDragStartCallback({ getCurrentSketchOutcome, getCurrentCommittedCheckpointId, dismissConstraintHoverPopup, + getDraggedEntityId, + onUpdateHoveredId, }: CreateOnDragStartCallbackArgs): (arg: { intersectionPoint: { twoD: Vector2; threeD: Vector3 } selected?: Object3D @@ -912,9 +916,17 @@ export function createOnDragStartCallback({ return ({ intersectionPoint }) => { dismissConstraintHoverPopup() beginDragSession() + const currentSketchOutcome = getCurrentSketchOutcome() + const draggedConstraintLabelId = getConstraintLabelId( + getDraggedEntityId(), + currentSketchOutcome?.sceneGraphDelta + ) + if (draggedConstraintLabelId !== null) { + onUpdateHoveredId(draggedConstraintLabelId) + } setLastSuccessfulDragFromPoint(intersectionPoint.twoD.clone()) setLastGoodPreview(null) - setDragStartOutcome(getCurrentSketchOutcome()) + setDragStartOutcome(currentSketchOutcome) setPreDragCheckpointId(getCurrentCommittedCheckpointId()) } } @@ -1237,6 +1249,7 @@ export function createOnDragCallback({ getDefaultLengthUnit, getJsAppSettings, sceneInfra, + onClearDragSnapping, onUpdateDragSnapping, onPreviewSolveStarted, onPreviewSolveSettled, @@ -1290,6 +1303,7 @@ export function createOnDragCallback({ getDefaultLengthUnit: () => UnitLength | undefined getJsAppSettings: () => Promise> sceneInfra: SceneInfra + onClearDragSnapping: () => void onUpdateDragSnapping: (candidate: SnappingCandidate | null) => void onPreviewSolveStarted?: () => void onPreviewSolveSettled?: () => void @@ -1355,7 +1369,7 @@ export function createOnDragCallback({ }) if (result && isActiveDragSession()) { - onUpdateDragSnapping(null) + onClearDragSnapping() onNewSketchOutcome({ ...result, writeToDisk: false, @@ -1852,6 +1866,8 @@ export function setUpOnDragAndSelectionClickCallbacks({ getCurrentCommittedCheckpointId: () => context.kclManager.currentSketchCheckpointId, dismissConstraintHoverPopup: dismissConstraintHoverPopupOnDragStart, + getDraggedEntityId, + onUpdateHoveredId: sendHoveredState, }), onDragEnd: createOnDragEndCallback({ getDraggedEntityId, @@ -2345,6 +2361,7 @@ export function setUpOnDragAndSelectionClickCallbacks({ getJsAppSettings: async () => jsAppSettings(context.rustContext.settingsActor), sceneInfra: context.sceneInfra, + onClearDragSnapping: clearDragSnappingState, onUpdateDragSnapping: updateDragSnappingState, onPreviewSolveStarted: markPreviewSolveStarted, onPreviewSolveSettled: markPreviewSolveSettled, From 2d199d94684d2864e2b32fd4dafc37961da9cc93 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sat, 13 Jun 2026 00:13:09 +0200 Subject: [PATCH 16/78] handle async fn calling edge cases --- .../sketchSolve/tools/dimensionTool.ts | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index d06ac4e8ff1..d4fc59f4964 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -44,6 +44,7 @@ type DimensionToolContext = { initialSelectionIds: SketchSolveSelectionId[] initialSelectionClickPoints: SelectionClickPoints initialObjects: ApiObject[] + runtime: DraftRuntime } type DimensionToolInput = { @@ -150,6 +151,8 @@ type DraftRuntime = { lastDraftKey: string | null previewInFlight: boolean queuedMousePoint: Coords2d | null + // Used by async api calls in case tool got deactivated since + active: boolean } const LINE_INTERSECTION_EPSILON = 1e-8 @@ -177,9 +180,15 @@ function createRuntime(): DraftRuntime { lastDraftKey: null, previewInFlight: false, queuedMousePoint: null, + active: true, } } +function deactivateRuntime(runtime: DraftRuntime) { + runtime.active = false + runtime.queuedMousePoint = null +} + function showAngleSectorPrompt() { toast('Choose angle sector, then click to place the label.', { id: ANGLE_SECTOR_PROMPT_TOAST_ID, @@ -691,6 +700,20 @@ async function deleteDraftConstraint( runtime.draftConstraintId = null } +async function deleteInactivePreviewConstraint( + context: DimensionToolContext, + constraintId: number +) { + await context.rustContext.deleteObjects( + SKETCH_FILE_VERSION, + context.sketchId, + [constraintId], + [], + jsAppSettings(context.rustContext.settingsActor), + false + ) +} + function sendPreviewResultToParent( self: { _parent?: { send: (event: unknown) => void } }, result: { @@ -736,7 +759,7 @@ async function replaceDraftAngleConstraint( self: { _parent?: { send: (event: unknown) => void } }, mousePoint: Coords2d ) { - if (!runtime.angleContext) { + if (!runtime.active || !runtime.angleContext) { return } @@ -751,6 +774,9 @@ async function replaceDraftAngleConstraint( } await deleteDraftConstraint(runtime, context) + if (!runtime.active) { + return + } const result = await context.rustContext.addConstraint( SKETCH_FILE_VERSION, @@ -763,6 +789,10 @@ async function replaceDraftAngleConstraint( if (constraintId === null) { return } + if (!runtime.active) { + await deleteInactivePreviewConstraint(context, constraintId) + return + } runtime.draftConstraintId = constraintId runtime.lastDraftKey = draftKey @@ -783,6 +813,10 @@ function requestDraftPreview( self: { _parent?: { send: (event: unknown) => void } }, mousePoint: Coords2d ) { + if (!runtime.active) { + return + } + runtime.queuedMousePoint = mousePoint if (runtime.previewInFlight) { return @@ -791,7 +825,7 @@ function requestDraftPreview( runtime.previewInFlight = true void (async () => { try { - while (runtime.queuedMousePoint) { + while (runtime.active && runtime.queuedMousePoint) { const nextMousePoint = runtime.queuedMousePoint runtime.queuedMousePoint = null await replaceDraftAngleConstraint( @@ -818,7 +852,7 @@ async function commitDraftAngleConstraint( }, mousePoint: Coords2d ) { - if (!runtime.angleContext) { + if (!runtime.active || !runtime.angleContext) { return } @@ -829,6 +863,7 @@ async function commitDraftAngleConstraint( ) try { + deactivateRuntime(runtime) await deleteDraftConstraint(runtime, context) const result = await context.rustContext.addConstraint( SKETCH_FILE_VERSION, @@ -891,7 +926,8 @@ function addDimensionListener({ send: (event: DimensionToolEvent) => void } }) { - const runtime = createRuntime() + const runtime = context.runtime + runtime.active = true const initialLineSelections = getInitialAngleLineSelections( context.initialSelectionIds, context.initialSelectionClickPoints, @@ -1022,6 +1058,7 @@ function addDimensionListener({ function removeDimensionListener({ context, }: { context: DimensionToolContext }) { + deactivateRuntime(context.runtime) dismissAngleSectorPrompt() context.sceneInfra.setCallbacks({ onClick: () => {}, @@ -1059,6 +1096,7 @@ export const machine = setup({ initialSelectionClickPoints: input.initialSelectionClickPoints ?? {}, initialObjects: input.initialObjects ?? input.sceneGraphDelta?.new_graph.objects ?? [], + runtime: createRuntime(), }), id: 'Dimension tool', initial: 'selecting lines', From 62aa8f6731281508549d569b7c937684c7fcab98 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sat, 13 Jun 2026 15:50:52 +0200 Subject: [PATCH 17/78] add edit_angle_constraint to avoid recreating constraint for draft preview on each drag --- rust/kcl-lib/src/frontend.rs | 268 ++++++++++++++---- rust/kcl-lib/src/frontend/sketch.rs | 9 + rust/kcl-lib/src/lib.rs | 1 + rust/kcl-wasm-lib/src/api.rs | 70 +++++ src/lib/rustContext.ts | 59 ++++ .../sketchSolve/tools/dimensionTool.spec.ts | 93 +++++- .../sketchSolve/tools/dimensionTool.ts | 63 ++-- .../sketchSolve/tools/sketchToolTestUtils.ts | 1 + 8 files changed, 478 insertions(+), 86 deletions(-) diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index cf7fc71e493..fbff2cc1cd0 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -245,6 +245,12 @@ pub struct EditDistanceConstraintLabelPositionOptions { pub commit_solved_initial_guesses: bool, } +/// Options for editing an angle constraint during sketch dragging. +pub struct EditAngleConstraintOptions { + /// Whether solver-updated initial guesses should be written back to KCL. + pub commit_solved_initial_guesses: bool, +} + #[derive(Debug, Clone)] pub struct FrontendState { program: Program, @@ -393,6 +399,24 @@ impl FrontendState { result } + /// Edit an angle constraint with optional solver writeback. + pub async fn edit_angle_constraint_with_options( + &mut self, + ctx: &ExecutorContext, + version: Version, + sketch: ObjectId, + constraint_id: ObjectId, + angle: Angle, + options: EditAngleConstraintOptions, + ) -> ExecResult<(SourceDelta, SceneGraphDelta)> { + let previous_commit_mode = self + .next_edit_commits_solver_solutions + .replace(options.commit_solved_initial_guesses); + let result = SketchApi::edit_angle_constraint(self, ctx, version, sketch, constraint_id, angle).await; + self.next_edit_commits_solver_solutions = previous_commit_mode; + result + } + pub async fn restore_sketch_checkpoint( &mut self, checkpoint_id: SketchCheckpointId, @@ -1571,6 +1595,59 @@ impl SketchApi for FrontendState { .await } + async fn edit_angle_constraint( + &mut self, + ctx: &ExecutorContext, + _version: Version, + sketch: ObjectId, + constraint_id: ObjectId, + angle: Angle, + ) -> ExecResult<(SourceDelta, SceneGraphDelta)> { + // TODO: Check version. + let sketch_block_ref = + sketch_block_ref_from_id(&self.scene_graph, sketch).map_err(KclErrorWithOutputs::no_outputs)?; + + let object = self.scene_graph.objects.get(constraint_id.0).ok_or_else(|| { + KclErrorWithOutputs::no_outputs(KclError::refactor(format!("Object not found: {constraint_id:?}"))) + })?; + if !matches!( + &object.kind, + ObjectKind::Constraint { + constraint: Constraint::Angle(_), + } + ) { + return Err(KclErrorWithOutputs::no_outputs(KclError::refactor(format!( + "Object is not an angle constraint: {constraint_id:?}" + )))); + } + + let mut new_ast = self.program.ast.clone(); + let (call, value) = self + .angle_constraint_ast_parts(&angle, &mut new_ast) + .map_err(KclErrorWithOutputs::no_outputs)?; + + self.mutate_ast( + &mut new_ast, + constraint_id, + AstMutateCommand::EditAngleConstraint { call, value }, + ) + .map_err(KclErrorWithOutputs::no_outputs)?; + let commit_solved_initial_guesses = self.next_edit_commits_solver_solutions.take().unwrap_or(true); + + self.execute_after_edit( + ctx, + sketch, + sketch_block_ref, + &mut new_ast, + ExecuteAfterEditOptions { + segment_ids_edited: Default::default(), + edit_kind: EditDeleteKind::Edit, + commit_solved_initial_guesses, + }, + ) + .await + } + /// Splitting a segment means creating a new segment, editing the old one, and then /// migrating a bunch of the constraints from the original segment to the new one /// (i.e. deleting them and re-adding them on the other segment). @@ -3725,45 +3802,38 @@ impl FrontendState { angle: Angle, new_ast: &mut ast::Node, ) -> Result { + let sketch_id = sketch; + let (angle_call_ast, angle_value_ast) = self.angle_constraint_ast_parts(&angle, new_ast)?; + let angle_ast = ast::Expr::BinaryExpression(Box::new(ast::Node::no_src(ast::BinaryExpression { + left: angle_call_ast, + operator: ast::BinaryOperator::Eq, + right: angle_value_ast, + digest: None, + }))); + + // Add the line to the AST of the sketch block. + let (sketch_block_ref, _) = self.mutate_ast( + new_ast, + sketch_id, + AstMutateCommand::AddSketchBlockExprStmt { expr: angle_ast }, + )?; + Ok(sketch_block_ref) + } + + fn angle_constraint_ast_parts( + &self, + angle: &Angle, + new_ast: &mut ast::Node, + ) -> Result<(ast::BinaryPart, ast::BinaryPart), KclError> { let &[l0_id, l1_id] = angle.lines.as_slice() else { return Err(KclError::refactor(format!( "Angle constraint must have exactly 2 lines, got {}", angle.lines.len() ))); }; - let sketch_id = sketch; - // Map the runtime objects back to variable names. - let line0_object = self - .scene_graph - .objects - .get(l0_id.0) - .ok_or_else(|| KclError::refactor(format!("Line not found: {l0_id:?}")))?; - let ObjectKind::Segment { segment: line0_segment } = &line0_object.kind else { - return Err(KclError::refactor(format!("Object is not a segment: {line0_object:?}"))); - }; - let Segment::Line(_) = line0_segment else { - return Err(KclError::refactor(format!( - "Only lines can be constrained to meet at an angle: {line0_object:?}", - ))); - }; let l0_ast = self.line_id_to_ast_reference(l0_id, new_ast)?; - - let line1_object = self - .scene_graph - .objects - .get(l1_id.0) - .ok_or_else(|| KclError::refactor(format!("Line not found: {l1_id:?}")))?; - let ObjectKind::Segment { segment: line1_segment } = &line1_object.kind else { - return Err(KclError::refactor(format!("Object is not a segment: {line1_object:?}"))); - }; - let Segment::Line(_) = line1_segment else { - return Err(KclError::refactor(format!( - "Only lines can be constrained to meet at an angle: {line1_object:?}", - ))); - }; let l1_ast = self.line_id_to_ast_reference(l1_id, new_ast)?; - let lines_ast = ast::Expr::ArrayExpression(Box::new(ast::Node::no_src(ast::ArrayExpression { elements: vec![l0_ast, l1_ast], digest: None, @@ -3812,37 +3882,24 @@ impl FrontendState { }); } - // Create the angle() call. - let angle_call_ast = ast::BinaryPart::CallExpressionKw(Box::new(ast::Node::no_src(ast::CallExpressionKw { + let call = ast::BinaryPart::CallExpressionKw(Box::new(ast::Node::no_src(ast::CallExpressionKw { callee: ast::Node::no_src(ast_sketch2_name(ANGLE_FN)), unlabeled: (!has_explicit_angle_mode).then_some(lines_ast), arguments, digest: None, non_code_meta: Default::default(), }))); - let angle_ast = ast::Expr::BinaryExpression(Box::new(ast::Node::no_src(ast::BinaryExpression { - left: angle_call_ast, - operator: ast::BinaryOperator::Eq, - right: ast::BinaryPart::Literal(Box::new(ast::Node::no_src(ast::Literal { - value: ast::LiteralValue::Number { - value: angle.angle.value, - suffix: angle.angle.units, - }, - raw: format_number_literal(angle.angle.value, angle.angle.units, None).map_err(|_| { - KclError::refactor(format!("Could not format numeric suffix: {:?}", angle.angle.units)) - })?, - digest: None, - }))), + let value = ast::BinaryPart::Literal(Box::new(ast::Node::no_src(ast::Literal { + value: ast::LiteralValue::Number { + value: angle.angle.value, + suffix: angle.angle.units, + }, + raw: format_number_literal(angle.angle.value, angle.angle.units, None) + .map_err(|_| KclError::refactor(format!("Could not format numeric suffix: {:?}", angle.angle.units)))?, digest: None, }))); - // Add the line to the AST of the sketch block. - let (sketch_block_ref, _) = self.mutate_ast( - new_ast, - sketch_id, - AstMutateCommand::AddSketchBlockExprStmt { expr: angle_ast }, - )?; - Ok(sketch_block_ref) + Ok((call, value)) } async fn add_tangent( @@ -5585,6 +5642,10 @@ enum AstMutateCommand { EditConstraintValue { value: ast::BinaryPart, }, + EditAngleConstraint { + call: ast::BinaryPart, + value: ast::BinaryPart, + }, EditDistanceConstraintLabelPosition { label_position: ast::Expr, }, @@ -6111,6 +6172,20 @@ fn process(ctx: &AstMutateContext, node: NodeMut) -> TraversalReturn { + if let NodeMut::BinaryExpression(binary_expr) = node { + let ast::BinaryPart::CallExpressionKw(existing_call) = &binary_expr.left else { + return TraversalReturn::new_continue(()); + }; + if existing_call.callee.name.name != ANGLE_FN { + return TraversalReturn::new_continue(()); + } + + binary_expr.left = call.clone(); + binary_expr.right = value.clone(); + return TraversalReturn::new_break(Ok(AstMutateCommandReturn::None)); + } + } AstMutateCommand::EditDistanceConstraintLabelPosition { label_position } => { if let NodeMut::BinaryExpression(binary_expr) = node { let ast::BinaryPart::CallExpressionKw(call) = &mut binary_expr.left else { @@ -10832,6 +10907,95 @@ sketch(on = XY) { mock_ctx.close().await; } + #[tokio::test(flavor = "multi_thread")] + async fn test_edit_angle_constraint() { + let initial_source = "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle([line1, line2]) == 60deg +} +"; + + let program = Program::parse(initial_source).unwrap().0.unwrap(); + let mut frontend = FrontendState::new(); + let mock_ctx = ExecutorContext::new_mock(None).await; + let version = Version(0); + + frontend.program = program.clone(); + let outcome = mock_ctx.run_mock(&program, &MockConfig::default()).await.unwrap(); + frontend.update_state_after_exec(outcome, true); + let sketch_object = find_first_sketch_object(&frontend.scene_graph).unwrap(); + let sketch_id = sketch_object.id; + let sketch = expect_sketch(sketch_object); + let constraint_id = sketch.constraints[0]; + let line1_id = *sketch.segments.get(2).unwrap(); + let line2_id = *sketch.segments.get(5).unwrap(); + let label_position = Point2d { + x: Number { + value: 10.0, + units: NumericSuffix::Mm, + }, + y: Number { + value: 11.0, + units: NumericSuffix::Mm, + }, + }; + + let (src_delta, scene_delta) = frontend + .edit_angle_constraint_with_options( + &mock_ctx, + version, + sketch_id, + constraint_id, + Angle { + lines: vec![line2_id, line1_id], + angle: Number { + value: 60.0, + units: NumericSuffix::Deg, + }, + sector: Some(3), + reflex: Some(false), + label_position: Some(label_position.clone()), + source: Default::default(), + }, + EditAngleConstraintOptions { + commit_solved_initial_guesses: false, + }, + ) + .await + .unwrap(); + assert_eq!( + src_delta.text.as_str(), + "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle( + lines = [line2, line1], + sector = 3, + reflex = false, + labelPosition = [10mm, 11mm], +) == 60deg +} +" + ); + + let constraint_object = scene_delta.new_graph.objects.get(constraint_id.0).unwrap(); + let ObjectKind::Constraint { constraint } = &constraint_object.kind else { + panic!("Expected constraint object"); + }; + let Constraint::Angle(angle) = constraint else { + panic!("Expected angle constraint"); + }; + assert_eq!(angle.lines, vec![line2_id, line1_id]); + assert_eq!(angle.sector, Some(3)); + assert_eq!(angle.reflex, Some(false)); + assert_eq!(angle.label_position, Some(label_position)); + + mock_ctx.close().await; + } + #[tokio::test(flavor = "multi_thread")] async fn test_edit_distance_constraint_label_position_preserves_anchor_segment_solution() { let initial_source = "\ diff --git a/rust/kcl-lib/src/frontend/sketch.rs b/rust/kcl-lib/src/frontend/sketch.rs index 42133f6afad..9ecdb90cac0 100644 --- a/rust/kcl-lib/src/frontend/sketch.rs +++ b/rust/kcl-lib/src/frontend/sketch.rs @@ -133,6 +133,15 @@ pub trait SketchApi { anchor_segment_ids: Vec, ) -> ExecResult<(SourceDelta, SceneGraphDelta)>; + async fn edit_angle_constraint( + &mut self, + ctx: &ExecutorContext, + version: Version, + sketch: ObjectId, + constraint_id: ObjectId, + angle: Angle, + ) -> ExecResult<(SourceDelta, SceneGraphDelta)>; + /// Batch operations for split segment: edit segments, add constraints, delete objects. /// All operations are applied to a single AST and execute_after_edit is called once at the end. /// new_segment_info contains the IDs from the segment(s) added in a previous step. diff --git a/rust/kcl-lib/src/lib.rs b/rust/kcl-lib/src/lib.rs index 418f1db29bf..b7c3c201cc2 100644 --- a/rust/kcl-lib/src/lib.rs +++ b/rust/kcl-lib/src/lib.rs @@ -197,6 +197,7 @@ pub mod front { pub(crate) use crate::frontend::modify::next_free_name_using_max; pub use crate::frontend::sketch::ExecResult; pub use crate::frontend::{ + EditAngleConstraintOptions, EditDistanceConstraintLabelPositionOptions, EditSegmentsOptions, FrontendState, diff --git a/rust/kcl-wasm-lib/src/api.rs b/rust/kcl-wasm-lib/src/api.rs index 6b57f363963..87c0a8209b3 100644 --- a/rust/kcl-wasm-lib/src/api.rs +++ b/rust/kcl-wasm-lib/src/api.rs @@ -4,6 +4,7 @@ use gloo_utils::format::JsValueSerdeExt; use kcl_lib::KclErrorWithOutputs; use kcl_lib::Program; use kcl_lib::SegmentDragAnchor; +use kcl_lib::front::EditAngleConstraintOptions; use kcl_lib::front::EditDistanceConstraintLabelPositionOptions; use kcl_lib::front::EditSegmentsOptions; use kcl_lib::front::Error; @@ -622,6 +623,75 @@ impl Context { .map_err(|e| format!("Could not serialize edit constraint result. {TRUE_BUG} Details: {e}"))?) } + /// Edit an angle constraint in a sketch. + #[wasm_bindgen] + pub async fn edit_angle_constraint( + &self, + version_json: &str, + sketch_json: &str, + constraint_id_json: &str, + constraint_json: &str, + settings: &str, + create_checkpoint: bool, + commit_solver_results: bool, + ) -> Result { + console_error_panic_hook::set_once(); + + if !commit_solver_results && create_checkpoint { + return Err("Preview angle edits cannot create sketch checkpoints".into()); + } + + let version: kcl_lib::front::Version = + serde_json::from_str(version_json).map_err(|e| format!("Could not deserialize Version: {e}"))?; + let sketch: kcl_lib::front::ObjectId = + serde_json::from_str(sketch_json).map_err(|e| format!("Could not deserialize ObjectId: {e}"))?; + let constraint_id: kcl_lib::front::ObjectId = + serde_json::from_str(constraint_id_json).map_err(|e| format!("Could not deserialize ObjectId: {e}"))?; + let constraint: kcl_lib::front::Constraint = + serde_json::from_str(constraint_json).map_err(|e| format!("Could not deserialize Constraint: {e}"))?; + let kcl_lib::front::Constraint::Angle(angle) = constraint else { + return Err("edit_angle_constraint requires an Angle constraint".into()); + }; + + let ctx = self.create_executor_ctx(settings, None, true).map_err(|e| { + format!("Could not create KCL executor context for edit angle constraint. {TRUE_BUG} Details: {e}") + })?; + + let frontend = Arc::clone(&self.frontend); + let mut guard = frontend.write().await; + let (source_delta, scene_graph_delta) = guard + .edit_angle_constraint_with_options( + &ctx, + version, + sketch, + constraint_id, + angle, + EditAngleConstraintOptions { + commit_solved_initial_guesses: commit_solver_results, + }, + ) + .await + .map_err(|e: KclErrorWithOutputs| js_value_from_serde(&e))?; + let checkpoint_id = if create_checkpoint { + Some( + guard + .create_sketch_checkpoint(scene_graph_delta.exec_outcome.clone()) + .await + .map_err(|e: Error| js_value_from_serde(&e))?, + ) + } else { + None + }; + let result = kcl_lib::front::SketchMutationOutcome { + source_delta, + scene_graph_delta, + checkpoint_id, + }; + + Ok(JsValue::from_serde(&result) + .map_err(|e| format!("Could not serialize edit angle constraint result. {TRUE_BUG} Details: {e}"))?) + } + /// Edit a constraint label position in a sketch. #[wasm_bindgen] pub async fn edit_distance_constraint_label_position( diff --git a/src/lib/rustContext.ts b/src/lib/rustContext.ts index 0cd643e1246..29f086c72c3 100644 --- a/src/lib/rustContext.ts +++ b/src/lib/rustContext.ts @@ -701,6 +701,49 @@ export default class RustContext { } } + async editAngleConstraint( + version: ApiVersion, + sketch: ApiObjectId, + constraintId: ApiObjectId, + constraint: Extract, + settings: DeepPartial, + createCheckpoint = false, + commitSolverResults = true + ): Promise { + const instance = + (await this._checkContextInstance()) as ContextWithAngleConstraintEdit + + try { + if (!commitSolverResults && createCheckpoint) { + return Promise.reject( + new Error('Preview angle edits cannot create sketch checkpoints') + ) + } + + const result = await instance.edit_angle_constraint( + JSON.stringify(version), + JSON.stringify(sketch), + JSON.stringify(constraintId), + JSON.stringify(constraint), + JSON.stringify(settings), + createCheckpoint, + commitSolverResults + ) + const checkpointId = normalizeSketchCheckpointId(result.checkpointId) + if (checkpointId instanceof Error) { + return Promise.reject(checkpointId) + } + return { + kclSource: result.sourceDelta, + sceneGraphDelta: result.sceneGraphDelta, + checkpointId, + } + } catch (e: any) { + const err = errFromErrWithOutputs(e) + return Promise.reject(err) + } + } + async editDistanceConstraintLabelPosition( version: ApiVersion, sketch: ApiObjectId, @@ -908,6 +951,22 @@ type SketchMutationResult = { checkpointId?: number | null } +type ContextWithAngleConstraintEdit = Context & { + edit_angle_constraint( + versionJson: string, + sketchJson: string, + constraintIdJson: string, + constraintJson: string, + settings: string, + createCheckpoint: boolean, + commitSolverResults: boolean + ): Promise<{ + sourceDelta: SourceDelta + sceneGraphDelta: SceneGraphDelta + checkpointId?: number | null + }> +} + type SetProgramOutcome = | (Omit< Extract, diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index 79c1971e3df..15bea852c9f 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -88,25 +88,49 @@ function createParentHarness( const kclManager = createMockKclManager() const events: Array<{ type: string; data?: unknown }> = [] let nextConstraintId = 30 + let currentObjects = [...objects] rustContext.addConstraint = vi.fn(async (_version, _sketchId, constraint) => { const constraintId = nextConstraintId++ - const resultObjects = [ - ...objects, + currentObjects = [ + ...currentObjects, createAngleConstraintObject({ id: constraintId, constraint }), ] return { kclSource: { text: '' }, - sceneGraphDelta: createSceneGraphDelta(resultObjects, [constraintId]), + sceneGraphDelta: createSceneGraphDelta(currentObjects, [constraintId]), checkpointId: null, } }) as typeof rustContext.addConstraint - rustContext.deleteObjects = vi.fn(async () => ({ - kclSource: { text: '' }, - sceneGraphDelta: createSceneGraphDelta(objects), - checkpointId: null, - })) as typeof rustContext.deleteObjects + rustContext.editAngleConstraint = vi.fn( + async (_version, _sketchId, constraintId, constraint) => { + currentObjects = currentObjects.map((object) => + object.id === constraintId + ? createAngleConstraintObject({ id: constraintId, constraint }) + : object + ) + + return { + kclSource: { text: '' }, + sceneGraphDelta: createSceneGraphDelta(currentObjects), + checkpointId: null, + } + } + ) as typeof rustContext.editAngleConstraint + rustContext.deleteObjects = vi.fn( + async (_version, _sketchId, constraintIds) => { + currentObjects = currentObjects.filter( + (object) => !constraintIds.includes(object.id) + ) + + return { + kclSource: { text: '' }, + sceneGraphDelta: createSceneGraphDelta(currentObjects), + checkpointId: null, + } + } + ) as typeof rustContext.deleteObjects const sceneGraphDelta = createSceneGraphDelta(objects) const parentMachine = setup({ @@ -337,6 +361,59 @@ describe('dimensionTool', () => { }) }) + it('edits the existing draft angle constraint while moving the cursor', async () => { + const sketch = createSketchApiObject({ id: 0 }) + const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) + const line0End = createPointApiObject({ id: 2, x: 10, y: 0 }) + const line1End = createPointApiObject({ + id: 3, + x: 5, + y: 8.660254037844386, + }) + const line0 = createLineApiObject({ id: 10, start: 1, end: 2 }) + const line1 = createLineApiObject({ id: 11, start: 1, end: 3 }) + const objects = [sketch, origin, line0End, line1End, line0, line1] + const { actor, sceneInfra, rustContext } = createParentHarness(objects) + const callbacks = (sceneInfra.setCallbacks as any).mock.calls[0][0] + + callbacks.onClick(createMouseEvent([8, 0])) + callbacks.onClick(createMouseEvent([5, 8.660254037844386])) + + await waitFor( + actor, + () => (rustContext.addConstraint as any).mock.calls.length === 1 + ) + + callbacks.onMove(createMouseEvent([0, 10])) + + await waitFor( + actor, + () => (rustContext.editAngleConstraint as any).mock.calls.length === 1 + ) + + expect((rustContext.addConstraint as any).mock.calls).toHaveLength(1) + expect((rustContext.deleteObjects as any).mock.calls).toHaveLength(0) + const editCall = (rustContext.editAngleConstraint as any).mock.calls[0] + expect(editCall[2]).toBe(30) + expect(editCall[3]).toEqual({ + type: 'Angle', + lines: [10, 11], + angle: { value: 120, units: 'Deg' }, + sector: 2, + reflex: false, + labelPosition: { + x: { value: 0, units: 'Mm' }, + y: { value: 10, units: 'Mm' }, + }, + source: { + expr: '120deg', + is_literal: true, + }, + }) + expect(editCall[5]).toBe(false) + expect(editCall[6]).toBe(false) + }) + it('starts sector selection when initialized with two selected lines', async () => { const sketch = createSketchApiObject({ id: 0 }) const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index d4fc59f4964..ba3a517fde1 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -155,6 +155,8 @@ type DraftRuntime = { active: boolean } +type ApiAngleConstraint = Extract + const LINE_INTERSECTION_EPSILON = 1e-8 const SECTOR_EPSILON = 1e-9 const ANGLE_SECTOR_PROMPT_TOAST_ID = 'dimension-tool-angle-sector-prompt' @@ -631,7 +633,7 @@ export function buildDimensionAngleConstraint( angleContext: DimensionAngleDraftContext, mousePoint: Coords2d, units: NumericSuffix -): ApiConstraint { +): ApiAngleConstraint { const selection = getDimensionAngleSelection(mousePoint, angleContext) const angle = getDimensionAngleDegrees(angleContext, selection) @@ -666,11 +668,7 @@ function getConstraintIdFromResult(result: { ) } -function getDraftKey(constraint: ApiConstraint) { - if (constraint.type !== 'Angle') { - return '' - } - +function getDraftKey(constraint: ApiAngleConstraint) { return [ constraint.lines.join(','), constraint.angle.value, @@ -773,24 +771,35 @@ async function replaceDraftAngleConstraint( return } - await deleteDraftConstraint(runtime, context) - if (!runtime.active) { - return - } + const settings = jsAppSettings(context.rustContext.settingsActor) + const existingConstraintId = runtime.draftConstraintId + const result = + existingConstraintId === null + ? await context.rustContext.addConstraint( + SKETCH_FILE_VERSION, + context.sketchId, + constraint, + settings, + false + ) + : await context.rustContext.editAngleConstraint( + SKETCH_FILE_VERSION, + context.sketchId, + existingConstraintId, + constraint, + settings, + false, + false + ) - const result = await context.rustContext.addConstraint( - SKETCH_FILE_VERSION, - context.sketchId, - constraint, - jsAppSettings(context.rustContext.settingsActor), - false - ) - const constraintId = getConstraintIdFromResult(result) + const constraintId = existingConstraintId ?? getConstraintIdFromResult(result) if (constraintId === null) { return } if (!runtime.active) { - await deleteInactivePreviewConstraint(context, constraintId) + if (existingConstraintId === null) { + await deleteInactivePreviewConstraint(context, constraintId) + } return } @@ -798,13 +807,15 @@ async function replaceDraftAngleConstraint( runtime.lastDraftKey = draftKey sendPreviewResultToParent(self, result) - sendParent(self, { - type: 'set draft entities', - data: { - segmentIds: [], - constraintIds: [constraintId], - }, - }) + if (existingConstraintId === null) { + sendParent(self, { + type: 'set draft entities', + data: { + segmentIds: [], + constraintIds: [constraintId], + }, + }) + } } function requestDraftPreview( diff --git a/src/machines/sketchSolve/tools/sketchToolTestUtils.ts b/src/machines/sketchSolve/tools/sketchToolTestUtils.ts index fcba3ea8e49..72d59efab96 100644 --- a/src/machines/sketchSolve/tools/sketchToolTestUtils.ts +++ b/src/machines/sketchSolve/tools/sketchToolTestUtils.ts @@ -284,6 +284,7 @@ export function createMockRustContext(): RustContext { addConstraint: vi.fn(), chainSegment: vi.fn(), editSegments: vi.fn(), + editAngleConstraint: vi.fn(), editDistanceConstraintLabelPosition: vi.fn(), deleteObjects: vi.fn(), settingsActor: { From 6bbe9dbd8e5fa1f7d12dd4f72d39d66c6a021163 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sat, 13 Jun 2026 22:29:21 +0200 Subject: [PATCH 18/78] lint --- .../AngleConstraintBuilder.test.ts | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts index 47f7be0d80f..8c216a20a62 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts @@ -94,35 +94,35 @@ describe('calculateArcRenderInput', () => { it('renders sector 1 from line0 forward to line1 forward', () => { const { angleConstraint, objects } = createSectorTestObjects(1) - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.line1).toEqual([ + expect(arcInput?.line1).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.line2).toEqual([ + expect(arcInput?.line2).toEqual([ [0, 0], [5, 5 * Math.sqrt(3)], ]) - expect(renderInput?.startAngle).toBeCloseTo(0) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.startAngle).toBeCloseTo(0) + expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) it('renders a reflex angle as the inverse of the selected sector', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300, true) - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.line1).toEqual([ + expect(arcInput?.line1).toEqual([ [0, 0], [5, 5 * Math.sqrt(3)], ]) - expect(renderInput?.line2).toEqual([ + expect(arcInput?.line2).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.startAngle).toBeCloseTo(Math.PI / 3) - expect(renderInput?.sweepAngle).toBeCloseTo((5 * Math.PI) / 3) + expect(arcInput?.startAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.sweepAngle).toBeCloseTo((5 * Math.PI) / 3) }) it('uses explicit label position for sector angle rendering', () => { @@ -136,81 +136,81 @@ describe('calculateArcRenderInput', () => { }) objects[20] = angleConstraint - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.labelPosition).toEqual([20, 30]) - expect(renderInput?.labelAngle).toBeCloseTo(Math.atan2(30, 20)) - expect(renderInput?.radius).toBeCloseTo(Math.hypot(20, 30)) - expect(renderInput?.startAngle).toBeCloseTo(0) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.labelPosition).toEqual([20, 30]) + expect(arcInput?.labelAngle).toBeCloseTo(Math.atan2(30, 20)) + expect(arcInput?.radius).toBeCloseTo(Math.hypot(20, 30)) + expect(arcInput?.startAngle).toBeCloseTo(0) + expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) it('does not infer reflex rendering from a major angle value', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300) - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.line1).toEqual([ + expect(arcInput?.line1).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.line2).toEqual([ + expect(arcInput?.line2).toEqual([ [0, 0], [5, 5 * Math.sqrt(3)], ]) - expect(renderInput?.startAngle).toBeCloseTo(0) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.startAngle).toBeCloseTo(0) + expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) it('renders sector 2 from line1 forward to line0 reverse', () => { const { angleConstraint, objects } = createSectorTestObjects(2, 120) - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.line1).toEqual([ + expect(arcInput?.line1).toEqual([ [0, 0], [5, 5 * Math.sqrt(3)], ]) - expect(renderInput?.line2).toEqual([ + expect(arcInput?.line2).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.startAngle).toBeCloseTo(Math.PI / 3) - expect(renderInput?.sweepAngle).toBeCloseTo((2 * Math.PI) / 3) + expect(arcInput?.startAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.sweepAngle).toBeCloseTo((2 * Math.PI) / 3) }) it('renders sector 3 from line0 reverse to line1 reverse', () => { const { angleConstraint, objects } = createSectorTestObjects(3) - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.line1).toEqual([ + expect(arcInput?.line1).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.line2).toEqual([ + expect(arcInput?.line2).toEqual([ [0, 0], [5, 5 * Math.sqrt(3)], ]) - expect(renderInput?.startAngle).toBeCloseTo(-Math.PI) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.startAngle).toBeCloseTo(-Math.PI) + expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) it('renders sector 4 from line1 reverse to line0 forward', () => { const { angleConstraint, objects } = createSectorTestObjects(4, 120) - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.line1).toEqual([ + expect(arcInput?.line1).toEqual([ [0, 0], [5, 5 * Math.sqrt(3)], ]) - expect(renderInput?.line2).toEqual([ + expect(arcInput?.line2).toEqual([ [0, 0], [10, 0], ]) - expect(renderInput?.startAngle).toBeCloseTo((-2 * Math.PI) / 3) - expect(renderInput?.sweepAngle).toBeCloseTo((2 * Math.PI) / 3) + expect(arcInput?.startAngle).toBeCloseTo((-2 * Math.PI) / 3) + expect(arcInput?.sweepAngle).toBeCloseTo((2 * Math.PI) / 3) }) it('uses the legacy heuristic when sector metadata is absent', () => { @@ -222,10 +222,10 @@ describe('calculateArcRenderInput', () => { delete angleConstraint.kind.constraint.sector } - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.startAngle).toBeCloseTo(0) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.startAngle).toBeCloseTo(0) + expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) it('uses explicit label position for legacy angle rendering', () => { @@ -238,12 +238,12 @@ describe('calculateArcRenderInput', () => { }) objects[20] = angleConstraint - const renderInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) - expect(renderInput?.labelPosition).toEqual([21, 31]) - expect(renderInput?.labelAngle).toBeCloseTo(Math.atan2(31, 21)) - expect(renderInput?.radius).toBeCloseTo(Math.hypot(21, 31)) - expect(renderInput?.startAngle).toBeCloseTo(0) - expect(renderInput?.sweepAngle).toBeCloseTo(Math.PI / 3) + expect(arcInput?.labelPosition).toEqual([21, 31]) + expect(arcInput?.labelAngle).toBeCloseTo(Math.atan2(31, 21)) + expect(arcInput?.radius).toBeCloseTo(Math.hypot(21, 31)) + expect(arcInput?.startAngle).toBeCloseTo(0) + expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) }) From f50ee3ccb9e2d18ad459a6c95086ca73610e69b0 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 14 Jun 2026 15:55:40 +0200 Subject: [PATCH 19/78] lint --- .../AngleConstraintBuilder.test.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts index 8c216a20a62..905a03b51ad 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts @@ -1,5 +1,5 @@ import type { ApiObject } from '@rust/kcl-lib/bindings/FrontendApi' -import { calculateArcRenderInput } from '@src/machines/sketchSolve/constraints/AngleConstraintBuilder' +import { calculateArcRenderInput as calculateArcInput } from '@src/machines/sketchSolve/constraints/AngleConstraintBuilder' import { createLineApiObject, createPointApiObject, @@ -94,7 +94,7 @@ describe('calculateArcRenderInput', () => { it('renders sector 1 from line0 forward to line1 forward', () => { const { angleConstraint, objects } = createSectorTestObjects(1) - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.line1).toEqual([ [0, 0], @@ -111,7 +111,7 @@ describe('calculateArcRenderInput', () => { it('renders a reflex angle as the inverse of the selected sector', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300, true) - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.line1).toEqual([ [0, 0], @@ -136,7 +136,7 @@ describe('calculateArcRenderInput', () => { }) objects[20] = angleConstraint - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.labelPosition).toEqual([20, 30]) expect(arcInput?.labelAngle).toBeCloseTo(Math.atan2(30, 20)) @@ -148,7 +148,7 @@ describe('calculateArcRenderInput', () => { it('does not infer reflex rendering from a major angle value', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300) - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.line1).toEqual([ [0, 0], @@ -165,7 +165,7 @@ describe('calculateArcRenderInput', () => { it('renders sector 2 from line1 forward to line0 reverse', () => { const { angleConstraint, objects } = createSectorTestObjects(2, 120) - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.line1).toEqual([ [0, 0], @@ -182,7 +182,7 @@ describe('calculateArcRenderInput', () => { it('renders sector 3 from line0 reverse to line1 reverse', () => { const { angleConstraint, objects } = createSectorTestObjects(3) - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.line1).toEqual([ [0, 0], @@ -199,7 +199,7 @@ describe('calculateArcRenderInput', () => { it('renders sector 4 from line1 reverse to line0 forward', () => { const { angleConstraint, objects } = createSectorTestObjects(4, 120) - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.line1).toEqual([ [0, 0], @@ -222,7 +222,7 @@ describe('calculateArcRenderInput', () => { delete angleConstraint.kind.constraint.sector } - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.startAngle).toBeCloseTo(0) expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) @@ -238,7 +238,7 @@ describe('calculateArcRenderInput', () => { }) objects[20] = angleConstraint - const arcInput = calculateArcRenderInput(angleConstraint, objects, 1) + const arcInput = calculateArcInput(angleConstraint, objects, 1) expect(arcInput?.labelPosition).toEqual([21, 31]) expect(arcInput?.labelAngle).toBeCloseTo(Math.atan2(31, 21)) From abee6c06802bc4336b1eb8ba29302faf92338623 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 14 Jun 2026 17:22:50 +0200 Subject: [PATCH 20/78] rename angle reflex -> inverse, reflex is not accurate at all times and is a bit of a weird name --- rust/kcl-lib/src/execution/exec_ast.rs | 26 ++++++++--------- rust/kcl-lib/src/execution/geometry.rs | 2 +- rust/kcl-lib/src/frontend.rs | 26 ++++++++--------- rust/kcl-lib/src/frontend/sketch.rs | 2 +- rust/kcl-lib/src/std/constraints.rs | 10 +++---- rust/kcl-lib/std/solver.kcl | 4 +-- .../AngleConstraintBuilder.test.ts | 14 +++++----- .../constraints/AngleConstraintBuilder.ts | 2 +- .../sketchSolve/tools/dimensionTool.spec.ts | 28 +++++++++---------- .../sketchSolve/tools/dimensionTool.ts | 16 +++++------ 10 files changed, 65 insertions(+), 65 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index de234026fcd..06496e82cd4 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -295,7 +295,7 @@ struct AngleSectorRay { direction: AngleRayDirection, } -fn angle_sector_rays(sector: AngleSector, is_reflex: bool) -> [AngleSectorRay; 2] { +fn angle_sector_rays(sector: AngleSector, is_inverse: bool) -> [AngleSectorRay; 2] { let rays = match sector { AngleSector::One => [ AngleSectorRay { @@ -338,7 +338,7 @@ fn angle_sector_rays(sector: AngleSector, is_reflex: bool) -> [AngleSectorRay; 2 }, ], }; - if is_reflex { [rays[1], rays[0]] } else { rays } + if is_inverse { [rays[1], rays[0]] } else { rays } } fn normalize_radians(angle: f64) -> f64 { @@ -3956,7 +3956,7 @@ impl Node { }; let points_at_angle_data = match *mode { AngleConstraintMode::LinesAtAngle => None, - AngleConstraintMode::PointsAtAngle { sector, reflex } => { + AngleConstraintMode::PointsAtAngle { sector, inverse } => { let sketch_vars = exec_state .mod_local .sketch_block @@ -3989,7 +3989,7 @@ impl Node { representative_angle_endpoint(line0, initial_line0, initial_vertex, range)?; let (line1_representative, line1_direction) = representative_angle_endpoint(line1, initial_line1, initial_vertex, range)?; - let sector_rays = angle_sector_rays(sector, reflex); + let sector_rays = angle_sector_rays(sector, inverse); let angle_kind = ezpz::datatypes::AngleKind::Other(remap_angle_for_representative_rays( sector_rays, @@ -4046,10 +4046,10 @@ impl Node { debug_assert!(false, "{}", &message); return Err(KclError::new_internal(KclErrorDetails::new(message, vec![range]))); }; - let (sector, reflex) = match *mode { + let (sector, inverse) = match *mode { AngleConstraintMode::LinesAtAngle => (None, None), - AngleConstraintMode::PointsAtAngle { sector, reflex } => { - (Some(front_angle_sector(sector)), Some(reflex)) + AngleConstraintMode::PointsAtAngle { sector, inverse } => { + (Some(front_angle_sector(sector)), Some(inverse)) } }; let sketch_constraint = crate::front::Constraint::Angle(Angle { @@ -4058,7 +4058,7 @@ impl Node { internal_err("Failed to convert angle units numeric suffix:", range) })?, sector, - reflex, + inverse, label_position: label_position.clone(), source, }); @@ -6185,7 +6185,7 @@ sketch(on = XY) { }) .unwrap(); assert_eq!(angle.sector, Some(1)); - assert_eq!(angle.reflex, Some(false)); + assert_eq!(angle.inverse, Some(false)); } #[tokio::test(flavor = "multi_thread")] @@ -6238,13 +6238,13 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_accepts_reflex_angle_for_sector() { + async fn angle_labelled_lines_accepts_inverse_angle_for_sector() { let result = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) - angle(lines = [line1, line2], sector = 1, reflex = true) == 360deg - 60deg + angle(lines = [line1, line2], sector = 1, inverse = true) == 360deg - 60deg } "#, ) @@ -6264,7 +6264,7 @@ sketch(on = XY) { }) .unwrap(); assert_eq!(angle.sector, Some(1)); - assert_eq!(angle.reflex, Some(true)); + assert_eq!(angle.inverse, Some(true)); } #[tokio::test(flavor = "multi_thread")] @@ -6346,7 +6346,7 @@ sketch(on = XY) { assert!( err.to_string() - .contains("angle() sector and reflex require the labelled lines argument"), + .contains("angle() sector and inverse require the labelled lines argument"), "unexpected error: {err:?}" ); } diff --git a/rust/kcl-lib/src/execution/geometry.rs b/rust/kcl-lib/src/execution/geometry.rs index cffeca737e5..0c4605efc2c 100644 --- a/rust/kcl-lib/src/execution/geometry.rs +++ b/rust/kcl-lib/src/execution/geometry.rs @@ -2414,7 +2414,7 @@ pub enum AngleSector { #[derive(Debug, Clone, Copy, PartialEq)] pub enum AngleConstraintMode { LinesAtAngle, - PointsAtAngle { sector: AngleSector, reflex: bool }, + PointsAtAngle { sector: AngleSector, inverse: bool }, } #[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)] diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index fbff2cc1cd0..d27bce23db1 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -143,7 +143,7 @@ const FIXED_FN: &str = "fixed"; const ANGLE_FN: &str = "angle"; const ANGLE_LINES_PARAM: &str = "lines"; const ANGLE_SECTOR_PARAM: &str = "sector"; -const ANGLE_REFLEX_PARAM: &str = "reflex"; +const ANGLE_INVERSE_PARAM: &str = "inverse"; const HORIZONTAL_DISTANCE_FN: &str = "horizontalDistance"; const VERTICAL_DISTANCE_FN: &str = "verticalDistance"; const EQUAL_LENGTH_FN: &str = "equalLength"; @@ -3840,7 +3840,7 @@ impl FrontendState { non_code_meta: Default::default(), }))); - let has_explicit_angle_mode = angle.sector.is_some() || angle.reflex.is_some(); + let has_explicit_angle_mode = angle.sector.is_some() || angle.inverse.is_some(); let mut arguments = if has_explicit_angle_mode { vec![ast::LabeledArg { label: Some(ast::Identifier::new(ANGLE_LINES_PARAM)), @@ -3864,12 +3864,12 @@ impl FrontendState { }); } - if let Some(reflex) = angle.reflex { + if let Some(inverse) = angle.inverse { arguments.push(ast::LabeledArg { - label: Some(ast::Identifier::new(ANGLE_REFLEX_PARAM)), + label: Some(ast::Identifier::new(ANGLE_INVERSE_PARAM)), arg: ast::Expr::Literal(Box::new(ast::Node::no_src(ast::Literal { - value: ast::LiteralValue::Bool(reflex), - raw: reflex.to_string(), + value: ast::LiteralValue::Bool(inverse), + raw: inverse.to_string(), digest: None, }))), }); @@ -10955,7 +10955,7 @@ sketch(on = XY) { units: NumericSuffix::Deg, }, sector: Some(3), - reflex: Some(false), + inverse: Some(false), label_position: Some(label_position.clone()), source: Default::default(), }, @@ -10974,7 +10974,7 @@ sketch(on = XY) { angle( lines = [line2, line1], sector = 3, - reflex = false, + inverse = false, labelPosition = [10mm, 11mm], ) == 60deg } @@ -10990,7 +10990,7 @@ sketch(on = XY) { }; assert_eq!(angle.lines, vec![line2_id, line1_id]); assert_eq!(angle.sector, Some(3)); - assert_eq!(angle.reflex, Some(false)); + assert_eq!(angle.inverse, Some(false)); assert_eq!(angle.label_position, Some(label_position)); mock_ctx.close().await; @@ -12741,7 +12741,7 @@ splineSketch = sketch(on = XY) { units: NumericSuffix::Deg, }, sector: None, - reflex: None, + inverse: None, label_position: None, source: Default::default(), }); @@ -13465,7 +13465,7 @@ sketch(on = XY) { units: NumericSuffix::Deg, }, sector: None, - reflex: None, + inverse: None, label_position: None, source: Default::default(), }); @@ -13527,7 +13527,7 @@ sketch(on = XY) { units: NumericSuffix::Deg, }, sector: Some(1), - reflex: Some(true), + inverse: Some(true), label_position: Some(Point2d { x: Number { value: -0.73, @@ -13553,7 +13553,7 @@ sketch(on = XY) { angle( lines = [line1, line2], sector = 1, - reflex = true, + inverse = true, labelPosition = [-0.73mm, 0.75mm], ) == 270deg } diff --git a/rust/kcl-lib/src/frontend/sketch.rs b/rust/kcl-lib/src/frontend/sketch.rs index 9ecdb90cac0..882d82f84af 100644 --- a/rust/kcl-lib/src/frontend/sketch.rs +++ b/rust/kcl-lib/src/frontend/sketch.rs @@ -575,7 +575,7 @@ pub struct Angle { pub sector: Option, #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(optional)] - pub reflex: Option, + pub inverse: Option, #[serde(rename = "labelPosition")] #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(rename = "labelPosition")] diff --git a/rust/kcl-lib/src/std/constraints.rs b/rust/kcl-lib/src/std/constraints.rs index 233bf952519..d91655a7fd7 100644 --- a/rust/kcl-lib/src/std/constraints.rs +++ b/rust/kcl-lib/src/std/constraints.rs @@ -5148,14 +5148,14 @@ pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result("sector", §or_ty, exec_state)? .unwrap_or_else(|| TyF64::count(1.0)); - let reflex = args - .get_kw_arg_opt::("reflex", &RuntimeType::bool(), exec_state)? + let inverse = args + .get_kw_arg_opt::("inverse", &RuntimeType::bool(), exec_state)? .unwrap_or(false); ( lines, AngleConstraintMode::PointsAtAngle { sector: angle_sector(sector, args.source_range)?, - reflex, + inverse, }, ) } else { @@ -5163,11 +5163,11 @@ pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result("sector", §or_ty, exec_state)? .is_some() || args - .get_kw_arg_opt::("reflex", &RuntimeType::bool(), exec_state)? + .get_kw_arg_opt::("inverse", &RuntimeType::bool(), exec_state)? .is_some() { return Err(KclError::new_semantic(KclErrorDetails::new( - "angle() sector and reflex require the labelled lines argument".to_owned(), + "angle() sector and inverse require the labelled lines argument".to_owned(), vec![args.source_range], ))); } diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index 25a9aca4900..19da4761266 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -450,8 +450,8 @@ export fn angle( lines?: [Segment; 2], /// Which of the four angle sectors to constrain, numbered around the line intersection. sector?: number(Count) = 1, - /// Whether to constrain the reflex complement of the selected sector. - reflex?: bool = false, + /// Whether to constrain the inverse of the selected sector. + inverse?: bool = false, /// The desired position of the constraint label. labelPosition?: Point2d, ) {} diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts index 905a03b51ad..56c7ccf34b8 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.test.ts @@ -19,14 +19,14 @@ function createAngleConstraintApiObject({ lines, angle, sector, - reflex, + inverse, labelPosition, }: { id: number lines: [number, number] angle: number sector?: 1 | 2 | 3 | 4 - reflex?: boolean + inverse?: boolean labelPosition?: [number, number] }): ApiObject { return { @@ -38,7 +38,7 @@ function createAngleConstraintApiObject({ lines, angle: { value: angle, units: 'Deg' }, sector, - reflex, + inverse, labelPosition: labelPosition ? { x: { value: labelPosition[0], units: 'Mm' }, @@ -58,7 +58,7 @@ function createAngleConstraintApiObject({ function createSectorTestObjects( sector: 1 | 2 | 3 | 4, angle = 60, - reflex = false + inverse = false ) { const origin = createPointApiObject({ id: 1, x: 0, y: 0 }) const east = createPointApiObject({ id: 2, x: 10, y: 0 }) @@ -74,7 +74,7 @@ function createSectorTestObjects( lines: [10, 11], angle, sector, - reflex, + inverse, }) return { @@ -108,7 +108,7 @@ describe('calculateArcRenderInput', () => { expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) - it('renders a reflex angle as the inverse of the selected sector', () => { + it('renders the inverse sweep of the selected sector', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300, true) const arcInput = calculateArcInput(angleConstraint, objects, 1) @@ -145,7 +145,7 @@ describe('calculateArcRenderInput', () => { expect(arcInput?.sweepAngle).toBeCloseTo(Math.PI / 3) }) - it('does not infer reflex rendering from a major angle value', () => { + it('does not infer inverse sweep from a major angle value', () => { const { angleConstraint, objects } = createSectorTestObjects(1, 300) const arcInput = calculateArcInput(angleConstraint, objects, 1) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index 4ae35f695c9..c81871a8e64 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -230,7 +230,7 @@ function calculateExplicitArcRenderInput( line2Dir ) const [start, end] = - obj.kind.constraint.reflex === true + obj.kind.constraint.inverse === true ? [sectorBoundaries[1], sectorBoundaries[0]] : sectorBoundaries const explicitLabelPosition = getAngleLabelPosition(obj) diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index 15bea852c9f..03b49661de8 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -222,23 +222,23 @@ describe('dimensionTool angle selection', () => { it('maps cursor sectors relative to the clicked rays', () => { expect(getDimensionAngleSelection([1, 0.25], angleContext)).toEqual({ sector: 1, - reflex: false, + inverse: false, }) expect(getDimensionAngleSelection([0, 10], angleContext)).toEqual({ sector: 2, - reflex: false, + inverse: false, }) expect(getDimensionAngleSelection([1, -1], angleContext)).toEqual({ sector: 4, - reflex: false, + inverse: false, }) expect(getDimensionAngleSelection([-1, -0.6], angleContext)).toEqual({ sector: 1, - reflex: true, + inverse: true, }) }) - it('uses reflex when the visual wedge is opposite the directed KCL sector', () => { + it('uses inverse when the visual wedge is opposite the directed KCL sector', () => { const clockwiseContext: DimensionAngleDraftContext = { line0Id: 10, line1Id: 11, @@ -253,23 +253,23 @@ describe('dimensionTool angle selection', () => { expect(getDimensionAngleSelection([1, 0.25], clockwiseContext)).toEqual({ sector: 1, - reflex: true, + inverse: true, }) expect(getDimensionAngleSelection([0, 10], clockwiseContext)).toEqual({ sector: 4, - reflex: true, + inverse: true, }) expect(getDimensionAngleSelection([1, -1], clockwiseContext)).toEqual({ sector: 2, - reflex: true, + inverse: true, }) expect(getDimensionAngleSelection([-1, -0.3], clockwiseContext)).toEqual({ sector: 1, - reflex: false, + inverse: false, }) }) - it('builds the labelled angle constraint with sector, reflex, and label position', () => { + it('builds the labelled angle constraint with sector, inverse, and label position', () => { const constraint = buildDimensionAngleConstraint( angleContext, [-1, -0.6], @@ -281,7 +281,7 @@ describe('dimensionTool angle selection', () => { lines: [10, 11], angle: { value: 300, units: 'Deg' }, sector: 1, - reflex: true, + inverse: true, labelPosition: { x: { value: -1, units: 'Mm' }, y: { value: -0.6, units: 'Mm' }, @@ -324,7 +324,7 @@ describe('dimensionTool', () => { lines: [10, 11], angle: { value: 60, units: 'Deg' }, sector: 1, - reflex: false, + inverse: false, labelPosition: { x: { value: 5, units: 'Mm' }, y: { value: 8.66, units: 'Mm' }, @@ -400,7 +400,7 @@ describe('dimensionTool', () => { lines: [10, 11], angle: { value: 120, units: 'Deg' }, sector: 2, - reflex: false, + inverse: false, labelPosition: { x: { value: 0, units: 'Mm' }, y: { value: 10, units: 'Mm' }, @@ -446,7 +446,7 @@ describe('dimensionTool', () => { lines: [10, 11], angle: { value: 300, units: 'Deg' }, sector: 1, - reflex: true, + inverse: true, labelPosition: { x: { value: -1, units: 'Mm' }, y: { value: -0.6, units: 'Mm' }, diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index ba3a517fde1..b2b2e03d8ff 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -130,7 +130,7 @@ export type DimensionAngleDraftContext = { type DimensionAngleSelection = { sector: AngleSector - reflex: boolean + inverse: boolean } type AngleRay = { @@ -479,14 +479,14 @@ function getSelectionForWedge(startKey: AngleRayKey, endKey: AngleRayKey) { if (boundary.startKey === startKey && boundary.endKey === endKey) { return { sector: boundary.sector, - reflex: false, + inverse: false, } } if (boundary.startKey === endKey && boundary.endKey === startKey) { return { sector: boundary.sector, - reflex: true, + inverse: true, } } } @@ -565,7 +565,7 @@ function invertAngleSelection( ): DimensionAngleSelection { return { sector: selection.sector, - reflex: !selection.reflex, + inverse: !selection.inverse, } } @@ -606,7 +606,7 @@ export function getDimensionAngleSelection( return { sector: 1, - reflex: false, + inverse: false, } } @@ -615,7 +615,7 @@ function getDimensionAngleDegrees( selection: DimensionAngleSelection ) { let [start, end] = getAngleSectorRays(angleContext, selection.sector) - if (selection.reflex) { + if (selection.inverse) { ;[start, end] = [end, start] } @@ -642,7 +642,7 @@ export function buildDimensionAngleConstraint( lines: [angleContext.line0Id, angleContext.line1Id], angle: { value: angle, units: 'Deg' }, sector: selection.sector, - reflex: selection.reflex, + inverse: selection.inverse, labelPosition: { x: toNumber(mousePoint[0], units), y: toNumber(mousePoint[1], units), @@ -673,7 +673,7 @@ function getDraftKey(constraint: ApiAngleConstraint) { constraint.lines.join(','), constraint.angle.value, constraint.sector ?? '', - constraint.reflex === true ? 'reflex' : 'direct', + constraint.inverse === true ? 'inverse' : 'direct', constraint.labelPosition?.x.value ?? '', constraint.labelPosition?.y.value ?? '', ].join(':') From 846ef52a2a85bc947183546a2b5995211813e33c Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Mon, 15 Jun 2026 12:45:17 +0200 Subject: [PATCH 21/78] refactor dimensionTool onClick to be more readable --- .../sketchSolve/tools/dimensionTool.ts | 101 +++++++++--------- 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index b2b2e03d8ff..6bdf006a253 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -985,61 +985,58 @@ function addDimensionListener({ } const mousePoint: Coords2d = [twoD.x, twoD.y] - if (runtime.angleContext) { - void commitDraftAngleConstraint(runtime, context, self, mousePoint) - return - } - - const lineSelection = getClosestLineSelection(mousePoint, context) - if (!lineSelection) { - return - } - if (!runtime.firstSelection) { - runtime.firstSelection = lineSelection - sendParent(self, { - type: 'update selected ids', - data: { - selectedIds: [lineSelection.id], - replaceExistingSelection: true, - selectionClickPoints: { - [lineSelection.id]: lineSelection.clickPoint, + // First click: choose the first line and remember which side was clicked. + const lineSelection = getClosestLineSelection(mousePoint, context) + if (lineSelection) { + runtime.firstSelection = lineSelection + sendParent(self, { + type: 'update selected ids', + data: { + selectedIds: [lineSelection.id], + replaceExistingSelection: true, + selectionClickPoints: { + [lineSelection.id]: lineSelection.clickPoint, + }, }, - }, - }) - return - } - - if (lineSelection.id === runtime.firstSelection.id) { - return - } - - const angleContext = getDimensionAngleContext( - runtime.firstSelection, - lineSelection, - getObjects(context) - ) - if (!angleContext) { - return + }) + } + } else if (!runtime.angleContext) { + // Second click: choose the second line and enter sector/label placement. + const lineSelection = getClosestLineSelection(mousePoint, context) + if (lineSelection && lineSelection.id !== runtime.firstSelection.id) { + const angleContext = getDimensionAngleContext( + runtime.firstSelection, + lineSelection, + getObjects(context) + ) + + if (angleContext) { + runtime.angleContext = angleContext + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: null }, + }) + sendParent(self, { + type: 'update selected ids', + data: { + selectedIds: [runtime.firstSelection.id, lineSelection.id], + replaceExistingSelection: true, + selectionClickPoints: { + [runtime.firstSelection.id]: + runtime.firstSelection.clickPoint, + [lineSelection.id]: lineSelection.clickPoint, + }, + }, + }) + requestDraftPreview(runtime, context, self, mousePoint) + } + } + } else { + // Third click: place the label and commit the draft angle constraint. + // If 2 lines were already selected when equipping, this is the first click. + void commitDraftAngleConstraint(runtime, context, self, mousePoint) } - - runtime.angleContext = angleContext - sendParent(self, { - type: 'update hovered id', - data: { hoveredId: null }, - }) - sendParent(self, { - type: 'update selected ids', - data: { - selectedIds: [runtime.firstSelection.id, lineSelection.id], - replaceExistingSelection: true, - selectionClickPoints: { - [runtime.firstSelection.id]: runtime.firstSelection.clickPoint, - [lineSelection.id]: lineSelection.clickPoint, - }, - }, - }) - requestDraftPreview(runtime, context, self, mousePoint) }, onMove: (args) => { const twoD = args?.intersectionPoint?.twoD From 85a589c785496e95482ec82a5e865d7471ecd032 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Mon, 15 Jun 2026 15:43:26 +0200 Subject: [PATCH 22/78] call editAngleConstraint now instead of delete + add in commitDraftAngleConstraint --- .../sketchSolve/tools/dimensionTool.spec.ts | 28 +++++++++- .../sketchSolve/tools/dimensionTool.ts | 55 +++++++++---------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index 03b49661de8..11b43d47c21 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -345,9 +345,33 @@ describe('dimensionTool', () => { await waitFor( actor, - () => (rustContext.addConstraint as any).mock.calls.length === 2 + () => (rustContext.editAngleConstraint as any).mock.calls.length === 1 ) + expect((rustContext.addConstraint as any).mock.calls).toHaveLength(1) + expect((rustContext.editAngleConstraint as any).mock.calls[0]).toEqual([ + 0, + 0, + 30, + { + type: 'Angle', + lines: [10, 11], + angle: { value: 60, units: 'Deg' }, + sector: 1, + inverse: false, + labelPosition: { + x: { value: 4, units: 'Mm' }, + y: { value: 3, units: 'Mm' }, + }, + source: { + expr: '60deg', + is_literal: true, + }, + }, + expect.any(Object), + true, + true, + ]) expect(events).toContainEqual({ type: 'update selected ids', data: { @@ -357,7 +381,7 @@ describe('dimensionTool', () => { }) expect(events).toContainEqual({ type: 'update hovered id', - data: { hoveredId: 31 }, + data: { hoveredId: 30 }, }) }) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 6bdf006a253..d9c10e60691 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -679,25 +679,6 @@ function getDraftKey(constraint: ApiAngleConstraint) { ].join(':') } -async function deleteDraftConstraint( - runtime: DraftRuntime, - context: DimensionToolContext -) { - if (runtime.draftConstraintId === null) { - return - } - - await context.rustContext.deleteObjects( - SKETCH_FILE_VERSION, - context.sketchId, - [runtime.draftConstraintId], - [], - jsAppSettings(context.rustContext.settingsActor), - false - ) - runtime.draftConstraintId = null -} - async function deleteInactivePreviewConstraint( context: DimensionToolContext, constraintId: number @@ -875,16 +856,33 @@ async function commitDraftAngleConstraint( try { deactivateRuntime(runtime) - await deleteDraftConstraint(runtime, context) - const result = await context.rustContext.addConstraint( - SKETCH_FILE_VERSION, - context.sketchId, - constraint, - jsAppSettings(context.rustContext.settingsActor), - true - ) + const settings = jsAppSettings(context.rustContext.settingsActor) + // This is normally never null, except for edge cases: + // - click is faster than draft preview creation + // - draft preview creation failed + const existingConstraintId = runtime.draftConstraintId + const result = + existingConstraintId === null + ? await context.rustContext.addConstraint( + SKETCH_FILE_VERSION, + context.sketchId, + constraint, + settings, + true + ) + : await context.rustContext.editAngleConstraint( + SKETCH_FILE_VERSION, + context.sketchId, + existingConstraintId, + constraint, + settings, + true, + true + ) - const constraintId = getConstraintIdFromResult(result) + const constraintId = + existingConstraintId ?? getConstraintIdFromResult(result) + runtime.draftConstraintId = null sendFinalResultToParent(self, result) sendParent(self, { type: 'clear draft entities' }) sendParent(self, { @@ -898,6 +896,7 @@ async function commitDraftAngleConstraint( dismissAngleSectorPrompt() self.send({ type: 'done' }) } catch (error) { + runtime.active = true toastSketchSolveError(error) } } From 6a714c04b298a57d3bac845d8792b880d3f9e8f0 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Mon, 15 Jun 2026 21:14:38 +0200 Subject: [PATCH 23/78] add support for right hand side 'angle' constraints in EditDistanceLabelPosition, EditAngleConstraint - letter is not used from P+C yet, but better to prepare for it just in case --- rust/kcl-lib/src/frontend.rs | 186 ++++++++++++++++++++++++++++++++--- 1 file changed, 172 insertions(+), 14 deletions(-) diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index d27bce23db1..ed0ff840fb2 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -5853,6 +5853,17 @@ fn source_ref_matches(ctx: &AstMutateContext, node_range: SourceRange, node_path } } +fn constraint_supports_label_position(part: &ast::BinaryPart) -> bool { + matches!( + part, + ast::BinaryPart::CallExpressionKw(call) + if matches!( + call.callee.name.name.as_str(), + DISTANCE_FN | HORIZONTAL_DISTANCE_FN | VERTICAL_DISTANCE_FN | RADIUS_FN | DIAMETER_FN | ANGLE_FN + ) + ) +} + fn process(ctx: &AstMutateContext, node: NodeMut) -> TraversalReturn> { match &ctx.command { AstMutateCommand::AddSketchBlockExprStmt { expr } => { @@ -6174,29 +6185,47 @@ fn process(ctx: &AstMutateContext, node: NodeMut) -> TraversalReturn { if let NodeMut::BinaryExpression(binary_expr) = node { - let ast::BinaryPart::CallExpressionKw(existing_call) = &binary_expr.left else { - return TraversalReturn::new_continue(()); - }; - if existing_call.callee.name.name != ANGLE_FN { - return TraversalReturn::new_continue(()); + let left_is_angle = matches!( + &binary_expr.left, + ast::BinaryPart::CallExpressionKw(existing_call) + if existing_call.callee.name.name == ANGLE_FN + ); + let right_is_angle = matches!( + &binary_expr.right, + ast::BinaryPart::CallExpressionKw(existing_call) + if existing_call.callee.name.name == ANGLE_FN + ); + + match (left_is_angle, right_is_angle) { + (true, _) => { + binary_expr.left = call.clone(); + binary_expr.right = value.clone(); + } + (false, true) => { + binary_expr.left = value.clone(); + binary_expr.right = call.clone(); + } + (false, false) => return TraversalReturn::new_continue(()), } - binary_expr.left = call.clone(); - binary_expr.right = value.clone(); return TraversalReturn::new_break(Ok(AstMutateCommandReturn::None)); } } AstMutateCommand::EditDistanceConstraintLabelPosition { label_position } => { if let NodeMut::BinaryExpression(binary_expr) = node { - let ast::BinaryPart::CallExpressionKw(call) = &mut binary_expr.left else { + let call = if constraint_supports_label_position(&binary_expr.left) { + let ast::BinaryPart::CallExpressionKw(call) = &mut binary_expr.left else { + unreachable!("constraint_supports_label_position already matched"); + }; + call + } else if constraint_supports_label_position(&binary_expr.right) { + let ast::BinaryPart::CallExpressionKw(call) = &mut binary_expr.right else { + unreachable!("constraint_supports_label_position already matched"); + }; + call + } else { return TraversalReturn::new_continue(()); }; - if !matches!( - call.callee.name.name.as_str(), - DISTANCE_FN | HORIZONTAL_DISTANCE_FN | VERTICAL_DISTANCE_FN | RADIUS_FN | DIAMETER_FN | ANGLE_FN - ) { - return TraversalReturn::new_continue(()); - } if let Some(label_arg) = call .arguments @@ -10907,6 +10936,73 @@ sketch(on = XY) { mock_ctx.close().await; } + #[tokio::test(flavor = "multi_thread")] + async fn test_edit_angle_constraint_label_position_with_call_on_right() { + let initial_source = "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + 60deg == angle(lines = [line1, line2]) +} +"; + + let program = Program::parse(initial_source).unwrap().0.unwrap(); + let mut frontend = FrontendState::new(); + let mock_ctx = ExecutorContext::new_mock(None).await; + let version = Version(0); + + frontend.program = program.clone(); + let outcome = mock_ctx.run_mock(&program, &MockConfig::default()).await.unwrap(); + frontend.update_state_after_exec(outcome, true); + let sketch_object = find_first_sketch_object(&frontend.scene_graph).unwrap(); + let sketch_id = sketch_object.id; + let sketch = expect_sketch(sketch_object); + let constraint_id = sketch.constraints[0]; + let label_position = Point2d { + x: Number { + value: 10.0, + units: NumericSuffix::Mm, + }, + y: Number { + value: 11.0, + units: NumericSuffix::Mm, + }, + }; + + let (src_delta, scene_delta) = frontend + .edit_distance_constraint_label_position( + &mock_ctx, + version, + sketch_id, + constraint_id, + label_position.clone(), + vec![], + ) + .await + .unwrap(); + assert_eq!( + src_delta.text.as_str(), + "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.46mm]) + 60deg == angle(lines = [line1, line2], labelPosition = [10mm, 11mm]) +} +" + ); + + let constraint_object = scene_delta.new_graph.objects.get(constraint_id.0).unwrap(); + let ObjectKind::Constraint { constraint } = &constraint_object.kind else { + panic!("Expected constraint object"); + }; + let Constraint::Angle(angle) = constraint else { + panic!("Expected angle constraint"); + }; + assert_eq!(angle.label_position, Some(label_position)); + + mock_ctx.close().await; + } + #[tokio::test(flavor = "multi_thread")] async fn test_edit_angle_constraint() { let initial_source = "\ @@ -10996,6 +11092,68 @@ sketch(on = XY) { mock_ctx.close().await; } + #[tokio::test(flavor = "multi_thread")] + async fn test_edit_angle_constraint_with_call_on_right() { + let initial_source = "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + 60deg == angle([line1, line2]) +} +"; + + let program = Program::parse(initial_source).unwrap().0.unwrap(); + let mut frontend = FrontendState::new(); + let mock_ctx = ExecutorContext::new_mock(None).await; + let version = Version(0); + + frontend.program = program.clone(); + let outcome = mock_ctx.run_mock(&program, &MockConfig::default()).await.unwrap(); + frontend.update_state_after_exec(outcome, true); + let sketch_object = find_first_sketch_object(&frontend.scene_graph).unwrap(); + let sketch_id = sketch_object.id; + let sketch = expect_sketch(sketch_object); + let constraint_id = sketch.constraints[0]; + let line1_id = *sketch.segments.get(2).unwrap(); + let line2_id = *sketch.segments.get(5).unwrap(); + + let (src_delta, _) = frontend + .edit_angle_constraint_with_options( + &mock_ctx, + version, + sketch_id, + constraint_id, + Angle { + lines: vec![line2_id, line1_id], + angle: Number { + value: 60.0, + units: NumericSuffix::Deg, + }, + sector: Some(3), + inverse: Some(false), + label_position: None, + source: Default::default(), + }, + EditAngleConstraintOptions { + commit_solved_initial_guesses: false, + }, + ) + .await + .unwrap(); + assert_eq!( + src_delta.text.as_str(), + "\ +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + 60deg == angle(lines = [line2, line1], sector = 3, inverse = false) +} +" + ); + + mock_ctx.close().await; + } + #[tokio::test(flavor = "multi_thread")] async fn test_edit_distance_constraint_label_position_preserves_anchor_segment_solution() { let initial_source = "\ From 80210704648fadcc0ba1482fb81cdd83a3c12335 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 17 Jun 2026 18:56:46 +0200 Subject: [PATCH 24/78] add dedicated toolbarToast for toasts appearing under the toolbar --- src/Toolbar.tsx | 26 +++++++ src/lib/toolbarToast.ts | 72 +++++++++++++++++++ .../sketchSolve/tools/dimensionTool.ts | 10 +-- 3 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 src/lib/toolbarToast.ts diff --git a/src/Toolbar.tsx b/src/Toolbar.tsx index f694dec50b1..751a30b3318 100644 --- a/src/Toolbar.tsx +++ b/src/Toolbar.tsx @@ -41,6 +41,7 @@ import { toolbarModeNameToKeymapScope, useToolbarConfig, } from '@src/lib/toolbar' +import { toolbarToastsSignal } from '@src/lib/toolbarToast' import { reportRejection } from '@src/lib/trap' import { type Platform, isArray } from '@src/lib/utils' import type { ModuleType } from '@src/lib/wasm_lib_wrapper' @@ -766,6 +767,7 @@ const Toolbar_ = memo( })}
+ {props.disableModelingForUnrenderedChanges && (

@@ -820,6 +822,30 @@ const Toolbar_ = memo( oldP.context?.currentTool === newP.context?.currentTool ) +const ToolbarToasts = memo(function ToolbarToasts() { + useSignals() + const toasts = toolbarToastsSignal.value + + if (toasts.length === 0) { + return null + } + + return ( + <> + {toasts.map((toast) => ( +

+ {toast.message} +
+ ))} + + ) +}) + interface ToolbarItemContentsProps extends React.PropsWithChildren { itemConfig: ToolbarItemResolved configCallbackProps: ToolbarItemCallbackProps diff --git a/src/lib/toolbarToast.ts b/src/lib/toolbarToast.ts new file mode 100644 index 00000000000..653b97f5377 --- /dev/null +++ b/src/lib/toolbarToast.ts @@ -0,0 +1,72 @@ +import { signal } from '@preact/signals-core' + +export type ToolbarToast = { + id: string + message: string +} + +type ToolbarToastOptions = { + id?: string + duration?: number +} + +type ToastToolbar = { + (message: string, options?: ToolbarToastOptions): string + dismiss: (id?: string) => void +} + +export const toolbarToastsSignal = signal([]) + +const dismissTimers = new Map>() +let nextToolbarToastId = 0 + +export const toastToolbar: ToastToolbar = Object.assign( + (message: string, options: ToolbarToastOptions = {}) => { + const id = options.id ?? `toolbar-toast-${++nextToolbarToastId}` + const duration = options.duration ?? 4000 + + clearDismissTimer(id) + + toolbarToastsSignal.value = [ + { id, message }, + ...toolbarToastsSignal.value.filter((toast) => toast.id !== id), + ] + + if (Number.isFinite(duration)) { + dismissTimers.set( + id, + setTimeout(() => dismissToolbarToast(id), duration) + ) + } + + return id + }, + { + dismiss: dismissToolbarToast, + } +) + +function dismissToolbarToast(id?: string) { + if (id === undefined) { + for (const toastId of dismissTimers.keys()) { + clearDismissTimer(toastId) + } + toolbarToastsSignal.value = [] + return + } + + clearDismissTimer(id) + toolbarToastsSignal.value = toolbarToastsSignal.value.filter( + (toast) => toast.id !== id + ) +} + +function clearDismissTimer(id: string) { + const timer = dismissTimers.get(id) + if (!timer) { + return + } + + clearTimeout(timer) + dismissTimers.delete(id) +} diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index d9c10e60691..77a256b8bec 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -12,6 +12,7 @@ import { baseUnitToNumericSuffix } from '@src/lang/wasm' import { SKETCH_FILE_VERSION } from '@src/lib/constants' import type RustContext from '@src/lib/rustContext' import { jsAppSettings } from '@src/lib/settings/settingsUtils' +import { toastToolbar } from '@src/lib/toolbarToast' import { roundOff } from '@src/lib/utils' import { TAU, @@ -33,7 +34,6 @@ import type { SketchSolveSelectionId, } from '@src/machines/sketchSolve/sketchSolveSelection' import type { BaseToolEvent } from '@src/machines/sketchSolve/tools/sharedToolTypes' -import toast from 'react-hot-toast' import { setup } from 'xstate' type DimensionToolContext = { @@ -192,18 +192,14 @@ function deactivateRuntime(runtime: DraftRuntime) { } function showAngleSectorPrompt() { - toast('Choose angle sector, then click to place the label.', { + toastToolbar('Move mouse to choose sector, then click to place label.', { id: ANGLE_SECTOR_PROMPT_TOAST_ID, duration: Number.POSITIVE_INFINITY, - position: 'top-center', - style: { - marginTop: '68px', - }, }) } function dismissAngleSectorPrompt() { - toast.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) + toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) } function getObjects(context: DimensionToolContext) { From 8dfd1c79192ad2d528a155a8289ad5d2bd5c3a77 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 21 Jun 2026 10:26:39 +0200 Subject: [PATCH 25/78] use new angleDimension() fn name for new angle constraint instead of reusing existing angle() --- rust/kcl-lib/src/execution/exec_ast.rs | 122 +++++++++++-------------- rust/kcl-lib/src/frontend.rs | 77 +++++++++------- rust/kcl-lib/src/std/constraints.rs | 81 ++++++++-------- rust/kcl-lib/src/std/mod.rs | 4 + rust/kcl-lib/std/solver.kcl | 21 ++++- 5 files changed, 158 insertions(+), 147 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 06496e82cd4..2ee5e6b16ce 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -271,7 +271,7 @@ fn intersection_of_initial_lines( let denom = vec2_cross(r, s); if denom.abs() <= 1e-9 { return Err(KclError::new_semantic(KclErrorDetails::new( - "angle(lines = ..., sector = ...) requires non-parallel lines".to_owned(), + "angleDimension(lines = ..., sector = ...) requires non-parallel lines".to_owned(), vec![range], ))); } @@ -381,7 +381,7 @@ fn representative_angle_endpoint( let endpoint_delta = if endpoint_index == 1 { end_delta } else { start_delta }; if vec2_len(endpoint_delta) <= 1e-9 { return Err(KclError::new_semantic(KclErrorDetails::new( - "angle(lines = ..., sector = ...) requires each line to have an endpoint away from the intersection" + "angleDimension(lines = ..., sector = ...) requires each line to have an endpoint away from the intersection" .to_owned(), vec![range], ))); @@ -6144,13 +6144,13 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_with_sector_allows_missing_unlabeled_input() { + async fn angle_dimension_with_sector_allows_missing_unlabeled_input() { parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle(lines = [line1, line2], sector = 2) == 60deg + angleDimension(lines = [line1, line2], sector = 2) == 60deg } "#, ) @@ -6159,43 +6159,34 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_defaults_to_sector_one() { - let result = parse_execute( + async fn angle_dimension_requires_sector() { + let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) - angle(lines = [line1, line2]) == 60deg + angleDimension(lines = [line1, line2]) == 60deg } "#, ) .await - .unwrap(); - let angle = result - .exec_state - .global - .root_module_artifacts - .scene_objects - .iter() - .find_map(|object| match &object.kind { - ObjectKind::Constraint { - constraint: crate::front::Constraint::Angle(angle), - } => Some(angle), - _ => None, - }) - .unwrap(); - assert_eq!(angle.sector, Some(1)); - assert_eq!(angle.inverse, Some(false)); + .unwrap_err(); + + assert!( + err.to_string() + .contains("The `angleDimension` function requires a keyword argument `sector`"), + "unexpected error: {err:?}" + ); } #[tokio::test(flavor = "multi_thread")] - async fn angle_accepts_label_position() { + async fn angle_dimension_accepts_label_position() { let result = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) - angle(lines = [line1, line2], sector = 1, labelPosition = [10mm, 11mm]) == 60deg + angleDimension(lines = [line1, line2], sector = 1, labelPosition = [10mm, 11mm]) == 60deg } "#, ) @@ -6220,16 +6211,16 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_accepts_all_four_sectors() { + async fn angle_dimension_accepts_all_four_sectors() { parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) - angle(lines = [line1, line2], sector = 1) == 60deg - angle(lines = [line1, line2], sector = 2) == 120deg - angle(lines = [line1, line2], sector = 3) == 60deg - angle(lines = [line1, line2], sector = 4) == 120deg + angleDimension(lines = [line1, line2], sector = 1) == 60deg + angleDimension(lines = [line1, line2], sector = 2) == 120deg + angleDimension(lines = [line1, line2], sector = 3) == 60deg + angleDimension(lines = [line1, line2], sector = 4) == 120deg } "#, ) @@ -6238,13 +6229,13 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_accepts_inverse_angle_for_sector() { + async fn angle_dimension_accepts_inverse_angle_for_sector() { let result = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) - angle(lines = [line1, line2], sector = 1, inverse = true) == 360deg - 60deg + angleDimension(lines = [line1, line2], sector = 1, inverse = true) == 360deg - 60deg } "#, ) @@ -6268,35 +6259,13 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_wins_when_both_are_supplied() { - let err = parse_execute( - r#" -sketch(on = XY) { - line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) - line2 = line(start = [var 4mm, var 0mm], end = [var 2mm, var 3mm]) - line3 = line(start = [var 0mm, var 1mm], end = [var 1mm, var 1mm]) - line4 = line(start = [var 0mm, var 2mm], end = [var 1mm, var 3mm]) - angle([line1, line2], lines = [line3, line4], sector = 5) == 60deg -} -"#, - ) - .await - .unwrap_err(); - - assert!( - err.to_string().contains("angle() sector must be 1, 2, 3, or 4"), - "unexpected error: {err:?}" - ); - } - - #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_rejects_invalid_sector() { + async fn angle_dimension_rejects_invalid_sector() { let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle(lines = [line1, line2], sector = 5) == 60deg + angleDimension(lines = [line1, line2], sector = 5) == 60deg } "#, ) @@ -6304,19 +6273,20 @@ sketch(on = XY) { .unwrap_err(); assert!( - err.to_string().contains("angle() sector must be 1, 2, 3, or 4"), + err.to_string() + .contains("angleDimension() sector must be 1, 2, 3, or 4"), "unexpected error: {err:?}" ); } #[tokio::test(flavor = "multi_thread")] - async fn angle_labelled_lines_rejects_parallel_lines() { + async fn angle_dimension_rejects_parallel_lines() { let err = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 4mm, var 1mm]) - angle(lines = [line1, line2], sector = 2) == 60deg + angleDimension(lines = [line1, line2], sector = 2) == 60deg } "#, ) @@ -6325,34 +6295,44 @@ sketch(on = XY) { assert!( err.to_string() - .contains("angle(lines = ..., sector = ...) requires non-parallel lines"), + .contains("angleDimension(lines = ..., sector = ...) requires non-parallel lines"), "unexpected error: {err:?}" ); } #[tokio::test(flavor = "multi_thread")] - async fn angle_sector_requires_labelled_lines() { - let err = parse_execute( + async fn angle_accepts_label_position() { + let result = parse_execute( r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) - angle([line1, line2], sector = 2) == 60deg + angle([line1, line2], labelPosition = [10mm, 11mm]) == 60deg } "#, ) .await - .unwrap_err(); - - assert!( - err.to_string() - .contains("angle() sector and inverse require the labelled lines argument"), - "unexpected error: {err:?}" - ); + .unwrap(); + let angle = result + .exec_state + .global + .root_module_artifacts + .scene_objects + .iter() + .find_map(|object| match &object.kind { + ObjectKind::Constraint { + constraint: crate::front::Constraint::Angle(angle), + } => Some(angle), + _ => None, + }) + .unwrap(); + let label_position = angle.label_position.as_ref().unwrap(); + assert_eq!(label_position.x.value, 10.0); + assert_eq!(label_position.y.value, 11.0); } #[tokio::test(flavor = "multi_thread")] - async fn angle_requires_unlabeled_or_labelled_lines() { + async fn angle_requires_unlabeled_lines() { parse_execute( r#" sketch(on = XY) { diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index 2c5947d5ff8..9b2e6457689 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -143,6 +143,7 @@ const DIAMETER_FN: &str = "diameter"; const DISTANCE_FN: &str = "distance"; const FIXED_FN: &str = "fixed"; const ANGLE_FN: &str = "angle"; +const ANGLE_DIMENSION_FN: &str = "angleDimension"; const ANGLE_LINES_PARAM: &str = "lines"; const ANGLE_SECTOR_PARAM: &str = "sector"; const ANGLE_INVERSE_PARAM: &str = "inverse"; @@ -3842,8 +3843,12 @@ impl FrontendState { non_code_meta: Default::default(), }))); - let has_explicit_angle_mode = angle.sector.is_some() || angle.inverse.is_some(); - let mut arguments = if has_explicit_angle_mode { + if angle.inverse == Some(true) && angle.sector.is_none() { + return Err(KclError::refactor("Angle inverse requires an angle sector".to_owned())); + } + + let uses_angle_dimension = angle.sector.is_some(); + let mut arguments = if uses_angle_dimension { vec![ast::LabeledArg { label: Some(ast::Identifier::new(ANGLE_LINES_PARAM)), arg: lines_ast.clone(), @@ -3866,12 +3871,12 @@ impl FrontendState { }); } - if let Some(inverse) = angle.inverse { + if angle.inverse == Some(true) { arguments.push(ast::LabeledArg { label: Some(ast::Identifier::new(ANGLE_INVERSE_PARAM)), arg: ast::Expr::Literal(Box::new(ast::Node::no_src(ast::Literal { - value: ast::LiteralValue::Bool(inverse), - raw: inverse.to_string(), + value: ast::LiteralValue::Bool(true), + raw: true.to_string(), digest: None, }))), }); @@ -3885,8 +3890,12 @@ impl FrontendState { } let call = ast::BinaryPart::CallExpressionKw(Box::new(ast::Node::no_src(ast::CallExpressionKw { - callee: ast::Node::no_src(ast_sketch2_name(ANGLE_FN)), - unlabeled: (!has_explicit_angle_mode).then_some(lines_ast), + callee: ast::Node::no_src(ast_sketch2_name(if uses_angle_dimension { + ANGLE_DIMENSION_FN + } else { + ANGLE_FN + })), + unlabeled: (!uses_angle_dimension).then_some(lines_ast), arguments, digest: None, non_code_meta: Default::default(), @@ -6000,14 +6009,27 @@ fn source_ref_matches(ctx: &AstMutateContext, node_range: SourceRange, node_path } } +fn is_angle_constraint_call_name(name: &str) -> bool { + matches!(name, ANGLE_FN | ANGLE_DIMENSION_FN) +} + +fn is_constraint_call_name(name: &str) -> bool { + matches!( + name, + DISTANCE_FN + | HORIZONTAL_DISTANCE_FN + | VERTICAL_DISTANCE_FN + | RADIUS_FN + | DIAMETER_FN + | ANGLE_FN + | ANGLE_DIMENSION_FN + ) +} + fn constraint_supports_label_position(part: &ast::BinaryPart) -> bool { matches!( part, - ast::BinaryPart::CallExpressionKw(call) - if matches!( - call.callee.name.name.as_str(), - DISTANCE_FN | HORIZONTAL_DISTANCE_FN | VERTICAL_DISTANCE_FN | RADIUS_FN | DIAMETER_FN | ANGLE_FN - ) + ast::BinaryPart::CallExpressionKw(call) if is_constraint_call_name(call.callee.name.name.as_str()) ) } @@ -6315,11 +6337,7 @@ fn process(ctx: &AstMutateContext, node: NodeMut) -> TraversalReturn TraversalReturn Result { - let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); - let sector_ty = RuntimeType::count(); - let label_position = get_constraint_label_position(exec_state, &args, "angle")?; - let (lines, mode): (Vec, AngleConstraintMode) = - if let Some(lines) = args.get_kw_arg_opt("lines", &line_array_ty, exec_state)? { - let sector = args - .get_kw_arg_opt::("sector", §or_ty, exec_state)? - .unwrap_or_else(|| TyF64::count(1.0)); - let inverse = args - .get_kw_arg_opt::("inverse", &RuntimeType::bool(), exec_state)? - .unwrap_or(false); - ( - lines, - AngleConstraintMode::PointsAtAngle { - sector: angle_sector(sector, args.source_range)?, - inverse, - }, - ) - } else { - if args - .get_kw_arg_opt::("sector", §or_ty, exec_state)? - .is_some() - || args - .get_kw_arg_opt::("inverse", &RuntimeType::bool(), exec_state)? - .is_some() - { - return Err(KclError::new_semantic(KclErrorDetails::new( - "angle() sector and inverse require the labelled lines argument".to_owned(), - vec![args.source_range], - ))); - } - ( - args.get_unlabeled_kw_arg("lines", &line_array_ty, exec_state)?, - AngleConstraintMode::LinesAtAngle, - ) - }; - +fn angle_constraint_from_lines( + lines: Vec, + mode: AngleConstraintMode, + label_position: Option>, + function_name: &str, + args: &Args, +) -> Result { let [line0, line1]: [KclValue; 2] = lines.try_into().map_err(|_| { KclError::new_semantic(KclErrorDetails::new( "must have two input lines".to_owned(), vec![args.source_range], )) })?; - let line0 = constrainable_line_from_kcl_value(&line0, "angle", args.source_range)?; - let line1 = constrainable_line_from_kcl_value(&line1, "angle", args.source_range)?; + let line0 = constrainable_line_from_kcl_value(&line0, function_name, args.source_range)?; + let line1 = constrainable_line_from_kcl_value(&line1, function_name, args.source_range)?; let sketch_constraint = SketchConstraint { kind: SketchConstraintKind::Angle { @@ -5200,6 +5169,34 @@ pub async fn angle(exec_state: &mut ExecState, args: Args) -> Result Result { + let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); + let label_position = get_constraint_label_position(exec_state, &args, "angle")?; + let lines = args.get_unlabeled_kw_arg("lines", &line_array_ty, exec_state)?; + angle_constraint_from_lines(lines, AngleConstraintMode::LinesAtAngle, label_position, "angle", &args) +} + +pub async fn angle_dimension(exec_state: &mut ExecState, args: Args) -> Result { + let line_array_ty = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Any)), ArrayLen::Known(2)); + let sector_ty = RuntimeType::count(); + let label_position = get_constraint_label_position(exec_state, &args, "angleDimension")?; + let lines = args.get_kw_arg("lines", &line_array_ty, exec_state)?; + let sector = args.get_kw_arg::("sector", §or_ty, exec_state)?; + let inverse = args + .get_kw_arg_opt::("inverse", &RuntimeType::bool(), exec_state)? + .unwrap_or(false); + angle_constraint_from_lines( + lines, + AngleConstraintMode::PointsAtAngle { + sector: angle_sector(sector, "angleDimension", args.source_range)?, + inverse, + }, + label_position, + "angleDimension", + &args, + ) +} + async fn lines_at_angle( angle_kind: LinesAtAngleKind, exec_state: &mut ExecState, diff --git a/rust/kcl-lib/src/std/mod.rs b/rust/kcl-lib/src/std/mod.rs index 3d94dddb76d..3eb1f0620a0 100644 --- a/rust/kcl-lib/src/std/mod.rs +++ b/rust/kcl-lib/src/std/mod.rs @@ -656,6 +656,10 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp |e, a| Box::pin(crate::std::constraints::angle(e, a).map(|r| r.map(KclValue::continue_))), StdFnProps::default("std::solver::angle"), ), + ("solver", "angleDimension") => ( + |e, a| Box::pin(crate::std::constraints::angle_dimension(e, a).map(|r| r.map(KclValue::continue_))), + StdFnProps::default("std::solver::angleDimension"), + ), ("solver", "tangent") => ( |e, a| Box::pin(crate::std::constraints::tangent(e, a).map(|r| r.map(KclValue::continue_))), StdFnProps::default("std::solver::tangent"), diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index 19da4761266..2ea463bad4e 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -446,10 +446,27 @@ export fn perpendicular( export fn angle( /// The two line segments whose relative angle should match the value set with `==`. @input?: [Segment; 2], + /// The desired position of the constraint label. + labelPosition?: Point2d, +) {} + +/// Constrain a specific angle dimension sector between two lines. +/// +/// ```kcl,sketchSolve +/// profile = sketch(on = XY) { +/// line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) +/// line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) +/// angleDimension(lines = [line1, line2], sector = 1) == 60deg +/// } +/// +/// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2) +/// ``` +@(impl = std_rust_constraint, feature_tree = true) +export fn angleDimension( /// The two line segments whose selected angle sector should match the value set with `==`. - lines?: [Segment; 2], + lines: [Segment; 2], /// Which of the four angle sectors to constrain, numbered around the line intersection. - sector?: number(Count) = 1, + sector: number(Count), /// Whether to constrain the inverse of the selected sector. inverse?: bool = false, /// The desired position of the constraint label. From 853789fcc5e1728ff2c3746809b1c44b35052af1 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 23 Jun 2026 15:05:26 +0200 Subject: [PATCH 26/78] move labelPosition when moving lines --- .../sketchSolve/tools/moveTool/moveTool.ts | 89 ++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.ts index 0c5baf5eff7..918eb5439ca 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.ts @@ -22,7 +22,9 @@ import { applyVectorToPoint2D } from '@src/lib/kclHelpers' import { jsAppSettings } from '@src/lib/settings/settingsUtils' import type { DeepPartial } from '@src/lib/types' import { isArray, roundOff } from '@src/lib/utils' -import { distance2d } from '@src/lib/utils2d' +import { distance2d, polar2d } from '@src/lib/utils2d' +import { calculateArcRenderInput } from '@src/machines/sketchSolve/constraints/AngleConstraintBuilder' +import { getArcLabelOffset } from '@src/machines/sketchSolve/constraints/ArcDimensionLine' import { isConstraintHoverPopup } from '@src/machines/sketchSolve/constraints/InvisibleConstraintSpriteBuilder' import { axisConstraintIncludesOrigin, @@ -408,6 +410,15 @@ function buildConstraintLabelEditsForMovedSegments({ }) } + if (isAngleConstraint(obj)) { + return buildAngleLabelEditsForMovedSegments({ + obj, + objectsBeforeDrag, + objectsAfterDrag, + units, + }) + } + return [] }) } @@ -522,6 +533,76 @@ function buildCircularLabelEditsForMovedSegments({ ] } +function buildAngleLabelEditsForMovedSegments({ + obj, + objectsBeforeDrag, + objectsAfterDrag, + units, +}: { + obj: ApiObject + objectsBeforeDrag: ApiObject[] + objectsAfterDrag: ApiObject[] + units: NumericSuffix +}): ConstraintLabelEdit[] { + if (!isAngleConstraint(obj)) { + return [] + } + + const { labelPosition } = obj.kind.constraint + if (!labelPosition) { + return [] + } + + const afterObj = objectsAfterDrag[obj.id] + if (!isAngleConstraint(afterObj)) { + return [] + } + + const beforeArc = calculateArcRenderInput(obj, objectsBeforeDrag, 1) + const afterArc = calculateArcRenderInput(afterObj, objectsAfterDrag, 1) + if (!beforeArc || !afterArc || beforeArc.labelAngle === undefined) { + return [] + } + + if ( + !lineSegmentMoved(beforeArc.line1, afterArc.line1) && + !lineSegmentMoved(beforeArc.line2, afterArc.line2) + ) { + return [] + } + + const labelRadius = new Vector2( + labelPosition.x.value, + labelPosition.y.value + ).distanceTo(new Vector2(beforeArc.center[0], beforeArc.center[1])) + const labelOffset = getArcLabelOffset( + beforeArc.startAngle, + beforeArc.sweepAngle, + beforeArc.labelAngle + ) + const labelAngle = afterArc.startAngle + labelOffset + const transformedLabel = new Vector2( + ...polar2d(afterArc.center, labelRadius, labelAngle) + ) + + return [ + { + constraintId: obj.id, + labelPosition: buildConstraintLabelPosition(transformedLabel, units), + }, + ] +} + +function lineSegmentMoved( + before: readonly [Coords2d, Coords2d], + after: readonly [Coords2d, Coords2d] +) { + return ( + distance2d(before[0], after[0]) > 1e-4 || + distance2d(before[1], after[1]) > 1e-4 + ) +} + function getDistanceConstraintPointPosition( point: number | 'ORIGIN', objects: ApiObject[] @@ -1513,9 +1594,11 @@ export function createOnDragCallback({ if (result && isActiveDragSession()) { if (!hasSketchSolveIssues(result.sceneGraphDelta)) { let appliedConstraintLabelEdits: ConstraintLabelEdit[] = [] + const labelEditBaselineObjects = + getDragStartOutcome()?.sceneGraphDelta.new_graph.objects ?? objects const constraintLabelEdits = buildConstraintLabelEditsForMovedSegments({ - objectsBeforeDrag: objects, + objectsBeforeDrag: labelEditBaselineObjects, objectsAfterDrag: result.sceneGraphDelta.new_graph.objects, units, }).filter(({ constraintId }) => { @@ -1523,7 +1606,7 @@ export function createOnDragCallback({ return true } - const constraint = objects[constraintId] + const constraint = labelEditBaselineObjects[constraintId] return ( !isRadiusConstraint(constraint) && !isDiameterConstraint(constraint) From 449357d02bfbb97b2ee8e96e25b32e70d3e03322 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 23 Jun 2026 22:16:13 +0200 Subject: [PATCH 27/78] move math helpers to utils --- rust/kcl-lib/src/execution/exec_ast.rs | 30 ++++++-------------------- rust/kcl-lib/src/std/utils.rs | 24 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 74ade74fe65..392c3de601c 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -117,6 +117,12 @@ use crate::std::shapes::SketchOrSurface; use crate::std::sketch::ensure_sketch_plane_in_engine; use crate::std::solver::SOLVER_CONVERGENCE_TOLERANCE; use crate::std::solver::create_segments_in_engine; +use crate::std::utils::vec2_add; +use crate::std::utils::vec2_cross; +use crate::std::utils::vec2_dot; +use crate::std::utils::vec2_len; +use crate::std::utils::vec2_scale; +use crate::std::utils::vec2_sub; fn internal_err(message: impl Into, range: impl Into) -> KclError { KclError::new_internal(KclErrorDetails::new(message.into(), vec![range.into()])) @@ -236,30 +242,6 @@ fn push_hidden_sketch_point( )) } -fn vec2_sub(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { - [a[0] - b[0], a[1] - b[1]] -} - -fn vec2_add(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { - [a[0] + b[0], a[1] + b[1]] -} - -fn vec2_scale(a: [f64; 2], scale: f64) -> [f64; 2] { - [a[0] * scale, a[1] * scale] -} - -fn vec2_cross(a: [f64; 2], b: [f64; 2]) -> f64 { - a[0] * b[1] - a[1] * b[0] -} - -fn vec2_dot(a: [f64; 2], b: [f64; 2]) -> f64 { - a[0] * b[0] + a[1] * b[1] -} - -fn vec2_len(a: [f64; 2]) -> f64 { - libm::hypot(a[0], a[1]) -} - fn intersection_of_initial_lines( line0: ([f64; 2], [f64; 2]), line1: ([f64; 2], [f64; 2]), diff --git a/rust/kcl-lib/src/std/utils.rs b/rust/kcl-lib/src/std/utils.rs index dccb6ee89db..6cb13054fbf 100644 --- a/rust/kcl-lib/src/std/utils.rs +++ b/rust/kcl-lib/src/std/utils.rs @@ -55,6 +55,30 @@ pub(crate) fn distance(a: Coords2d, b: Coords2d) -> f64 { ((b[0] - a[0]).squared() + (b[1] - a[1]).squared()).sqrt() } +pub(crate) fn vec2_sub(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { + [a[0] - b[0], a[1] - b[1]] +} + +pub(crate) fn vec2_add(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { + [a[0] + b[0], a[1] + b[1]] +} + +pub(crate) fn vec2_scale(a: [f64; 2], scale: f64) -> [f64; 2] { + [a[0] * scale, a[1] * scale] +} + +pub(crate) fn vec2_cross(a: [f64; 2], b: [f64; 2]) -> f64 { + a[0] * b[1] - a[1] * b[0] +} + +pub(crate) fn vec2_dot(a: [f64; 2], b: [f64; 2]) -> f64 { + a[0] * b[0] + a[1] * b[1] +} + +pub(crate) fn vec2_len(a: [f64; 2]) -> f64 { + libm::hypot(a[0], a[1]) +} + /// Get the angle between these points pub(crate) fn between(a: Coords2d, b: Coords2d) -> Angle { let x = b[0] - a[0]; From df9ff39be1fa1a8ece888aa8f5a1802a36d2dfe5 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 23 Jun 2026 22:39:42 +0200 Subject: [PATCH 28/78] clean up math utils functions --- rust/kcl-lib/src/execution/exec_ast.rs | 34 ++++++-------------------- rust/kcl-lib/src/std/utils.rs | 21 ++++++++++++++++ 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 392c3de601c..8572b679aa5 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -117,11 +117,9 @@ use crate::std::shapes::SketchOrSurface; use crate::std::sketch::ensure_sketch_plane_in_engine; use crate::std::solver::SOLVER_CONVERGENCE_TOLERANCE; use crate::std::solver::create_segments_in_engine; -use crate::std::utils::vec2_add; -use crate::std::utils::vec2_cross; +use crate::std::utils::intersect_lines_2d; use crate::std::utils::vec2_dot; use crate::std::utils::vec2_len; -use crate::std::utils::vec2_scale; use crate::std::utils::vec2_sub; fn internal_err(message: impl Into, range: impl Into) -> KclError { @@ -242,27 +240,6 @@ fn push_hidden_sketch_point( )) } -fn intersection_of_initial_lines( - line0: ([f64; 2], [f64; 2]), - line1: ([f64; 2], [f64; 2]), - range: SourceRange, -) -> Result<[f64; 2], KclError> { - let p = line0.0; - let r = vec2_sub(line0.1, line0.0); - let q = line1.0; - let s = vec2_sub(line1.1, line1.0); - let denom = vec2_cross(r, s); - if denom.abs() <= 1e-9 { - return Err(KclError::new_semantic(KclErrorDetails::new( - "angleDimension(lines = ..., sector = ...) requires non-parallel lines".to_owned(), - vec![range], - ))); - } - - let t = vec2_cross(vec2_sub(q, p), s) / denom; - Ok(vec2_add(p, vec2_scale(r, t))) -} - fn front_angle_sector(sector: AngleSector) -> u8 { match sector { AngleSector::One => 1, @@ -4014,8 +3991,13 @@ impl Node { range, "angle line1", )?; - let initial_vertex = - intersection_of_initial_lines(initial_line0, initial_line1, range)?; + let Some(initial_vertex) = intersect_lines_2d(initial_line0, initial_line1) else { + return Err(KclError::new_semantic(KclErrorDetails::new( + "angleDimension(lines = ..., sector = ...) requires non-parallel lines" + .to_owned(), + vec![range], + ))); + }; let (line0_representative, line0_direction) = representative_angle_endpoint(line0, initial_line0, initial_vertex, range)?; let (line1_representative, line1_direction) = diff --git a/rust/kcl-lib/src/std/utils.rs b/rust/kcl-lib/src/std/utils.rs index 6cb13054fbf..e4cfc5db409 100644 --- a/rust/kcl-lib/src/std/utils.rs +++ b/rust/kcl-lib/src/std/utils.rs @@ -79,6 +79,27 @@ pub(crate) fn vec2_len(a: [f64; 2]) -> f64 { libm::hypot(a[0], a[1]) } +/// Intersect two infinite 2D lines. +/// +/// Each line is represented by two `[x, y]` points on the line. The points are +/// not treated as finite segment endpoints. +/// +/// Returns the intersection point, or `None` when the lines are parallel or +/// nearly parallel. +pub(crate) fn intersect_lines_2d(line0: ([f64; 2], [f64; 2]), line1: ([f64; 2], [f64; 2])) -> Option<[f64; 2]> { + let p = line0.0; + let r = vec2_sub(line0.1, line0.0); + let q = line1.0; + let s = vec2_sub(line1.1, line1.0); + let denom = vec2_cross(r, s); + if denom.abs() <= 1e-9 { + return None; + } + + let t = vec2_cross(vec2_sub(q, p), s) / denom; + Some(vec2_add(p, vec2_scale(r, t))) +} + /// Get the angle between these points pub(crate) fn between(a: Coords2d, b: Coords2d) -> Angle { let x = b[0] - a[0]; From 22d7e60fda02681702daa66ab330be121557367f Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 14:57:18 +0200 Subject: [PATCH 29/78] better branching to avoid impossible error case --- rust/kcl-lib/src/execution/exec_ast.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 8572b679aa5..6fc51abb0f8 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -391,6 +391,11 @@ struct PointsAtAngleLineData { angle_kind: ezpz::datatypes::AngleKind, } +enum AngleConstraintLowering { + LinesAtAngle, + PointsAtAngle(PointsAtAngleLineData), +} + fn push_points_at_angle_for_lines( sketch_block_state: &mut SketchBlockState, sketch_var_ty: NumericType, @@ -3962,8 +3967,8 @@ impl Node { return Err(internal_err(message, self)); } }; - let points_at_angle_data = match *mode { - AngleConstraintMode::LinesAtAngle => None, + let angle_lowering = match *mode { + AngleConstraintMode::LinesAtAngle => AngleConstraintLowering::LinesAtAngle, AngleConstraintMode::PointsAtAngle { sector, inverse } => { let sketch_vars = exec_state .mod_local @@ -4009,7 +4014,7 @@ impl Node { [line0_direction, line1_direction], desired_angle, )); - Some(PointsAtAngleLineData { + AngleConstraintLowering::PointsAtAngle(PointsAtAngleLineData { initial_vertex, representative_points: [line0_representative, line1_representative], angle_kind, @@ -4024,15 +4029,15 @@ impl Node { debug_assert!(false, "{}", &message); return Err(internal_err(message, self)); }; - match (*mode, points_at_angle_data) { - (AngleConstraintMode::LinesAtAngle, None) => { + match angle_lowering { + AngleConstraintLowering::LinesAtAngle => { sketch_block_state.solver_constraints.push(Constraint::LinesAtAngle( datum_line_from_constrainable(line0, range)?, datum_line_from_constrainable(line1, range)?, ezpz::datatypes::AngleKind::Other(desired_angle), )); } - (AngleConstraintMode::PointsAtAngle { .. }, Some(points_at_angle_data)) => { + AngleConstraintLowering::PointsAtAngle(points_at_angle_data) => { push_points_at_angle_for_lines( sketch_block_state, sketch_var_ty, @@ -4041,11 +4046,6 @@ impl Node { range, )? } - _ => { - let message = "Invalid angle constraint lowering state".to_owned(); - debug_assert!(false, "{}", &message); - return Err(internal_err(message, self)); - } } use crate::execution::Artifact; use crate::execution::CodeRef; From c47f151d7918ee8ef79937211200a3ca502bc552 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 15:45:45 +0200 Subject: [PATCH 30/78] math fn updates --- rust/kcl-lib/src/std/utils.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rust/kcl-lib/src/std/utils.rs b/rust/kcl-lib/src/std/utils.rs index e4cfc5db409..f457737ddb3 100644 --- a/rust/kcl-lib/src/std/utils.rs +++ b/rust/kcl-lib/src/std/utils.rs @@ -55,27 +55,27 @@ pub(crate) fn distance(a: Coords2d, b: Coords2d) -> f64 { ((b[0] - a[0]).squared() + (b[1] - a[1]).squared()).sqrt() } -pub(crate) fn vec2_sub(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { +pub(crate) fn vec2_sub(a: Coords2d, b: Coords2d) -> Coords2d { [a[0] - b[0], a[1] - b[1]] } -pub(crate) fn vec2_add(a: [f64; 2], b: [f64; 2]) -> [f64; 2] { +pub(crate) fn vec2_add(a: Coords2d, b: Coords2d) -> Coords2d { [a[0] + b[0], a[1] + b[1]] } -pub(crate) fn vec2_scale(a: [f64; 2], scale: f64) -> [f64; 2] { +pub(crate) fn vec2_scale(a: Coords2d, scale: f64) -> Coords2d { [a[0] * scale, a[1] * scale] } -pub(crate) fn vec2_cross(a: [f64; 2], b: [f64; 2]) -> f64 { +pub(crate) fn vec2_cross(a: Coords2d, b: Coords2d) -> f64 { a[0] * b[1] - a[1] * b[0] } -pub(crate) fn vec2_dot(a: [f64; 2], b: [f64; 2]) -> f64 { +pub(crate) fn vec2_dot(a: Coords2d, b: Coords2d) -> f64 { a[0] * b[0] + a[1] * b[1] } -pub(crate) fn vec2_len(a: [f64; 2]) -> f64 { +pub(crate) fn vec2_len(a: Coords2d) -> f64 { libm::hypot(a[0], a[1]) } @@ -86,7 +86,7 @@ pub(crate) fn vec2_len(a: [f64; 2]) -> f64 { /// /// Returns the intersection point, or `None` when the lines are parallel or /// nearly parallel. -pub(crate) fn intersect_lines_2d(line0: ([f64; 2], [f64; 2]), line1: ([f64; 2], [f64; 2])) -> Option<[f64; 2]> { +pub(crate) fn intersect_lines_2d(line0: (Coords2d, Coords2d), line1: (Coords2d, Coords2d)) -> Option { let p = line0.0; let r = vec2_sub(line0.1, line0.0); let q = line1.0; From e657848ce0c12db1f893ec172d5669b745c1f072 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 15:49:29 +0200 Subject: [PATCH 31/78] simplify distance fn --- rust/kcl-lib/src/std/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kcl-lib/src/std/utils.rs b/rust/kcl-lib/src/std/utils.rs index f457737ddb3..1838e54ec7b 100644 --- a/rust/kcl-lib/src/std/utils.rs +++ b/rust/kcl-lib/src/std/utils.rs @@ -52,7 +52,7 @@ pub(crate) fn point_3d_to_mm(p: [TyF64; 3]) -> [f64; 3] { /// Get the distance between two points. pub(crate) fn distance(a: Coords2d, b: Coords2d) -> f64 { - ((b[0] - a[0]).squared() + (b[1] - a[1]).squared()).sqrt() + vec2_len(vec2_sub(b, a)) } pub(crate) fn vec2_sub(a: Coords2d, b: Coords2d) -> Coords2d { From 4b22a85ea208f93580d457b09efea47825d7a036 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 16:46:45 +0200 Subject: [PATCH 32/78] math refactors --- src/lib/utils2d.ts | 13 +++++++++++++ .../constraints/AngleConstraintBuilder.ts | 14 ++++---------- .../sketchSolve/constraints/ArcDimensionLine.ts | 8 ++------ src/machines/sketchSolve/tools/dimensionTool.ts | 13 ++----------- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/lib/utils2d.ts b/src/lib/utils2d.ts index 28c21405b09..5b5fc2c0549 100644 --- a/src/lib/utils2d.ts +++ b/src/lib/utils2d.ts @@ -7,6 +7,19 @@ export function deg2Rad(deg: number): number { export const TAU = Math.PI * 2 +// Normalize a radian angle into [0, 2PI). +export function normalizeAngle(angle: number) { + return ((angle % TAU) + TAU) % TAU +} + +// Returns the counter-clockwise angular distance from start to end in radians, +// normalized into [0, 2PI). +export function getCcwSweep(start: Coords2d, end: Coords2d) { + return normalizeAngle( + Math.atan2(end[1], end[0]) - Math.atan2(start[1], start[0]) + ) +} + export function getTangentPointFromPreviousArc( lastArcCenter: Coords2d, lastArcCCW: boolean, diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index c81871a8e64..a5d318b62fd 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -6,13 +6,14 @@ import { DISTANCE_CONSTRAINT_BODY } from '@src/clientSideScene/sceneConstants' import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { Coords2d } from '@src/lang/util' import { - TAU, addVec, distance2d, dot2d, + getCcwSweep, getPolarAngle2d, intersectRanges, lerp, + normalizeAngle, normalizeVec, rotateVec2d, scaleVec, @@ -199,8 +200,7 @@ export function calculateArcRenderInput( export function normalizeAngleRad(angle: ApiNumber) { const angleRadians = angle.units === 'Rad' ? angle.value : (angle.value * Math.PI) / 180 - const normalized = ((angleRadians % TAU) + TAU) % TAU - return normalized + return normalizeAngle(angleRadians) } // Major angles are ones > 180deg @@ -245,7 +245,7 @@ function calculateExplicitArcRenderInput( const radius = getAngleArcRadius(explicitLabelPosition, center, defaultRadius) const startVector = scaleVec(start.dir, radius) const startAngle = Math.atan2(startVector[1], startVector[0]) - const sweepAngle = ccwSweepBetweenDirections(start.dir, end.dir) + const sweepAngle = getCcwSweep(start.dir, end.dir) const defaultLabelPosition = addVec( center, rotateVec2d(startVector, sweepAngle / 2) @@ -323,12 +323,6 @@ function angleSectorBoundaries( } } -function ccwSweepBetweenDirections(start: Coords2d, end: Coords2d) { - const startAngle = Math.atan2(start[1], start[0]) - const endAngle = Math.atan2(end[1], end[0]) - return (((endAngle - startAngle) % TAU) + TAU) % TAU -} - function calculateExplicitArcRadius( line1: LineSegment, line2: LineSegment, diff --git a/src/machines/sketchSolve/constraints/ArcDimensionLine.ts b/src/machines/sketchSolve/constraints/ArcDimensionLine.ts index 687ab10d392..797daa6964e 100644 --- a/src/machines/sketchSolve/constraints/ArcDimensionLine.ts +++ b/src/machines/sketchSolve/constraints/ArcDimensionLine.ts @@ -10,7 +10,7 @@ import { import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import type { Coords2d } from '@src/lang/util' import { getResolvedTheme } from '@src/lib/theme' -import { TAU, dot2d, polar2d, subVec } from '@src/lib/utils2d' +import { TAU, dot2d, normalizeAngle, polar2d, subVec } from '@src/lib/utils2d' import { createArcPositions } from '@src/machines/sketchSolve/arcPositions' import { CONSTRAINT_COLOR, @@ -165,7 +165,7 @@ export function getArcLabelOffset( return sweep * 0.5 } - const offset = normalizePositiveAngle(labelAngle - startAngle) + const offset = normalizeAngle(labelAngle - startAngle) if (offset <= sweep + ANGLE_EPSILON) { return Math.min(offset, sweep) } @@ -203,10 +203,6 @@ function compactArcSections(sections: [number, number][]) { return sections.filter(([start, end]) => end - start > ANGLE_EPSILON) } -function normalizePositiveAngle(angle: number) { - return ((angle % TAU) + TAU) % TAU -} - function updateArc( arc: Line2, center: Coords2d, diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 77a256b8bec..cc2e2f0f88b 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -15,9 +15,10 @@ import { jsAppSettings } from '@src/lib/settings/settingsUtils' import { toastToolbar } from '@src/lib/toolbarToast' import { roundOff } from '@src/lib/utils' import { - TAU, dot2d, + getCcwSweep, length2d, + normalizeAngle, normalizeVec, scaleVec, subVec, @@ -355,16 +356,6 @@ function getInitialAngleLineSelections( ] } -function normalizeAngle(angle: number) { - return ((angle % TAU) + TAU) % TAU -} - -function getCcwSweep(start: Coords2d, end: Coords2d) { - return normalizeAngle( - Math.atan2(end[1], end[0]) - Math.atan2(start[1], start[0]) - ) -} - function isDirectionInSector( direction: Coords2d, start: Coords2d, From 05e5b0f64ec6c110b199f4cbc64626cc3ddcb8d6 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 16:49:15 +0200 Subject: [PATCH 33/78] inline reverseDirection --- src/machines/sketchSolve/tools/dimensionTool.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index cc2e2f0f88b..42f312e0415 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -366,10 +366,6 @@ function isDirectionInSector( ) } -function reverseDirection(direction: Coords2d): Coords2d { - return scaleVec(direction, -1) -} - function getClickedRayKey( lineIndex: 0 | 1, direction: RayDirection @@ -393,16 +389,16 @@ export function getAngleSectorRays( case 2: return [ angleContext.line1Direction, - reverseDirection(angleContext.line0Direction), + scaleVec(angleContext.line0Direction, -1), ] case 3: return [ - reverseDirection(angleContext.line0Direction), - reverseDirection(angleContext.line1Direction), + scaleVec(angleContext.line0Direction, -1), + scaleVec(angleContext.line1Direction, -1), ] case 4: return [ - reverseDirection(angleContext.line1Direction), + scaleVec(angleContext.line1Direction, -1), angleContext.line0Direction, ] } @@ -445,12 +441,12 @@ function getAngleRays( { key: 'line0Forward', direction: angleContext.line0Direction }, { key: 'line0Reverse', - direction: reverseDirection(angleContext.line0Direction), + direction: scaleVec(angleContext.line0Direction, -1), }, { key: 'line1Forward', direction: angleContext.line1Direction }, { key: 'line1Reverse', - direction: reverseDirection(angleContext.line1Direction), + direction: scaleVec(angleContext.line1Direction, -1), }, ] From 54a436d3462e8a07465966ace7579f183f417679 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 17:07:58 +0200 Subject: [PATCH 34/78] remove duplicated line intersection fn --- src/lib/utils2d.ts | 20 +++++++++++++++ .../constraints/AngleConstraintBuilder.ts | 22 +--------------- .../sketchSolve/tools/dimensionTool.ts | 25 +------------------ 3 files changed, 22 insertions(+), 45 deletions(-) diff --git a/src/lib/utils2d.ts b/src/lib/utils2d.ts index 5b5fc2c0549..29dde17ac12 100644 --- a/src/lib/utils2d.ts +++ b/src/lib/utils2d.ts @@ -114,6 +114,26 @@ export function cross2d(a: Coords2d, b: Coords2d): number { return a[0] * b[1] - a[1] * b[0] } +// Returns the intersection of two infinite lines defined by two points each. +// Returns null when the lines are parallel or nearly parallel. +export function getLineIntersection( + line0: readonly [Coords2d, Coords2d], + line1: readonly [Coords2d, Coords2d] +): Coords2d | null { + const p = line0[0] + const q = line1[0] + const r = subVec(line0[1], line0[0]) + const s = subVec(line1[1], line1[0]) + const denominator = cross2d(r, s) + if (Math.abs(denominator) <= 1e-9) { + return null + } + + const qp = subVec(q, p) + const t = cross2d(qp, s) / denominator + return [p[0] + r[0] * t, p[1] + r[1] * t] +} + // Takes a vector given by 2 coords and rotates it 90deg CCW. export function perpendicular(v: Coords2d): Coords2d { return [-v[1], v[0]] diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index a5d318b62fd..ba755307e22 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -10,6 +10,7 @@ import { distance2d, dot2d, getCcwSweep, + getLineIntersection, getPolarAngle2d, intersectRanges, lerp, @@ -387,24 +388,3 @@ function withMinimumMagnitude(value: number, minMagnitude: number) { } return Math.sign(value) * Math.max(Math.abs(value), minMagnitude) } - -// Returns the intersection of 2 infinite lines that lie on the given line segments. -// Returns a valid point even if the line segments themselves don't intersect. -// Returns null if the lines are parallel, -export function getLineIntersection( - line1: LineSegment, - line2: LineSegment -): Coords2d | null { - const p = line1[0] - const q = line2[0] - const r = subVec(line1[1], line1[0]) - const s = subVec(line2[1], line2[0]) - const denominator = r[0] * s[1] - r[1] * s[0] - if (Math.abs(denominator) < 1e-8) { - return null - } - - const qp = subVec(q, p) - const t = (qp[0] * s[1] - qp[1] * s[0]) / denominator - return [p[0] + r[0] * t, p[1] + r[1] * t] -} diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 42f312e0415..47d859a8d86 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -17,6 +17,7 @@ import { roundOff } from '@src/lib/utils' import { dot2d, getCcwSweep, + getLineIntersection, length2d, normalizeAngle, normalizeVec, @@ -158,7 +159,6 @@ type DraftRuntime = { type ApiAngleConstraint = Extract -const LINE_INTERSECTION_EPSILON = 1e-8 const SECTOR_EPSILON = 1e-9 const ANGLE_SECTOR_PROMPT_TOAST_ID = 'dimension-tool-angle-sector-prompt' @@ -207,29 +207,6 @@ function getObjects(context: DimensionToolContext) { return context.initialObjects } -function getLineIntersection( - line0Points: readonly [Coords2d, Coords2d], - line1Points: readonly [Coords2d, Coords2d] -): Coords2d | null { - const [p0, p1] = line0Points - const [p2, p3] = line1Points - const line0Direction = subVec(p1, p0) - const line1Direction = subVec(p3, p2) - const denominator = - line0Direction[0] * line1Direction[1] - - line0Direction[1] * line1Direction[0] - - if (Math.abs(denominator) < LINE_INTERSECTION_EPSILON) { - return null - } - - const delta = subVec(p2, p0) - const t = - (delta[0] * line1Direction[1] - delta[1] * line1Direction[0]) / denominator - - return [p0[0] + t * line0Direction[0], p0[1] + t * line0Direction[1]] -} - function getClickedRayDirection( linePoints: readonly [Coords2d, Coords2d], vertex: Coords2d, From ed54463708249bac9ad074111fbf574fe30399f2 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 17:19:11 +0200 Subject: [PATCH 35/78] remove nonsensical one liner --- src/machines/sketchSolve/tools/dimensionTool.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 47d859a8d86..49b4a59dbc9 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -492,17 +492,13 @@ function findWedgeIndexForRays( ) } -function getBaseWedgeIndex(angleContext: DimensionAngleDraftContext): number { - return angleContext.baseWedgeIndex -} - function getHoveredWedgeIndex( mousePoint: Coords2d, angleContext: DimensionAngleDraftContext ): number { const mouseDirection = subVec(mousePoint, angleContext.vertex) if (length2d(mouseDirection) === 0) { - return getBaseWedgeIndex(angleContext) + return angleContext.baseWedgeIndex } const wedges = getAngleWedges(angleContext) @@ -517,7 +513,7 @@ function getHoveredWedgeIndex( return hoveredIndex } - return getBaseWedgeIndex(angleContext) + return angleContext.baseWedgeIndex } function invertAngleSelection( @@ -540,7 +536,7 @@ function getWedgeSelection( const wedges = getAngleWedges(angleContext) return ( wedges[wedgeIndex]?.selection ?? - wedges[getBaseWedgeIndex(angleContext)]?.selection + wedges[angleContext.baseWedgeIndex]?.selection ) } @@ -548,7 +544,7 @@ export function getDimensionAngleSelection( mousePoint: Coords2d, angleContext: DimensionAngleDraftContext ): DimensionAngleSelection { - const baseWedgeIndex = getBaseWedgeIndex(angleContext) + const baseWedgeIndex = angleContext.baseWedgeIndex const hoveredWedgeIndex = getHoveredWedgeIndex(mousePoint, angleContext) const baseSelection = getWedgeSelection(angleContext, baseWedgeIndex) From 032ebf00b1d40f55b93444828f7346e3b0f04b34 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 17:22:43 +0200 Subject: [PATCH 36/78] move getAngleDiff to utils2d next to getCCwSweep --- src/lib/utils.ts | 36 ------------------- src/lib/utils2d.ts | 17 +++++++++ .../constraints/RadiusConstraintBuilder.ts | 3 +- .../invisibleConstraintSpriteUtils.ts | 3 +- .../interaction/interactionHelpers.ts | 10 ++++-- .../tools/moveTool/areaSelectUtils.ts | 3 +- .../tools/threePointArcToolImpl.ts | 4 +-- 7 files changed, 30 insertions(+), 46 deletions(-) diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 5715408bfd8..6525afbd714 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -148,42 +148,6 @@ export function normaliseAngle(angle: number): number { return result > 180 ? result - 360 : result } -/** - * Computes the directed angular distance from startAngle to endAngle - * in radians, going either CCW or CW. - * - * Notes: - * - If startAngle === endAngle, the result is 0 for both directions (not 2Ï€). - * - Inputs are typically within [-Ï€, Ï€], but any value work, - * - * @param startAngle - Start angle in radians. - * @param endAngle - End angle in radians. - * @param ccw - If true, measure the CCW distance from start to end. If false, measure CW. - * @returns Angular distance in radians in the range [0, 2Ï€). - * - * @example - * getAngleDiff(0, Math.PI / 2, true) => Math.PI / 2 - * getAngleDiff(0, Math.PI / 2, false) => 3 * Math.PI / 2 - * getAngleDiff(0.1, -0.1, true) => 2 * Math.PI - 0.2 - * getAngleDiff(0.1, -0.1, false) => 0.2 - * getAngleDiff(-0.1, 0.1, true) => 0.2 - */ -export function getAngleDiff( - startAngle: number, - endAngle: number, - ccw: boolean -) { - const TWO_PI = Math.PI * 2 - - let d = endAngle - startAngle - - // Wrap into [0, 2Ï€) - d = ((d % TWO_PI) + TWO_PI) % TWO_PI - - // If going CW, take the other way around (but still wrap into [0, 2Ï€)) - return ccw ? d : (TWO_PI - d) % TWO_PI -} - export function throttle( func: (args: T) => any, wait: number diff --git a/src/lib/utils2d.ts b/src/lib/utils2d.ts index 29dde17ac12..bfcaa42ab77 100644 --- a/src/lib/utils2d.ts +++ b/src/lib/utils2d.ts @@ -20,6 +20,23 @@ export function getCcwSweep(start: Coords2d, end: Coords2d) { ) } +/** + * Computes the directed angular distance from startAngle to endAngle + * in radians, going either CCW or CW. + * + * Notes: + * - If startAngle === endAngle, the result is 0 for both directions (not 2PI). + * - Inputs are typically within [-PI, PI], but any value works. + */ +export function getAngleDiff( + startAngle: number, + endAngle: number, + ccw: boolean +) { + const diff = normalizeAngle(endAngle - startAngle) + return ccw ? diff : (TAU - diff) % TAU +} + export function getTangentPointFromPreviousArc( lastArcCenter: Coords2d, lastArcCCW: boolean, diff --git a/src/machines/sketchSolve/constraints/RadiusConstraintBuilder.ts b/src/machines/sketchSolve/constraints/RadiusConstraintBuilder.ts index 1f619e13b84..0adc3ac848d 100644 --- a/src/machines/sketchSolve/constraints/RadiusConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/RadiusConstraintBuilder.ts @@ -1,8 +1,7 @@ import type { ApiObject } from '@rust/kcl-lib/bindings/FrontendApi' import { DISTANCE_CONSTRAINT_BODY } from '@src/clientSideScene/sceneConstants' import type { SceneInfra } from '@src/clientSideScene/sceneInfra' -import { getAngleDiff } from '@src/lib/utils' -import { getPolarAngle2d } from '@src/lib/utils2d' +import { getAngleDiff, getPolarAngle2d } from '@src/lib/utils2d' import { createArcPositions } from '@src/machines/sketchSolve/arcPositions' import type { ConstraintResources } from '@src/machines/sketchSolve/constraints/ConstraintResources' import { diff --git a/src/machines/sketchSolve/constraints/invisibleConstraintSpriteUtils.ts b/src/machines/sketchSolve/constraints/invisibleConstraintSpriteUtils.ts index 8b6111ad26e..73ae37261fc 100644 --- a/src/machines/sketchSolve/constraints/invisibleConstraintSpriteUtils.ts +++ b/src/machines/sketchSolve/constraints/invisibleConstraintSpriteUtils.ts @@ -3,8 +3,7 @@ import type { ApiObject, } from '@rust/kcl-lib/bindings/FrontendApi' import type { Coords2d } from '@src/lang/util' -import { getAngleDiff } from '@src/lib/utils' -import { lerp2d } from '@src/lib/utils2d' +import { getAngleDiff, lerp2d } from '@src/lib/utils2d' import { Vector3 } from 'three' import { SKETCH_HIGHLIGHT_SECONDARY_COLOR } from '@src/lib/constants' diff --git a/src/machines/sketchSolve/interaction/interactionHelpers.ts b/src/machines/sketchSolve/interaction/interactionHelpers.ts index a3bfd0e4dfb..530c3922bc9 100644 --- a/src/machines/sketchSolve/interaction/interactionHelpers.ts +++ b/src/machines/sketchSolve/interaction/interactionHelpers.ts @@ -3,8 +3,14 @@ import { DISTANCE_CONSTRAINT_LABEL } from '@src/clientSideScene/sceneConstants' import type { SceneInfra } from '@src/clientSideScene/sceneInfra' import { SKETCH_SOLVE_GROUP } from '@src/clientSideScene/sceneUtils' import type { Coords2d } from '@src/lang/util' -import { getAngleDiff, isArray } from '@src/lib/utils' -import { distance2d, dot2d, polar2d, subVec } from '@src/lib/utils2d' +import { isArray } from '@src/lib/utils' +import { + distance2d, + dot2d, + getAngleDiff, + polar2d, + subVec, +} from '@src/lib/utils2d' import { getArcPoints, getControlPointSplinePoints, diff --git a/src/machines/sketchSolve/tools/moveTool/areaSelectUtils.ts b/src/machines/sketchSolve/tools/moveTool/areaSelectUtils.ts index 9356c4ab29f..c7e146728b4 100644 --- a/src/machines/sketchSolve/tools/moveTool/areaSelectUtils.ts +++ b/src/machines/sketchSolve/tools/moveTool/areaSelectUtils.ts @@ -5,8 +5,7 @@ import { SKETCH_SOLVE_GROUP, } from '@src/clientSideScene/sceneUtils' import type { Coords2d } from '@src/lang/util' -import { getAngleDiff } from '@src/lib/utils' -import { TAU } from '@src/lib/utils2d' +import { TAU, getAngleDiff } from '@src/lib/utils2d' import { getArcPoints, getLinePoints, diff --git a/src/machines/sketchSolve/tools/threePointArcToolImpl.ts b/src/machines/sketchSolve/tools/threePointArcToolImpl.ts index f5b67ba3aeb..011fa364fd4 100644 --- a/src/machines/sketchSolve/tools/threePointArcToolImpl.ts +++ b/src/machines/sketchSolve/tools/threePointArcToolImpl.ts @@ -10,8 +10,8 @@ import type { Coords2d } from '@src/lang/util' import { baseUnitToNumericSuffix } from '@src/lang/wasm' import type RustContext from '@src/lib/rustContext' import { jsAppSettings } from '@src/lib/settings/settingsUtils' -import { getAngleDiff, roundOff } from '@src/lib/utils' -import { lerp2d, subVec } from '@src/lib/utils2d' +import { roundOff } from '@src/lib/utils' +import { getAngleDiff, lerp2d, subVec } from '@src/lib/utils2d' import { isArcSegment, isPointSegment, From e62584693ad76a4ad6e63332e1ced5505e067235 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 17:23:32 +0200 Subject: [PATCH 37/78] remove duplicate fn --- rust/kcl-lib/src/execution/exec_ast.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 6fc51abb0f8..9b8cf46777e 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -118,6 +118,7 @@ use crate::std::sketch::ensure_sketch_plane_in_engine; use crate::std::solver::SOLVER_CONVERGENCE_TOLERANCE; use crate::std::solver::create_segments_in_engine; use crate::std::utils::intersect_lines_2d; +use crate::std::utils::normalize_rad; use crate::std::utils::vec2_dot; use crate::std::utils::vec2_len; use crate::std::utils::vec2_sub; @@ -301,15 +302,6 @@ fn angle_sector_rays(sector: AngleSector, is_inverse: bool) -> [AngleSectorRay; if is_inverse { [rays[1], rays[0]] } else { rays } } -fn normalize_radians(angle: f64) -> f64 { - let normalized = angle % std::f64::consts::TAU; - if normalized < 0.0 { - normalized + std::f64::consts::TAU - } else { - normalized - } -} - fn line_endpoint_datum( line: &ConstrainableLine2d, endpoint_index: usize, @@ -382,7 +374,7 @@ fn remap_angle_for_representative_rays( -desired - sign_offset }; - ezpz::datatypes::Angle::from_radians(normalize_radians(representative_angle)) + ezpz::datatypes::Angle::from_radians(normalize_rad(representative_angle)) } struct PointsAtAngleLineData { From c8976f70c0c57a141c858d5a5b85df22cb048d5c Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 24 Jun 2026 17:27:53 +0200 Subject: [PATCH 38/78] revert unintended xstate layout change --- src/machines/sketchSolve/tools/dimensionTool.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 49b4a59dbc9..75f4c6b76bb 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -1050,6 +1050,7 @@ export const machine = setup({ }, }, }).createMachine({ + /** @xstate-layout N4IgpgJg5mDOIC5QBECWBbMA7WqD2WABAC554A2AxAK5ZgCO1qADgNoAMAuoqM3rsXxYeIAB6J2AGhABPCQF950tJhxCSZcgDoAhgHcdqQViiEAZqgBOsYoT6osxSjogQ7eB8Q7ckIPgKERcQQANgAWMK0AZgB2AFYYgE4ADhD2AEYQqIzpOQQo9PStGOT00rCQxMqAJijkuMVlDGxcAg0KXQMjQlgwAGMCN3tHZ1d3T28RfyNA32DwyNiElLTM7PTcxDC45K1qkLKQ5OqYqLj09iiwxpAVFvVSDoBhAgtLdAdTCGa1AlhKCAEMBaBwANzwAGtgXdfkRHtoXlg3h8TIRvqpWjgEGC8H0dIICN5Jr5pgThHNEHF2DE9ok4md9tUIuFkmFNghkjFqtFUiztmV9jcYZj2gjXlYUV8fpj-mBLJY8JYtMxyPizIr0FphQ9NFpEcjPmjpUJYNisOC8WSiVwpvwZgQglt2OwtCF6TFnYkomd0tU4uzStyyhF0lFEtVEuxqqzFEoQFg8BA4CJtW14baAg6KQgALRhZLsnOhorpL0xLKJeLh-NC41p3X6QzGUxvGzjRwZ+3k0DBKIHLThj0FCJxMIxMKxdm1bkxX1pEpxJnjhpx1NwhtdWy9AZYIYeDsku1kx35EI0kfsKkT9Ie8MhdkRGnHN3bdiRirR66ruvr57i96Gui9x-J2x7Zt6NJemEzp+icfr3rIiAHJEYTVDeo6ltUfqJIktYYjqHS0AwTDMMwnygbMPYSAGZwDr6VLjuElaLrG8hAA */ context: ({ input }): DimensionToolContext => ({ sceneInfra: input.sceneInfra, rustContext: input.rustContext, From 8c55ba18bde4b0924a5d39fb655f86d1de627174 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 12:32:26 +0200 Subject: [PATCH 39/78] simplify: remove wedge concept, convert directly to sector from mouse pos --- .../sketchSolve/tools/dimensionTool.spec.ts | 31 ++- .../sketchSolve/tools/dimensionTool.ts | 190 ++++++------------ 2 files changed, 85 insertions(+), 136 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index 11b43d47c21..fd1528a2168 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -216,7 +216,10 @@ describe('dimensionTool angle selection', () => { line1Id: 11, ...lineDirections, vertex: [0, 0], - baseWedgeIndex: 0, + baseSelection: { + sector: 1, + inverse: false, + }, } it('maps cursor sectors relative to the clicked rays', () => { @@ -238,7 +241,7 @@ describe('dimensionTool angle selection', () => { }) }) - it('uses inverse when the visual wedge is opposite the directed KCL sector', () => { + it('uses inverse when the visible region is opposite the directed KCL sector', () => { const clockwiseContext: DimensionAngleDraftContext = { line0Id: 10, line1Id: 11, @@ -248,7 +251,10 @@ describe('dimensionTool angle selection', () => { ] as Coords2d, line1Direction: [1, 0], vertex: [0, 0], - baseWedgeIndex: 0, + baseSelection: { + sector: 1, + inverse: true, + }, } expect(getDimensionAngleSelection([1, 0.25], clockwiseContext)).toEqual({ @@ -269,6 +275,25 @@ describe('dimensionTool angle selection', () => { }) }) + it('keeps the clicked sector and flips inverse when hovering the opposite side', () => { + const southLineContext: DimensionAngleDraftContext = { + line0Id: 10, + line1Id: 11, + line0Direction: [1, 0], + line1Direction: [0, -1], + vertex: [0, 0], + baseSelection: { + sector: 1, + inverse: true, + }, + } + + expect(getDimensionAngleSelection([-1, 1], southLineContext)).toEqual({ + sector: 1, + inverse: false, + }) + }) + it('builds the labelled angle constraint with sector, inverse, and label position', () => { const constraint = buildDimensionAngleConstraint( angleContext, diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 75f4c6b76bb..4bdc17dbf90 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -19,7 +19,6 @@ import { getCcwSweep, getLineIntersection, length2d, - normalizeAngle, normalizeVec, scaleVec, subVec, @@ -127,7 +126,7 @@ export type DimensionAngleDraftContext = { line0Direction: Coords2d line1Direction: Coords2d vertex: Coords2d - baseWedgeIndex: number + baseSelection: DimensionAngleSelection } type DimensionAngleSelection = { @@ -135,17 +134,6 @@ type DimensionAngleSelection = { inverse: boolean } -type AngleRay = { - key: AngleRayKey - direction: Coords2d -} - -type AngleWedge = { - start: AngleRay - end: AngleRay - selection: DimensionAngleSelection -} - type DraftRuntime = { firstSelection: LineSelection | null angleContext: DimensionAngleDraftContext | null @@ -160,6 +148,9 @@ type DraftRuntime = { type ApiAngleConstraint = Extract const SECTOR_EPSILON = 1e-9 +const ANGLE_SECTORS = [1, 2, 3, 4] as const satisfies ReadonlyArray< + AngleSector +> const ANGLE_SECTOR_PROMPT_TOAST_ID = 'dimension-tool-angle-sector-prompt' function getDefaultLengthUnit(kclManager: KclManager): NumericSuffix { @@ -268,20 +259,21 @@ function getDimensionAngleContext( secondSelection.clickPoint ) - const angleContext = { + const angleContextBase = { line0Id: firstSelection.id, line1Id: secondSelection.id, line0Direction: normalizeVec(line0Vector), line1Direction: normalizeVec(line1Vector), vertex, - baseWedgeIndex: 0, } - angleContext.baseWedgeIndex = findWedgeIndexForRays( - angleContext, - getClickedRayKey(0, line0Ray), - getClickedRayKey(1, line1Ray) - ) - return angleContext + return { + ...angleContextBase, + baseSelection: getBaseAngleSelection( + angleContextBase, + getClickedRayKey(0, line0Ray), + getClickedRayKey(1, line1Ray) + ), + } } function getFarthestLinePointFromVertex( @@ -408,112 +400,71 @@ const DIRECT_SECTOR_BOUNDARIES = [ endKey: AngleRayKey }> -function getAngleRays( - angleContext: Pick< - DimensionAngleDraftContext, - 'line0Direction' | 'line1Direction' - > -): AngleRay[] { - const rays: AngleRay[] = [ - { key: 'line0Forward', direction: angleContext.line0Direction }, - { - key: 'line0Reverse', - direction: scaleVec(angleContext.line0Direction, -1), - }, - { key: 'line1Forward', direction: angleContext.line1Direction }, - { - key: 'line1Reverse', - direction: scaleVec(angleContext.line1Direction, -1), - }, - ] - - return rays.sort( - (left, right) => - normalizeAngle(Math.atan2(left.direction[1], left.direction[0])) - - normalizeAngle(Math.atan2(right.direction[1], right.direction[0])) - ) -} - -function getSelectionForWedge(startKey: AngleRayKey, endKey: AngleRayKey) { +function getSectorForRayPair(startKey: AngleRayKey, endKey: AngleRayKey) { for (const boundary of DIRECT_SECTOR_BOUNDARIES) { - if (boundary.startKey === startKey && boundary.endKey === endKey) { - return { - sector: boundary.sector, - inverse: false, - } - } - - if (boundary.startKey === endKey && boundary.endKey === startKey) { - return { - sector: boundary.sector, - inverse: true, - } + if ( + (boundary.startKey === startKey && boundary.endKey === endKey) || + (boundary.startKey === endKey && boundary.endKey === startKey) + ) { + return boundary.sector } } } -function getAngleWedges( +function getVisibleAngleSelection( angleContext: Pick< DimensionAngleDraftContext, 'line0Direction' | 'line1Direction' - > -): AngleWedge[] { - const rays = getAngleRays(angleContext) - const wedges: AngleWedge[] = [] - - for (let index = 0; index < rays.length; index++) { - const start = rays[index] - const end = rays[(index + 1) % rays.length] - const selection = getSelectionForWedge(start.key, end.key) - if (selection) { - wedges.push({ start, end, selection }) - } + >, + sector: AngleSector +): DimensionAngleSelection { + const [start, end] = getAngleSectorRays(angleContext, sector) + return { + sector, + inverse: getCcwSweep(start, end) > Math.PI, } - - return wedges } -function findWedgeIndexForRays( +function getBaseAngleSelection( angleContext: Pick< DimensionAngleDraftContext, 'line0Direction' | 'line1Direction' >, line0Ray: AngleRayKey, line1Ray: AngleRayKey -) { - const wedges = getAngleWedges(angleContext) - return Math.max( - wedges.findIndex( - (wedge) => - (wedge.start.key === line0Ray && wedge.end.key === line1Ray) || - (wedge.start.key === line1Ray && wedge.end.key === line0Ray) - ), - 0 - ) +): DimensionAngleSelection { + const sector = getSectorForRayPair(line0Ray, line1Ray) ?? 1 + return getVisibleAngleSelection(angleContext, sector) } -function getHoveredWedgeIndex( +function getVisibleAngleSectorRays( + angleContext: Pick< + DimensionAngleDraftContext, + 'line0Direction' | 'line1Direction' + >, + selection: DimensionAngleSelection +): [Coords2d, Coords2d] { + const [start, end] = getAngleSectorRays(angleContext, selection.sector) + return selection.inverse ? [end, start] : [start, end] +} + +function getHoveredAngleSelection( mousePoint: Coords2d, angleContext: DimensionAngleDraftContext -): number { +): DimensionAngleSelection { const mouseDirection = subVec(mousePoint, angleContext.vertex) if (length2d(mouseDirection) === 0) { - return angleContext.baseWedgeIndex + return angleContext.baseSelection } - const wedges = getAngleWedges(angleContext) - const hoveredIndex = wedges.findIndex((wedge) => - isDirectionInSector( - mouseDirection, - wedge.start.direction, - wedge.end.direction - ) + return ( + ANGLE_SECTORS.map((sector) => + getVisibleAngleSelection(angleContext, sector) + ).find((selection) => { + const [start, end] = getVisibleAngleSectorRays(angleContext, selection) + return isDirectionInSector(mouseDirection, start, end) + }) ?? angleContext.baseSelection ) - if (hoveredIndex !== -1) { - return hoveredIndex - } - - return angleContext.baseWedgeIndex } function invertAngleSelection( @@ -525,45 +476,18 @@ function invertAngleSelection( } } -function getOppositeWedgeIndex(wedgeIndex: number) { - return (wedgeIndex + 2) % 4 -} - -function getWedgeSelection( - angleContext: DimensionAngleDraftContext, - wedgeIndex: number -) { - const wedges = getAngleWedges(angleContext) - return ( - wedges[wedgeIndex]?.selection ?? - wedges[angleContext.baseWedgeIndex]?.selection - ) -} - export function getDimensionAngleSelection( mousePoint: Coords2d, angleContext: DimensionAngleDraftContext ): DimensionAngleSelection { - const baseWedgeIndex = angleContext.baseWedgeIndex - const hoveredWedgeIndex = getHoveredWedgeIndex(mousePoint, angleContext) - const baseSelection = getWedgeSelection(angleContext, baseWedgeIndex) - - if ( - baseSelection && - hoveredWedgeIndex === getOppositeWedgeIndex(baseWedgeIndex) - ) { - return invertAngleSelection(baseSelection) - } + const hoveredSelection = getHoveredAngleSelection(mousePoint, angleContext) + const oppositeBaseSector = ((angleContext.baseSelection.sector + 1) % 4) + 1 - const hoveredSelection = getWedgeSelection(angleContext, hoveredWedgeIndex) - if (hoveredSelection) { - return hoveredSelection + if (hoveredSelection.sector === oppositeBaseSector) { + return invertAngleSelection(angleContext.baseSelection) } - return { - sector: 1, - inverse: false, - } + return hoveredSelection } function getDimensionAngleDegrees( From d84cb7590e0498807fe1c53af46263a580a29319 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 12:34:16 +0200 Subject: [PATCH 40/78] fmt --- src/machines/sketchSolve/tools/dimensionTool.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 4bdc17dbf90..cfcb8abec90 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -148,9 +148,7 @@ type DraftRuntime = { type ApiAngleConstraint = Extract const SECTOR_EPSILON = 1e-9 -const ANGLE_SECTORS = [1, 2, 3, 4] as const satisfies ReadonlyArray< - AngleSector -> +const ANGLE_SECTORS = [1, 2, 3, 4] as const satisfies ReadonlyArray const ANGLE_SECTOR_PROMPT_TOAST_ID = 'dimension-tool-angle-sector-prompt' function getDefaultLengthUnit(kclManager: KclManager): NumericSuffix { From 3dc991044e8f6df8190d53055a9986d019153f14 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 13:40:05 +0200 Subject: [PATCH 41/78] simplify dimensiontool --- .../sketchSolve/tools/dimensionTool.ts | 63 ++----------------- 1 file changed, 5 insertions(+), 58 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index cfcb8abec90..58c49c51a7c 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -114,11 +114,6 @@ type LineSelection = { type RayDirection = 'forward' | 'reverse' export type AngleSector = 1 | 2 | 3 | 4 -type AngleRayKey = - | 'line0Forward' - | 'line0Reverse' - | 'line1Forward' - | 'line1Reverse' export type DimensionAngleDraftContext = { line0Id: number @@ -268,8 +263,8 @@ function getDimensionAngleContext( ...angleContextBase, baseSelection: getBaseAngleSelection( angleContextBase, - getClickedRayKey(0, line0Ray), - getClickedRayKey(1, line1Ray) + line0Ray, + line1Ray ), } } @@ -333,16 +328,6 @@ function isDirectionInSector( ) } -function getClickedRayKey( - lineIndex: 0 | 1, - direction: RayDirection -): AngleRayKey { - if (lineIndex === 0) { - return direction === 'forward' ? 'line0Forward' : 'line0Reverse' - } - return direction === 'forward' ? 'line1Forward' : 'line1Reverse' -} - export function getAngleSectorRays( angleContext: Pick< DimensionAngleDraftContext, @@ -371,44 +356,6 @@ export function getAngleSectorRays( } } -const DIRECT_SECTOR_BOUNDARIES = [ - { - sector: 1, - startKey: 'line0Forward', - endKey: 'line1Forward', - }, - { - sector: 2, - startKey: 'line1Forward', - endKey: 'line0Reverse', - }, - { - sector: 3, - startKey: 'line0Reverse', - endKey: 'line1Reverse', - }, - { - sector: 4, - startKey: 'line1Reverse', - endKey: 'line0Forward', - }, -] as const satisfies ReadonlyArray<{ - sector: AngleSector - startKey: AngleRayKey - endKey: AngleRayKey -}> - -function getSectorForRayPair(startKey: AngleRayKey, endKey: AngleRayKey) { - for (const boundary of DIRECT_SECTOR_BOUNDARIES) { - if ( - (boundary.startKey === startKey && boundary.endKey === endKey) || - (boundary.startKey === endKey && boundary.endKey === startKey) - ) { - return boundary.sector - } - } -} - function getVisibleAngleSelection( angleContext: Pick< DimensionAngleDraftContext, @@ -428,10 +375,10 @@ function getBaseAngleSelection( DimensionAngleDraftContext, 'line0Direction' | 'line1Direction' >, - line0Ray: AngleRayKey, - line1Ray: AngleRayKey + line0Ray: RayDirection, + line1Ray: RayDirection ): DimensionAngleSelection { - const sector = getSectorForRayPair(line0Ray, line1Ray) ?? 1 + const sector = getBaseAngleSector(line0Ray, line1Ray) return getVisibleAngleSelection(angleContext, sector) } From 8ff64026a2d7fc9f364743e603bef7eb6cdc2de2 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 13:40:13 +0200 Subject: [PATCH 42/78] fmt --- src/machines/sketchSolve/tools/dimensionTool.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 58c49c51a7c..9571d5c15b8 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -261,11 +261,7 @@ function getDimensionAngleContext( } return { ...angleContextBase, - baseSelection: getBaseAngleSelection( - angleContextBase, - line0Ray, - line1Ray - ), + baseSelection: getBaseAngleSelection(angleContextBase, line0Ray, line1Ray), } } From 344c35452b0a7d52f5f3a6c9ddc50c7f6c67b676 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 13:50:03 +0200 Subject: [PATCH 43/78] more simplifications --- .../sketchSolve/tools/dimensionTool.ts | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 9571d5c15b8..1eeb42a23cc 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -124,6 +124,11 @@ export type DimensionAngleDraftContext = { baseSelection: DimensionAngleSelection } +type DimensionAngleDirections = { + line0Direction: Coords2d + line1Direction: Coords2d +} + type DimensionAngleSelection = { sector: AngleSector inverse: boolean @@ -187,10 +192,6 @@ function dismissAngleSectorPrompt() { toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) } -function getObjects(context: DimensionToolContext) { - return context.initialObjects -} - function getClickedRayDirection( linePoints: readonly [Coords2d, Coords2d], vertex: Coords2d, @@ -325,10 +326,7 @@ function isDirectionInSector( } export function getAngleSectorRays( - angleContext: Pick< - DimensionAngleDraftContext, - 'line0Direction' | 'line1Direction' - >, + angleContext: DimensionAngleDirections, sector: AngleSector ): [Coords2d, Coords2d] { switch (sector) { @@ -353,10 +351,7 @@ export function getAngleSectorRays( } function getVisibleAngleSelection( - angleContext: Pick< - DimensionAngleDraftContext, - 'line0Direction' | 'line1Direction' - >, + angleContext: DimensionAngleDirections, sector: AngleSector ): DimensionAngleSelection { const [start, end] = getAngleSectorRays(angleContext, sector) @@ -367,10 +362,7 @@ function getVisibleAngleSelection( } function getBaseAngleSelection( - angleContext: Pick< - DimensionAngleDraftContext, - 'line0Direction' | 'line1Direction' - >, + angleContext: DimensionAngleDirections, line0Ray: RayDirection, line1Ray: RayDirection ): DimensionAngleSelection { @@ -379,10 +371,7 @@ function getBaseAngleSelection( } function getVisibleAngleSectorRays( - angleContext: Pick< - DimensionAngleDraftContext, - 'line0Direction' | 'line1Direction' - >, + angleContext: DimensionAngleDirections, selection: DimensionAngleSelection ): [Coords2d, Coords2d] { const [start, end] = getAngleSectorRays(angleContext, selection.sector) @@ -726,9 +715,8 @@ function getClosestLineSelection( mousePoint: Coords2d, context: DimensionToolContext ): LineSelection | null { - const objects = getObjects(context) const currentSketchObjects = getCurrentSketchObjectsById( - objects, + context.initialObjects, context.sketchId ) const closestLine = findClosestApiObjects( @@ -759,17 +747,18 @@ function addDimensionListener({ }) { const runtime = context.runtime runtime.active = true + const initialObjects = context.initialObjects const initialLineSelections = getInitialAngleLineSelections( context.initialSelectionIds, context.initialSelectionClickPoints, - getObjects(context) + initialObjects ) if (initialLineSelections) { const [firstSelection, secondSelection] = initialLineSelections const angleContext = getDimensionAngleContext( firstSelection, secondSelection, - getObjects(context) + initialObjects ) if (angleContext) { runtime.firstSelection = firstSelection @@ -828,7 +817,7 @@ function addDimensionListener({ const angleContext = getDimensionAngleContext( runtime.firstSelection, lineSelection, - getObjects(context) + initialObjects ) if (angleContext) { @@ -894,12 +883,6 @@ function removeDimensionListener({ }) } -function deleteDraftEntities(self: { - _parent?: { send: (event: unknown) => void } -}) { - sendParent(self, { type: 'delete draft entities' }) -} - export const machine = setup({ types: { context: {} as DimensionToolContext, @@ -909,7 +892,8 @@ export const machine = setup({ actions: { 'add dimension listener': addDimensionListener, 'remove dimension listener': removeDimensionListener, - 'delete draft entities': ({ self }) => deleteDraftEntities(self), + 'delete draft entities': ({ self }) => + sendParent(self, { type: 'delete draft entities' }), 'toast sketch solve error': ({ event }) => { toastSketchSolveError(event) }, From b0795e8ce289f951c2b2be658df3e16fa2a3b03f Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 13:51:10 +0200 Subject: [PATCH 44/78] rename --- src/machines/sketchSolve/tools/dimensionTool.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 1eeb42a23cc..fffa3defd0a 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -542,7 +542,7 @@ function sendFinalResultToParent( }) } -async function replaceDraftAngleConstraint( +async function updateDraftAngleConstraint( runtime: DraftRuntime, context: DimensionToolContext, self: { _parent?: { send: (event: unknown) => void } }, @@ -630,7 +630,7 @@ function requestDraftPreview( while (runtime.active && runtime.queuedMousePoint) { const nextMousePoint = runtime.queuedMousePoint runtime.queuedMousePoint = null - await replaceDraftAngleConstraint( + await updateDraftAngleConstraint( runtime, context, self, From 21b37179ecfe9fbbab5300e468417a3969307afe Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 13:59:20 +0200 Subject: [PATCH 45/78] fmt --- src/machines/sketchSolve/tools/dimensionTool.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index fffa3defd0a..468bac24f03 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -558,6 +558,7 @@ async function updateDraftAngleConstraint( getDefaultLengthUnit(context.kclManager) ) const draftKey = getDraftKey(constraint) + // Skip constraint edits when the mouse moved too little to change the draft. if (draftKey === runtime.lastDraftKey) { return } @@ -630,12 +631,7 @@ function requestDraftPreview( while (runtime.active && runtime.queuedMousePoint) { const nextMousePoint = runtime.queuedMousePoint runtime.queuedMousePoint = null - await updateDraftAngleConstraint( - runtime, - context, - self, - nextMousePoint - ) + await updateDraftAngleConstraint(runtime, context, self, nextMousePoint) } } catch (error) { toastSketchSolveError(error) From a9796dad2afe7947a9f5b63cb283426dc26347d4 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 14:09:45 +0200 Subject: [PATCH 46/78] simplify more --- src/machines/sketchSolve/tools/dimensionTool.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 468bac24f03..231c518ed75 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -262,7 +262,10 @@ function getDimensionAngleContext( } return { ...angleContextBase, - baseSelection: getBaseAngleSelection(angleContextBase, line0Ray, line1Ray), + baseSelection: getVisibleAngleSelection( + angleContextBase, + getBaseAngleSector(line0Ray, line1Ray) + ), } } @@ -361,15 +364,6 @@ function getVisibleAngleSelection( } } -function getBaseAngleSelection( - angleContext: DimensionAngleDirections, - line0Ray: RayDirection, - line1Ray: RayDirection -): DimensionAngleSelection { - const sector = getBaseAngleSector(line0Ray, line1Ray) - return getVisibleAngleSelection(angleContext, sector) -} - function getVisibleAngleSectorRays( angleContext: DimensionAngleDirections, selection: DimensionAngleSelection From 8b9e2804bf1327e4dd5aaa6047d9f24146dc4c5d Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 14:24:47 +0200 Subject: [PATCH 47/78] move getAngleSectorRays close to getBaseAngleSector --- .../sketchSolve/tools/dimensionTool.ts | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 231c518ed75..7896db5b60a 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -202,6 +202,7 @@ function getClickedRayDirection( return dot2d(clickDirection, lineDirection) >= 0 ? 'forward' : 'reverse' } +// Given which side of line0 and line1 the user clicked, which semantic sector is that? export function getBaseAngleSector( line0Ray: RayDirection, line1Ray: RayDirection @@ -218,6 +219,32 @@ export function getBaseAngleSector( return 4 } +// Given a sector number, what are the ordered start/end rays used to measure the angle? +export function getAngleSectorRays( + angleContext: DimensionAngleDirections, + sector: AngleSector +): [Coords2d, Coords2d] { + switch (sector) { + case 1: + return [angleContext.line0Direction, angleContext.line1Direction] + case 2: + return [ + angleContext.line1Direction, + scaleVec(angleContext.line0Direction, -1), + ] + case 3: + return [ + scaleVec(angleContext.line0Direction, -1), + scaleVec(angleContext.line1Direction, -1), + ] + case 4: + return [ + scaleVec(angleContext.line1Direction, -1), + angleContext.line0Direction, + ] + } +} + function getDimensionAngleContext( firstSelection: LineSelection, secondSelection: LineSelection, @@ -328,31 +355,6 @@ function isDirectionInSector( ) } -export function getAngleSectorRays( - angleContext: DimensionAngleDirections, - sector: AngleSector -): [Coords2d, Coords2d] { - switch (sector) { - case 1: - return [angleContext.line0Direction, angleContext.line1Direction] - case 2: - return [ - angleContext.line1Direction, - scaleVec(angleContext.line0Direction, -1), - ] - case 3: - return [ - scaleVec(angleContext.line0Direction, -1), - scaleVec(angleContext.line1Direction, -1), - ] - case 4: - return [ - scaleVec(angleContext.line1Direction, -1), - angleContext.line0Direction, - ] - } -} - function getVisibleAngleSelection( angleContext: DimensionAngleDirections, sector: AngleSector From acf7ea78cc85e8ecec61c22d054098b93f2a4afd Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 14:26:15 +0200 Subject: [PATCH 48/78] use bool instead of string for ray dir --- .../sketchSolve/tools/dimensionTool.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 7896db5b60a..32592fc968b 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -112,7 +112,6 @@ type LineSelection = { clickPoint: Coords2d } -type RayDirection = 'forward' | 'reverse' export type AngleSector = 1 | 2 | 3 | 4 export type DimensionAngleDraftContext = { @@ -192,28 +191,28 @@ function dismissAngleSectorPrompt() { toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) } -function getClickedRayDirection( +function isClickedRayDirectionForward( linePoints: readonly [Coords2d, Coords2d], vertex: Coords2d, clickPoint: Coords2d -): RayDirection { +): boolean { const lineDirection = normalizeVec(subVec(linePoints[1], linePoints[0])) const clickDirection = subVec(clickPoint, vertex) - return dot2d(clickDirection, lineDirection) >= 0 ? 'forward' : 'reverse' + return dot2d(clickDirection, lineDirection) >= 0 } // Given which side of line0 and line1 the user clicked, which semantic sector is that? export function getBaseAngleSector( - line0Ray: RayDirection, - line1Ray: RayDirection + line0RayDirectionIsForward: boolean, + line1RayDirectionIsForward: boolean ): AngleSector { - if (line0Ray === 'forward' && line1Ray === 'forward') { + if (line0RayDirectionIsForward && line1RayDirectionIsForward) { return 1 } - if (line0Ray === 'reverse' && line1Ray === 'forward') { + if (!line0RayDirectionIsForward && line1RayDirectionIsForward) { return 2 } - if (line0Ray === 'reverse' && line1Ray === 'reverse') { + if (!line0RayDirectionIsForward && !line1RayDirectionIsForward) { return 3 } return 4 @@ -269,12 +268,12 @@ function getDimensionAngleContext( return null } - const line0Ray = getClickedRayDirection( + const line0RayDirectionIsForward = isClickedRayDirectionForward( line0Points, vertex, firstSelection.clickPoint ) - const line1Ray = getClickedRayDirection( + const line1RayDirectionIsForward = isClickedRayDirectionForward( line1Points, vertex, secondSelection.clickPoint @@ -291,7 +290,10 @@ function getDimensionAngleContext( ...angleContextBase, baseSelection: getVisibleAngleSelection( angleContextBase, - getBaseAngleSector(line0Ray, line1Ray) + getBaseAngleSector( + line0RayDirectionIsForward, + line1RayDirectionIsForward + ) ), } } From 26f0fb92268ce6e4c429d63848c19128709eb80f Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 14:26:26 +0200 Subject: [PATCH 49/78] fmt --- src/machines/sketchSolve/tools/dimensionTool.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 32592fc968b..54275493221 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -290,10 +290,7 @@ function getDimensionAngleContext( ...angleContextBase, baseSelection: getVisibleAngleSelection( angleContextBase, - getBaseAngleSector( - line0RayDirectionIsForward, - line1RayDirectionIsForward - ) + getBaseAngleSector(line0RayDirectionIsForward, line1RayDirectionIsForward) ), } } From 14a02eaef79954fc4354af87ec197612e14346a6 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 18:03:17 +0200 Subject: [PATCH 50/78] remove duplicated types --- .../sketchSolve/tools/dimensionTool.ts | 71 +++++-------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 54275493221..b829658a35c 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -30,6 +30,7 @@ import { import { findClosestApiObjects } from '@src/machines/sketchSolve/interaction/interactionHelpers' import { getCurrentSketchObjectsById } from '@src/machines/sketchSolve/sceneGraphUtils' import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' +import type { SketchSolveMachineEvent } from '@src/machines/sketchSolve/sketchSolveImpl' import type { SelectionClickPoints, SketchSolveSelectionId, @@ -65,47 +66,13 @@ type DimensionToolEvent = type: 'done' } -type ParentSketchSolveEvent = - | { - type: 'update selected ids' - data: { - selectedIds?: SketchSolveSelectionId[] - duringAreaSelectIds?: number[] - replaceExistingSelection?: boolean - selectionClickPoints?: SelectionClickPoints - } - } - | { - type: 'update hovered id' - data: { - hoveredId: SketchSolveSelectionId | null - } - } - | { - type: 'update sketch outcome' - data: { - sourceDelta: SourceDelta - sceneGraphDelta: SceneGraphDelta - checkpointId?: number | null - updateEditor?: boolean - writeToDisk?: boolean - addToHistory?: boolean - suppressExecOutcomeIssues?: boolean - } - } - | { - type: 'set draft entities' - data: { - segmentIds: number[] - constraintIds: number[] - } - } - | { - type: 'clear draft entities' - } - | { - type: 'delete draft entities' - } +type ParentSketchSolveSender = { + _parent?: { send: (event: SketchSolveMachineEvent) => void } +} + +type DimensionToolSelf = ParentSketchSolveSender & { + send: (event: DimensionToolEvent) => void +} type LineSelection = { id: number @@ -157,8 +124,8 @@ function getDefaultLengthUnit(kclManager: KclManager): NumericSuffix { } function sendParent( - self: { _parent?: { send: (event: unknown) => void } }, - event: ParentSketchSolveEvent + self: ParentSketchSolveSender, + event: SketchSolveMachineEvent ) { self._parent?.send(event) } @@ -499,7 +466,7 @@ async function deleteInactivePreviewConstraint( } function sendPreviewResultToParent( - self: { _parent?: { send: (event: unknown) => void } }, + self: ParentSketchSolveSender, result: { kclSource: SourceDelta sceneGraphDelta: SceneGraphDelta @@ -520,7 +487,7 @@ function sendPreviewResultToParent( } function sendFinalResultToParent( - self: { _parent?: { send: (event: unknown) => void } }, + self: ParentSketchSolveSender, result: { kclSource: SourceDelta sceneGraphDelta: SceneGraphDelta @@ -540,7 +507,7 @@ function sendFinalResultToParent( async function updateDraftAngleConstraint( runtime: DraftRuntime, context: DimensionToolContext, - self: { _parent?: { send: (event: unknown) => void } }, + self: ParentSketchSolveSender, mousePoint: Coords2d ) { if (!runtime.active || !runtime.angleContext) { @@ -608,7 +575,7 @@ async function updateDraftAngleConstraint( function requestDraftPreview( runtime: DraftRuntime, context: DimensionToolContext, - self: { _parent?: { send: (event: unknown) => void } }, + self: ParentSketchSolveSender, mousePoint: Coords2d ) { if (!runtime.active) { @@ -639,10 +606,7 @@ function requestDraftPreview( async function commitDraftAngleConstraint( runtime: DraftRuntime, context: DimensionToolContext, - self: { - _parent?: { send: (event: unknown) => void } - send: (event: DimensionToolEvent) => void - }, + self: DimensionToolSelf, mousePoint: Coords2d ) { if (!runtime.active || !runtime.angleContext) { @@ -731,10 +695,7 @@ function addDimensionListener({ self, }: { context: DimensionToolContext - self: { - _parent?: { send: (event: unknown) => void } - send: (event: DimensionToolEvent) => void - } + self: DimensionToolSelf }) { const runtime = context.runtime runtime.active = true From 53b1cbcd386739c0b1eec6188fd623fcd3366f2a Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 18:24:55 +0200 Subject: [PATCH 51/78] inline functions --- .../sketchSolve/tools/dimensionTool.ts | 63 ++++++------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index b829658a35c..498ca699d0c 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -113,7 +113,6 @@ type DraftRuntime = { type ApiAngleConstraint = Extract -const SECTOR_EPSILON = 1e-9 const ANGLE_SECTORS = [1, 2, 3, 4] as const satisfies ReadonlyArray const ANGLE_SECTOR_PROMPT_TOAST_ID = 'dimension-tool-angle-sector-prompt' @@ -147,17 +146,6 @@ function deactivateRuntime(runtime: DraftRuntime) { runtime.queuedMousePoint = null } -function showAngleSectorPrompt() { - toastToolbar('Move mouse to choose sector, then click to place label.', { - id: ANGLE_SECTOR_PROMPT_TOAST_ID, - duration: Number.POSITIVE_INFINITY, - }) -} - -function dismissAngleSectorPrompt() { - toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) -} - function isClickedRayDirectionForward( linePoints: readonly [Coords2d, Coords2d], vertex: Coords2d, @@ -311,16 +299,6 @@ function getInitialAngleLineSelections( ] } -function isDirectionInSector( - direction: Coords2d, - start: Coords2d, - end: Coords2d -) { - return ( - getCcwSweep(start, direction) <= getCcwSweep(start, end) + SECTOR_EPSILON - ) -} - function getVisibleAngleSelection( angleContext: DimensionAngleDirections, sector: AngleSector @@ -354,7 +332,10 @@ function getHoveredAngleSelection( getVisibleAngleSelection(angleContext, sector) ).find((selection) => { const [start, end] = getVisibleAngleSectorRays(angleContext, selection) - return isDirectionInSector(mouseDirection, start, end) + const isDirectionInSector = + getCcwSweep(start, mouseDirection) <= getCcwSweep(start, end) + 1e-9 + + return isDirectionInSector }) ?? angleContext.baseSelection ) } @@ -486,24 +467,6 @@ function sendPreviewResultToParent( }) } -function sendFinalResultToParent( - self: ParentSketchSolveSender, - result: { - kclSource: SourceDelta - sceneGraphDelta: SceneGraphDelta - checkpointId?: number | null - } -) { - sendParent(self, { - type: 'update sketch outcome', - data: { - sourceDelta: result.kclSource, - sceneGraphDelta: result.sceneGraphDelta, - checkpointId: result.checkpointId ?? null, - }, - }) -} - async function updateDraftAngleConstraint( runtime: DraftRuntime, context: DimensionToolContext, @@ -648,7 +611,14 @@ async function commitDraftAngleConstraint( const constraintId = existingConstraintId ?? getConstraintIdFromResult(result) runtime.draftConstraintId = null - sendFinalResultToParent(self, result) + sendParent(self, { + type: 'update sketch outcome', + data: { + sourceDelta: result.kclSource, + sceneGraphDelta: result.sceneGraphDelta, + checkpointId: result.checkpointId ?? null, + }, + }) sendParent(self, { type: 'clear draft entities' }) sendParent(self, { type: 'update selected ids', @@ -658,7 +628,7 @@ async function commitDraftAngleConstraint( type: 'update hovered id', data: { hoveredId: constraintId }, }) - dismissAngleSectorPrompt() + toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) self.send({ type: 'done' }) } catch (error) { runtime.active = true @@ -715,7 +685,10 @@ function addDimensionListener({ if (angleContext) { runtime.firstSelection = firstSelection runtime.angleContext = angleContext - showAngleSectorPrompt() + toastToolbar('Move mouse to choose sector, then click to place label.', { + id: ANGLE_SECTOR_PROMPT_TOAST_ID, + duration: Number.POSITIVE_INFINITY, + }) sendParent(self, { type: 'update hovered id', data: { hoveredId: null }, @@ -828,7 +801,7 @@ function removeDimensionListener({ context, }: { context: DimensionToolContext }) { deactivateRuntime(context.runtime) - dismissAngleSectorPrompt() + toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) context.sceneInfra.setCallbacks({ onClick: () => {}, onMove: () => {}, From 46782151bb4d679d4c1472651a624f745cb9fc6f Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 18:25:39 +0200 Subject: [PATCH 52/78] clarify mouse move listener in dimenstionTool --- src/machines/sketchSolve/tools/dimensionTool.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 498ca699d0c..d93053b4dc5 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -784,15 +784,16 @@ function addDimensionListener({ const mousePoint: Coords2d = [twoD.x, twoD.y] if (runtime.angleContext) { + // After both lines are selected, mouse movement updates the angle label draft. requestDraftPreview(runtime, context, self, mousePoint) - return + } else { + // Before the second line is selected, mouse movement only updates line hover. + const lineSelection = getClosestLineSelection(mousePoint, context) + sendParent(self, { + type: 'update hovered id', + data: { hoveredId: lineSelection?.id ?? null }, + }) } - - const lineSelection = getClosestLineSelection(mousePoint, context) - sendParent(self, { - type: 'update hovered id', - data: { hoveredId: lineSelection?.id ?? null }, - }) }, }) } From 9ebd2e530c616e705a3da7da09f4c9f26edd1451 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 19:15:47 +0200 Subject: [PATCH 53/78] selectedClickPoints refactor --- src/machines/sketchSolve/sketchSolveImpl.ts | 30 ++++++++------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/machines/sketchSolve/sketchSolveImpl.ts b/src/machines/sketchSolve/sketchSolveImpl.ts index 4c9da94c6da..9cf23fe0bed 100644 --- a/src/machines/sketchSolve/sketchSolveImpl.ts +++ b/src/machines/sketchSolve/sketchSolveImpl.ts @@ -815,17 +815,13 @@ export function updateSelectedIds({ event, context }: SolveAssignArgs) { ...context.selectionClickPoints, ...(event.data.selectionClickPoints ?? {}), } + let nextSelectedIds: SketchSolveSelectionId[] // If empty array is provided, clear the selection if (event.data.selectedIds.length === 0) { - updates.selectedIds = [] - updates.selectionClickPoints = {} + nextSelectedIds = [] } else if (event.data.replaceExistingSelection) { - updates.selectedIds = event.data.selectedIds - updates.selectionClickPoints = getSelectionClickPointsForIds( - event.data.selectedIds, - selectionClickPoints - ) + nextSelectedIds = event.data.selectedIds } else { const first = event.data.selectedIds[0] if ( @@ -834,24 +830,20 @@ export function updateSelectedIds({ event, context }: SolveAssignArgs) { context.selectedIds.includes(first) ) { // If only one ID is selected and it's already in the selection, remove only it from the selection - const nextSelectedIds = context.selectedIds.filter((id) => id !== first) - updates.selectedIds = nextSelectedIds - updates.selectionClickPoints = getSelectionClickPointsForIds( - nextSelectedIds, - context.selectionClickPoints - ) + nextSelectedIds = context.selectedIds.filter((id) => id !== first) } else { // Merge new IDs with existing selection - const result = Array.from( + nextSelectedIds = Array.from( new Set([...context.selectedIds, ...event.data.selectedIds]) ) - updates.selectedIds = result - updates.selectionClickPoints = getSelectionClickPointsForIds( - result, - selectionClickPoints - ) } } + + updates.selectedIds = nextSelectedIds + updates.selectionClickPoints = getSelectionClickPointsForIds( + nextSelectedIds, + selectionClickPoints + ) } return updates From 432e0ebe9f1e7e037edd2e1dc95a81baddf5ae3e Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 19:26:04 +0200 Subject: [PATCH 54/78] rename selectionClickPoints to selectionCoordinates --- .../sketchSolve/sketchSolveDiagram.ts | 4 +- src/machines/sketchSolve/sketchSolveImpl.ts | 40 +++++++++---------- .../sketchSolve/sketchSolveSelection.ts | 2 +- .../sketchSolve/tools/dimensionTool.spec.ts | 8 ++-- .../sketchSolve/tools/dimensionTool.ts | 22 +++++----- .../tools/moveTool/moveTool.spec.ts | 4 +- .../sketchSolve/tools/moveTool/moveTool.ts | 10 ++--- 7 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/machines/sketchSolve/sketchSolveDiagram.ts b/src/machines/sketchSolve/sketchSolveDiagram.ts index 008c09f9e4e..58d873ad063 100644 --- a/src/machines/sketchSolve/sketchSolveDiagram.ts +++ b/src/machines/sketchSolve/sketchSolveDiagram.ts @@ -456,7 +456,7 @@ export const sketchSolveMachine = setup({ }), 'clear selection': assign({ selectedIds: [], - selectionClickPoints: {}, + selectionCoordinates: {}, duringAreaSelectIds: [], }), 'toggle non-visual constraints': assign(({ context }) => ({ @@ -507,7 +507,7 @@ export const sketchSolveMachine = setup({ return { sketchSolveToolName: null, selectedIds: [], - selectionClickPoints: {}, + selectionCoordinates: {}, duringAreaSelectIds: [], hoveredId: null, constraintHoverPopups: [], diff --git a/src/machines/sketchSolve/sketchSolveImpl.ts b/src/machines/sketchSolve/sketchSolveImpl.ts index 9cf23fe0bed..4783fd7d782 100644 --- a/src/machines/sketchSolve/sketchSolveImpl.ts +++ b/src/machines/sketchSolve/sketchSolveImpl.ts @@ -24,7 +24,7 @@ import { } from '@src/machines/sketchSolve/segments' import { ORIGIN_TARGET, - type SelectionClickPoints, + type SelectionCoordinates, type SketchSolveSelectionId, getObjectSelectionIds, isObjectSelectionId, @@ -92,7 +92,7 @@ export { getObjectSelectionIds, isObjectSelectionId, ORIGIN_TARGET, - type SelectionClickPoints, + type SelectionCoordinates, type SketchSolveSelectionId, type SketchSpecialTarget, } from '@src/machines/sketchSolve/sketchSolveSelection' @@ -134,7 +134,7 @@ export type SketchSolveMachineEvent = selectedIds?: Array duringAreaSelectIds?: Array replaceExistingSelection?: boolean - selectionClickPoints?: SelectionClickPoints + selectionCoordinates?: SelectionCoordinates } } | { @@ -230,7 +230,7 @@ export type SketchSolveContext = { childTool?: ToolActorRef pendingToolName?: EquipTool selectedIds: Array - selectionClickPoints: SelectionClickPoints + selectionCoordinates: SelectionCoordinates duringAreaSelectIds: Array hoveredId: SketchSolveSelectionId | null constraintHoverPopups: ConstraintHoverPopup[] @@ -780,23 +780,23 @@ export function cleanupSketchSolveGroup(sceneInfra: SceneInfra) { disposeGroupChildren(sketchSegments) } -function getSelectionClickPointsForIds( +function getSelectionCoordinatesForIds( selectedIds: readonly SketchSolveSelectionId[], - selectionClickPoints: SelectionClickPoints -): SelectionClickPoints { - const nextSelectionClickPoints: SelectionClickPoints = {} + selectionCoordinates: SelectionCoordinates +): SelectionCoordinates { + const nextSelectionCoordinates: SelectionCoordinates = {} for (const selectedId of selectedIds) { if (typeof selectedId !== 'number') { continue } - const clickPoint = selectionClickPoints[selectedId] + const clickPoint = selectionCoordinates[selectedId] if (clickPoint) { - nextSelectionClickPoints[selectedId] = clickPoint + nextSelectionCoordinates[selectedId] = clickPoint } } - return nextSelectionClickPoints + return nextSelectionCoordinates } export function updateSelectedIds({ event, context }: SolveAssignArgs) { @@ -811,9 +811,9 @@ export function updateSelectedIds({ event, context }: SolveAssignArgs) { // Handle regular selectedIds update (for click selection, etc.) if (event.data.selectedIds !== undefined) { - const selectionClickPoints = { - ...context.selectionClickPoints, - ...(event.data.selectionClickPoints ?? {}), + const selectionCoordinates = { + ...context.selectionCoordinates, + ...(event.data.selectionCoordinates ?? {}), } let nextSelectedIds: SketchSolveSelectionId[] @@ -840,9 +840,9 @@ export function updateSelectedIds({ event, context }: SolveAssignArgs) { } updates.selectedIds = nextSelectedIds - updates.selectionClickPoints = getSelectionClickPointsForIds( + updates.selectionCoordinates = getSelectionCoordinatesForIds( nextSelectedIds, - selectionClickPoints + selectionCoordinates ) } @@ -859,7 +859,7 @@ export function updateSelectedIdsFromCodeSelection({ if (!objects) { return { selectedIds: [], - selectionClickPoints: {}, + selectionCoordinates: {}, duringAreaSelectIds: [], } } @@ -869,7 +869,7 @@ export function updateSelectedIdsFromCodeSelection({ getCurrentSketchObjectsById(objects, context.sketchId), event.data.ranges ), - selectionClickPoints: {}, + selectionCoordinates: {}, duringAreaSelectIds: [], } } @@ -1593,7 +1593,7 @@ export function spawnTool( kclManager: context.kclManager, sketchId: context.sketchId, initialSelectionIds: context.selectedIds, - initialSelectionClickPoints: context.selectionClickPoints, + initialSelectionCoordinates: context.selectionCoordinates, initialObjects: context.sketchExecOutcome?.sceneGraphDelta.new_graph.objects || [], toolVariant: toolVariants[nameOfToolToSpawn], @@ -1634,7 +1634,7 @@ export type ToolInput = { kclManager: KclManager sketchId: number initialSelectionIds?: SketchSolveSelectionId[] - initialSelectionClickPoints?: SelectionClickPoints + initialSelectionCoordinates?: SelectionCoordinates initialObjects?: ApiObject[] toolVariant?: string // eg. 'corner' | 'center' | 'angled' for rectTool } diff --git a/src/machines/sketchSolve/sketchSolveSelection.ts b/src/machines/sketchSolve/sketchSolveSelection.ts index ca26a1fd9f3..77938b3301d 100644 --- a/src/machines/sketchSolve/sketchSolveSelection.ts +++ b/src/machines/sketchSolve/sketchSolveSelection.ts @@ -4,7 +4,7 @@ export const ORIGIN_TARGET = 'origin' export type SketchSpecialTarget = typeof ORIGIN_TARGET export type SketchSolveSelectionId = number | SketchSpecialTarget -export type SelectionClickPoints = Partial> +export type SelectionCoordinates = Partial> export function isObjectSelectionId( id: SketchSolveSelectionId | null | undefined diff --git a/src/machines/sketchSolve/tools/dimensionTool.spec.ts b/src/machines/sketchSolve/tools/dimensionTool.spec.ts index fd1528a2168..a90469e9cf9 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.spec.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.spec.ts @@ -4,7 +4,7 @@ import type { } from '@rust/kcl-lib/bindings/FrontendApi' import type { Coords2d } from '@src/lang/util' import type { - SelectionClickPoints, + SelectionCoordinates, SketchSolveSelectionId, } from '@src/machines/sketchSolve/sketchSolveSelection' import { @@ -80,7 +80,7 @@ function createParentHarness( objects: ApiObject[], options: { initialSelectionIds?: SketchSolveSelectionId[] - initialSelectionClickPoints?: SelectionClickPoints + initialSelectionCoordinates?: SelectionCoordinates } = {} ) { const sceneInfra = createMockSceneInfra() @@ -189,7 +189,7 @@ function createParentHarness( kclManager, sketchId: 0, initialSelectionIds: options.initialSelectionIds, - initialSelectionClickPoints: options.initialSelectionClickPoints, + initialSelectionCoordinates: options.initialSelectionCoordinates, initialObjects: sceneGraphDelta.new_graph.objects, }, }, @@ -510,7 +510,7 @@ describe('dimensionTool', () => { data: { selectedIds: [10, 11], replaceExistingSelection: true, - selectionClickPoints: { + selectionCoordinates: { 10: [10, 0], 11: [5, 8.660254037844386], }, diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index d93053b4dc5..7e93dd5cd88 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -32,7 +32,7 @@ import { getCurrentSketchObjectsById } from '@src/machines/sketchSolve/sceneGrap import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' import type { SketchSolveMachineEvent } from '@src/machines/sketchSolve/sketchSolveImpl' import type { - SelectionClickPoints, + SelectionCoordinates, SketchSolveSelectionId, } from '@src/machines/sketchSolve/sketchSolveSelection' import type { BaseToolEvent } from '@src/machines/sketchSolve/tools/sharedToolTypes' @@ -44,7 +44,7 @@ type DimensionToolContext = { kclManager: KclManager sketchId: number initialSelectionIds: SketchSolveSelectionId[] - initialSelectionClickPoints: SelectionClickPoints + initialSelectionCoordinates: SelectionCoordinates initialObjects: ApiObject[] runtime: DraftRuntime } @@ -55,7 +55,7 @@ type DimensionToolInput = { kclManager: KclManager sketchId: number initialSelectionIds?: SketchSolveSelectionId[] - initialSelectionClickPoints?: SelectionClickPoints + initialSelectionCoordinates?: SelectionCoordinates initialObjects?: ApiObject[] sceneGraphDelta?: SceneGraphDelta } @@ -262,7 +262,7 @@ function getFarthestLinePointFromVertex( function getInitialAngleLineSelections( selectionIds: readonly SketchSolveSelectionId[], - selectionClickPoints: SelectionClickPoints, + selectionCoordinates: SelectionCoordinates, objects: ApiObject[] ): [LineSelection, LineSelection] | null { const lineIds = selectionIds.filter( @@ -287,13 +287,13 @@ function getInitialAngleLineSelections( { id: lineIds[0], clickPoint: - selectionClickPoints[lineIds[0]] ?? + selectionCoordinates[lineIds[0]] ?? getFarthestLinePointFromVertex(line0Points, vertex), }, { id: lineIds[1], clickPoint: - selectionClickPoints[lineIds[1]] ?? + selectionCoordinates[lineIds[1]] ?? getFarthestLinePointFromVertex(line1Points, vertex), }, ] @@ -672,7 +672,7 @@ function addDimensionListener({ const initialObjects = context.initialObjects const initialLineSelections = getInitialAngleLineSelections( context.initialSelectionIds, - context.initialSelectionClickPoints, + context.initialSelectionCoordinates, initialObjects ) if (initialLineSelections) { @@ -698,7 +698,7 @@ function addDimensionListener({ data: { selectedIds: [firstSelection.id, secondSelection.id], replaceExistingSelection: true, - selectionClickPoints: { + selectionCoordinates: { [firstSelection.id]: firstSelection.clickPoint, [secondSelection.id]: secondSelection.clickPoint, }, @@ -729,7 +729,7 @@ function addDimensionListener({ data: { selectedIds: [lineSelection.id], replaceExistingSelection: true, - selectionClickPoints: { + selectionCoordinates: { [lineSelection.id]: lineSelection.clickPoint, }, }, @@ -756,7 +756,7 @@ function addDimensionListener({ data: { selectedIds: [runtime.firstSelection.id, lineSelection.id], replaceExistingSelection: true, - selectionClickPoints: { + selectionCoordinates: { [runtime.firstSelection.id]: runtime.firstSelection.clickPoint, [lineSelection.id]: lineSelection.clickPoint, @@ -832,7 +832,7 @@ export const machine = setup({ kclManager: input.kclManager, sketchId: input.sketchId, initialSelectionIds: input.initialSelectionIds ?? [], - initialSelectionClickPoints: input.initialSelectionClickPoints ?? {}, + initialSelectionCoordinates: input.initialSelectionCoordinates ?? {}, initialObjects: input.initialObjects ?? input.sceneGraphDelta?.new_graph.objects ?? [], runtime: createRuntime(), diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts index 05b33618a28..9aef9990bb6 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts @@ -3675,7 +3675,7 @@ describe('createOnClickCallback', () => { expect(onUpdateSelectedIds).toHaveBeenCalledWith({ selectedIds: [5], duringAreaSelectIds: [], - selectionClickPoints: { + selectionCoordinates: { 5: [20, 0], }, }) @@ -3712,7 +3712,7 @@ describe('createOnClickCallback', () => { expect(onUpdateSelectedIds).toHaveBeenCalledWith({ selectedIds: [11], duringAreaSelectIds: [], - selectionClickPoints: { + selectionCoordinates: { 11: [5, 10], }, }) diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.ts index 918eb5439ca..f4957c0e3d9 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.ts @@ -56,7 +56,7 @@ import { getCurrentSketchObjectsById } from '@src/machines/sketchSolve/sceneGrap import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' import { ORIGIN_TARGET, - type SelectionClickPoints, + type SelectionCoordinates, type SketchSolveSelectionId, type SolveActionArgs, buildSegmentCtorFromObject, @@ -1073,7 +1073,7 @@ export function createOnClickCallback({ selectedIds: Array duringAreaSelectIds: Array replaceExistingSelection?: boolean - selectionClickPoints?: SelectionClickPoints + selectionCoordinates?: SelectionCoordinates }) => void onEditConstraint: (constraintId: number) => void }): (arg: { @@ -1122,7 +1122,7 @@ export function createOnClickCallback({ sceneInfra ) } - const selectionClickPoints = + const selectionCoordinates = closestSelection && typeof closestSelection.selectionId === 'number' && isLineSegment(selectedApiObject) && @@ -1133,7 +1133,7 @@ export function createOnClickCallback({ selectedIds: closestSelection ? [closestSelection.selectionId] : [], duringAreaSelectIds: [], ...(shouldReplaceSelection ? { replaceExistingSelection: true } : {}), - ...(selectionClickPoints ? { selectionClickPoints } : {}), + ...(selectionCoordinates ? { selectionCoordinates } : {}), }) } } @@ -2504,7 +2504,7 @@ export function setUpOnDragAndSelectionClickCallbacks({ selectedIds: Array duringAreaSelectIds: Array replaceExistingSelection?: boolean - selectionClickPoints?: SelectionClickPoints + selectionCoordinates?: SelectionCoordinates }) => self.send({ type: 'update selected ids', data }), onEditConstraint: (constraintId: number) => { self.send({ From 871b3f5a21b041a538c9a3b1b9a7500fe848f647 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 22:47:54 +0200 Subject: [PATCH 55/78] use utils2d function --- src/lib/utils2d.ts | 9 ++ .../sketchSolve/sketchSolveDiagram.ts | 88 ++++++------------- 2 files changed, 34 insertions(+), 63 deletions(-) diff --git a/src/lib/utils2d.ts b/src/lib/utils2d.ts index bfcaa42ab77..7e97ea9f9cb 100644 --- a/src/lib/utils2d.ts +++ b/src/lib/utils2d.ts @@ -1,6 +1,8 @@ import type { Coords2d } from '@src/lang/util' import { getAngle } from '@src/lib/utils' +export type LineCoords = readonly [Coords2d, Coords2d] + export function deg2Rad(deg: number): number { return (deg * Math.PI) / 180 } @@ -101,6 +103,13 @@ export function isParallel( return Math.abs(cross2d(a, b) / denominator) < Math.sin(epsilonRadians) } +export function linesAreParallel(line1: LineCoords, line2: LineCoords) { + const line1Dir = subVec(line1[1], line1[0]) + const line2Dir = subVec(line2[1], line2[0]) + + return isParallel(line1Dir, line2Dir) +} + export function addVec(a: Coords2d, b: Coords2d): Coords2d { return [a[0] + b[0], a[1] + b[1]] } diff --git a/src/machines/sketchSolve/sketchSolveDiagram.ts b/src/machines/sketchSolve/sketchSolveDiagram.ts index 58d873ad063..db217f28c97 100644 --- a/src/machines/sketchSolve/sketchSolveDiagram.ts +++ b/src/machines/sketchSolve/sketchSolveDiagram.ts @@ -5,6 +5,7 @@ import type { } from '@rust/kcl-lib/bindings/FrontendApi' import { toggleSketchExtension } from '@src/editor/plugins/sketch' import type { KclManager } from '@src/lang/KclManager' +import type { Coords2d } from '@src/lang/util' import { baseUnitToNumericSuffix, distanceBetweenPoint2DExpr, @@ -12,19 +13,23 @@ import { import { SKETCH_FILE_VERSION } from '@src/lib/constants' import { jsAppSettings } from '@src/lib/settings/settingsUtils' import { roundOff } from '@src/lib/utils' +import { type LineCoords, distance2d, linesAreParallel } from '@src/lib/utils2d' import type { DefaultPlane, ExtrudeFacePlane, OffsetPlane, } from '@src/machines/modelingSharedTypes' import { + PointSegment, buildCircularSizeDimensionConstraintInput, + getLinePoints, isArcSegment, isCircleSegment, isControlPointSplineSegment, isLineSegment, isOwnedLineSegment, isPointSegment, + pointToCoords2d, } from '@src/machines/sketchSolve/constraints/constraintUtils' import { toastSketchSolveError } from '@src/machines/sketchSolve/sketchSolveErrors' import { @@ -115,19 +120,14 @@ async function runSketchSolveToolbarAction( function getSelectionPointCoords( selection: ApiObject | typeof ORIGIN_TARGET | undefined -) { +): Coords2d | null { if (selection === ORIGIN_TARGET) { - return { x: 0, y: 0 } + return [0, 0] } - if (!isPointSegment(selection)) { return null } - - return { - x: selection.kind.segment.position.x.value, - y: selection.kind.segment.position.y.value, - } + return pointToCoords2d(selection) } function getPointCoordsById(objects: ApiObject[], pointId: number) { @@ -135,24 +135,10 @@ function getPointCoordsById(objects: ApiObject[], pointId: number) { return getSelectionPointCoords(point) } -function getLineCoords(objects: ApiObject[], line: ApiObject | undefined) { - if (!isLineSegment(line)) { - return null - } - - const start = getPointCoordsById(objects, line.kind.segment.start) - const end = getPointCoordsById(objects, line.kind.segment.end) - if (!start || !end) { - return null - } - - return { start, end } -} - function getCircularCoords( objects: ApiObject[], circular: ApiObject | undefined -) { +): { center: Coords2d; radius: number } | null { if (!isArcSegment(circular) && !isCircleSegment(circular)) { return null } @@ -165,47 +151,28 @@ function getCircularCoords( return { center, - radius: Math.hypot(start.x - center.x, start.y - center.y), + radius: distance2d(start, center), } } -function pointToLineDistance( - point: { x: number; y: number }, - line: { start: { x: number; y: number }; end: { x: number; y: number } } -) { - const dx = line.end.x - line.start.x - const dy = line.end.y - line.start.y +function pointToLineDistance(point: Coords2d, line: LineCoords) { + const dx = line[1][0] - line[0][0] + const dy = line[1][1] - line[0][1] const length = Math.hypot(dx, dy) if (length === 0) { return null } return Math.abs( - ((point.x - line.start.x) * dy - (point.y - line.start.y) * dx) / length + ((point[0] - line[0][0]) * dy - (point[1] - line[0][1]) * dx) / length ) } function pointToCircularDistance( - point: { x: number; y: number }, - circular: { center: { x: number; y: number }; radius: number } + point: Coords2d, + circular: { center: Coords2d; radius: number } ) { - return Math.abs( - Math.hypot(point.x - circular.center.x, point.y - circular.center.y) - - circular.radius - ) -} - -function linesAreParallel( - line1: { start: { x: number; y: number }; end: { x: number; y: number } }, - line2: { start: { x: number; y: number }; end: { x: number; y: number } } -) { - const dx1 = line1.end.x - line1.start.x - const dy1 = line1.end.y - line1.start.y - const dx2 = line2.end.x - line2.start.x - const dy2 = line2.end.y - line2.start.y - const scale = Math.hypot(dx1, dy1) * Math.hypot(dx2, dy2) - - return scale !== 0 && Math.abs(dx1 * dy2 - dy1 * dx2) <= 1e-9 * scale + return Math.abs(distance2d(point, circular.center) - circular.radius) } function getCurrentDistanceBetweenSelections( @@ -216,13 +183,13 @@ function getCurrentDistanceBetweenSelections( const point1 = getSelectionPointCoords(first) const point2 = getSelectionPointCoords(second) if (point1 && point2) { - return Math.hypot(point2.x - point1.x, point2.y - point1.y) + return distance2d(point2, point1) } const firstObject = first === ORIGIN_TARGET ? undefined : first const secondObject = second === ORIGIN_TARGET ? undefined : second - const firstLine = getLineCoords(objects, firstObject) - const secondLine = getLineCoords(objects, secondObject) + const firstLine = getLinePoints(firstObject, objects) + const secondLine = getLinePoints(secondObject, objects) const firstCircular = getCircularCoords(objects, firstObject) const secondCircular = getCircularCoords(objects, secondObject) @@ -258,17 +225,14 @@ function getCurrentDistanceBetweenSelections( if (firstCircular && secondCircular) { return Math.abs( - Math.hypot( - firstCircular.center.x - secondCircular.center.x, - firstCircular.center.y - secondCircular.center.y - ) - + distance2d(firstCircular.center, secondCircular.center) - firstCircular.radius - secondCircular.radius ) } if (firstLine && secondLine && linesAreParallel(firstLine, secondLine)) { - return pointToLineDistance(firstLine.start, secondLine) + return pointToLineDistance(firstLine[0], secondLine) } return null @@ -317,8 +281,8 @@ async function addAxisDistanceConstraint( if (point1 && point2) { const signedDistance = axis === 'horizontal' - ? roundOff(point2.x - point1.x) - : roundOff(point2.y - point1.y) + ? roundOff(point2[0] - point1[0]) + : roundOff(point2[1] - point1[1]) if (signedDistance < 0) { segmentsToConstrain = [segmentsToConstrain[1], segmentsToConstrain[0]] @@ -649,9 +613,7 @@ export const sketchSolveMachine = setup({ const point1 = getSelectionPointCoords(first) const point2 = getSelectionPointCoords(second) if (point1 && point2) { - distance = roundOff( - Math.hypot(point2.x - point1.x, point2.y - point1.y) - ) + distance = roundOff(distance2d(point2, point1)) } } } else if (currentSelections.length === 1) { From 12e2b76e876fc32c6655f8d8efa18eb36d0236ab Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 23:04:25 +0200 Subject: [PATCH 56/78] lint --- src/machines/sketchSolve/sketchSolveDiagram.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machines/sketchSolve/sketchSolveDiagram.ts b/src/machines/sketchSolve/sketchSolveDiagram.ts index dc9353ceaff..844c4249fd2 100644 --- a/src/machines/sketchSolve/sketchSolveDiagram.ts +++ b/src/machines/sketchSolve/sketchSolveDiagram.ts @@ -20,7 +20,6 @@ import type { OffsetPlane, } from '@src/machines/modelingSharedTypes' import { - PointSegment, buildCircularSizeDimensionConstraintInput, getLinePoints, isArcSegment, From a93df6e049beb5dd6774d7167c9533bd3425e8a3 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Thu, 25 Jun 2026 23:54:02 +0200 Subject: [PATCH 57/78] revert optional unlabeled arg for angle --- rust/kcl-lib/src/execution/exec_ast.rs | 2 +- rust/kcl-lib/src/execution/fn_call.rs | 29 +++++++++---------------- rust/kcl-lib/src/execution/kcl_value.rs | 10 ++------- rust/kcl-lib/std/solver.kcl | 2 +- 4 files changed, 14 insertions(+), 29 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 9b8cf46777e..5a8bf84dd72 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -6152,7 +6152,7 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn angle_dimension_with_sector_allows_missing_unlabeled_input() { + async fn angle_dimension_with_sector_uses_named_lines() { parse_execute( r#" sketch(on = XY) { diff --git a/rust/kcl-lib/src/execution/fn_call.rs b/rust/kcl-lib/src/execution/fn_call.rs index 7d5abee5816..81815b29859 100644 --- a/rust/kcl-lib/src/execution/fn_call.rs +++ b/rust/kcl-lib/src/execution/fn_call.rs @@ -63,7 +63,7 @@ impl ArgsStatus for Sugary {} // Invariants guaranteed by the `Desugared` status: // - There is either 0 or 1 unlabeled arguments // - Any lableled args are in the labeled map, and not the unlabeled Vec. -// - The arguments match the type signature of the function, allowing omitted optional args +// - The arguments match the type signature of the function exactly // - pipe_value.is_none() #[derive(Debug, Clone)] pub struct Desugared; @@ -867,7 +867,6 @@ fn type_check_params_kw( if let Some(l) = l && fn_def.named_args.contains_key(l) && !args.labeled.contains_key(l) - && !(fn_name == Some("angle") && l == "lines") { true } else { @@ -880,7 +879,7 @@ fn type_check_params_kw( debug_assert!(previous.is_none()); } - if let Some((name, ty, default_value)) = &fn_def.input_arg { + if let Some((name, ty)) = &fn_def.input_arg { // Expecting an input arg if args.unlabeled.is_empty() { @@ -901,8 +900,6 @@ fn type_check_params_kw( ), )); result.unlabeled = vec![(Some(name.clone()), arg)]; - } else if default_value.is_some() { - // Optional @input was omitted. } else { // Just missing return Err(KclError::new_argument(KclErrorDetails::new( @@ -1127,25 +1124,19 @@ fn assign_args_to_params_kw( } } - if let Some((param_name, _, default_value)) = &fn_def.input_arg { - if let Some(unlabeled) = args.unlabeled_kw_arg_unconverted() { - exec_state.mut_stack().add( - param_name.clone(), - unlabeled.value.clone(), - unlabeled.source_ranges().pop().unwrap_or(SourceRange::synthetic()), - )?; - } else if let Some(default_value) = default_value { - let value = KclValue::from_default_param(default_value.clone(), exec_state); - exec_state - .mut_stack() - .add(param_name.clone(), value, default_value.source_range())?; - } else { + if let Some((param_name, _)) = &fn_def.input_arg { + let Some(unlabeled) = args.unlabeled_kw_arg_unconverted() else { debug_assert!(false, "Bad args"); return Err(KclError::new_internal(KclErrorDetails::new( "Desugared arguments are inconsistent".to_owned(), source_ranges, ))); - } + }; + exec_state.mut_stack().add( + param_name.clone(), + unlabeled.value.clone(), + unlabeled.source_ranges().pop().unwrap_or(SourceRange::synthetic()), + )?; } Ok(()) diff --git a/rust/kcl-lib/src/execution/kcl_value.rs b/rust/kcl-lib/src/execution/kcl_value.rs index 05d52234956..38e34a38c25 100644 --- a/rust/kcl-lib/src/execution/kcl_value.rs +++ b/rust/kcl-lib/src/execution/kcl_value.rs @@ -206,7 +206,7 @@ pub struct NamedParam { #[derive(Debug, Clone, PartialEq)] pub struct FunctionSource { - pub input_arg: Option<(String, Option, Option)>, + pub input_arg: Option<(String, Option)>, pub named_args: IndexMap, pub return_type: Option>, pub deprecated: bool, @@ -272,12 +272,7 @@ impl FunctionSource { } #[expect(clippy::type_complexity)] - fn args_from_ast( - ast: &FunctionExpression, - ) -> ( - Option<(String, Option, Option)>, - IndexMap, - ) { + fn args_from_ast(ast: &FunctionExpression) -> (Option<(String, Option)>, IndexMap) { let mut input_arg = None; let mut named_args = IndexMap::new(); for p in &ast.params { @@ -285,7 +280,6 @@ impl FunctionSource { input_arg = Some(( p.identifier.name.clone(), p.param_type.as_ref().map(|t| t.inner.clone()), - p.default_value.clone(), )); continue; } diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index 2ea463bad4e..edba5653782 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -445,7 +445,7 @@ export fn perpendicular( @(impl = std_rust_constraint, feature_tree = true) export fn angle( /// The two line segments whose relative angle should match the value set with `==`. - @input?: [Segment; 2], + @input: [Segment; 2], /// The desired position of the constraint label. labelPosition?: Point2d, ) {} From 4569975d350c9a924c82f1cb748224e0c49dd6bc Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 30 Jun 2026 15:39:55 +0200 Subject: [PATCH 58/78] remove dead code --- src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts index ba755307e22..9f29d6e40ec 100644 --- a/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts +++ b/src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts @@ -172,7 +172,6 @@ export function calculateArcRenderInput( ) : radiusSigned - //const signedAngle = getSignedAngleBetweenVec(line1Dir, line2Dir) const signedAngle = normalizeAngleRad(obj.kind.constraint.angle) const explicitLabelPosition = getAngleLabelPosition(obj) From fbe52eea63c1543d8502ee77ffcb39d75181fc39 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 30 Jun 2026 22:57:58 +0200 Subject: [PATCH 59/78] deprecate angle constraint --- rust/kcl-lib/std/solver.kcl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index ca1f9f64178..610397290e5 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -429,6 +429,8 @@ export fn perpendicular( /// Constrain lines to meet at a given angle. /// +/// Deprecated as of KCL 2.0. Use `angleDimension` for new angle constraints. +/// /// ```kcl,sketchSolve /// profile = sketch(on = XY) { /// line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) @@ -442,7 +444,7 @@ export fn perpendicular( /// /// solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2) /// ``` -@(impl = std_rust_constraint, feature_tree = true) +@(impl = std_rust_constraint, feature_tree = true, deprecated_since = "2.0") export fn angle( /// The two line segments whose relative angle should match the value set with `==`. @input: [Segment; 2], From 9ac6476dc216456e6155c40eea6e2a270006d4ea Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 30 Jun 2026 23:12:39 +0200 Subject: [PATCH 60/78] missing angleRadius test --- rust/kcl-derive-docs/src/example_tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/kcl-derive-docs/src/example_tests.rs b/rust/kcl-derive-docs/src/example_tests.rs index 3203e35d2c2..34c4c8a4599 100644 --- a/rust/kcl-derive-docs/src/example_tests.rs +++ b/rust/kcl-derive-docs/src/example_tests.rs @@ -285,6 +285,7 @@ pub const TEST_NAMES: &[&str] = &[ "std-solver-parallel-0", "std-solver-perpendicular-0", "std-solver-angle-0", + "std-solver-angleDimension-0", "std-solver-symmetric-0", "std-solver-tangent-0", "std-solver-horizontal-0", From c10a6d20aae1893e8d29e02035d4d1a2ad78f7e9 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sat, 4 Jul 2026 20:10:53 +0200 Subject: [PATCH 61/78] generate kcl docs --- docs/kcl-std/functions/std-solver-angle.md | 10 +++- .../functions/std-solver-angleDimension.md | 58 +++++++++++++++++++ docs/kcl-std/index.md | 1 + docs/kcl-std/modules/std-solver.md | 1 + 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 docs/kcl-std/functions/std-solver-angleDimension.md diff --git a/docs/kcl-std/functions/std-solver-angle.md b/docs/kcl-std/functions/std-solver-angle.md index 3b21024acce..56a6d657b0f 100644 --- a/docs/kcl-std/functions/std-solver-angle.md +++ b/docs/kcl-std/functions/std-solver-angle.md @@ -5,19 +5,25 @@ excerpt: "Constrain lines to meet at a given angle." layout: manual --- +**WARNING:** This function is deprecated as of KCL 2.0. + Constrain lines to meet at a given angle. ```kcl -solver::angle(@input: [Segment; 2]) +solver::angle( + @input: [Segment; 2], + labelPosition?: Point2d, +) ``` - +Deprecated as of KCL 2.0. Use `angleDimension` for new angle constraints. ### Arguments | Name | Type | Description | Required | |----------|------|-------------|----------| | `input` | [[`Segment`](/docs/kcl-std/types/std-types-Segment); 2] | The two line segments whose relative angle should match the value set with `==`. | Yes | +| `labelPosition` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The desired position of the constraint label. | No | ### Examples diff --git a/docs/kcl-std/functions/std-solver-angleDimension.md b/docs/kcl-std/functions/std-solver-angleDimension.md new file mode 100644 index 00000000000..fb24077b43e --- /dev/null +++ b/docs/kcl-std/functions/std-solver-angleDimension.md @@ -0,0 +1,58 @@ +--- +title: "solver::angleDimension" +subtitle: "Function in std::solver" +excerpt: "Constrain a specific angle dimension sector between two lines." +layout: manual +--- + +Constrain a specific angle dimension sector between two lines. + +```kcl +solver::angleDimension( + lines: [Segment; 2], + sector: number(_), + inverse?: bool, + labelPosition?: Point2d, +) +``` + + + +### Arguments + +| Name | Type | Description | Required | +|----------|------|-------------|----------| +| `lines` | [[`Segment`](/docs/kcl-std/types/std-types-Segment); 2] | The two line segments whose selected angle sector should match the value set with `==`. | Yes | +| `sector` | [`number(_)`](/docs/kcl-std/types/std-types-number) | Which of the four angle sectors to constrain, numbered around the line intersection. | Yes | +| `inverse` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether to constrain the inverse of the selected sector. | No | +| `labelPosition` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The desired position of the constraint label. | No | + + +### Examples + +```kcl +profile = sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angleDimension(lines = [line1, line2], sector = 1) == 60deg +} + +solid = extrude(region(point = [2mm, 1mm], sketch = profile), length = 2) + +``` + + + + + + diff --git a/docs/kcl-std/index.md b/docs/kcl-std/index.md index b37e88101ce..d187ef59d46 100644 --- a/docs/kcl-std/index.md +++ b/docs/kcl-std/index.md @@ -165,6 +165,7 @@ layout: manual * [`union`](/docs/kcl-std/functions/std-solid-union) * [**std::solver**](/docs/kcl-std/modules/std-solver) * [`solver::angle`](/docs/kcl-std/functions/std-solver-angle) + * [`solver::angleDimension`](/docs/kcl-std/functions/std-solver-angleDimension) * [`solver::arc`](/docs/kcl-std/functions/std-solver-arc) * [`solver::circle`](/docs/kcl-std/functions/std-solver-circle) * [`solver::coincident`](/docs/kcl-std/functions/std-solver-coincident) diff --git a/docs/kcl-std/modules/std-solver.md b/docs/kcl-std/modules/std-solver.md index b6fad3cde33..645cf2a958a 100644 --- a/docs/kcl-std/modules/std-solver.md +++ b/docs/kcl-std/modules/std-solver.md @@ -47,6 +47,7 @@ functions, because those are what actually constrain the solved result. * [`solver::ORIGIN`](/docs/kcl-std/consts/std-solver-ORIGIN) * [`solver::angle`](/docs/kcl-std/functions/std-solver-angle) +* [`solver::angleDimension`](/docs/kcl-std/functions/std-solver-angleDimension) * [`solver::arc`](/docs/kcl-std/functions/std-solver-arc) * [`solver::circle`](/docs/kcl-std/functions/std-solver-circle) * [`solver::coincident`](/docs/kcl-std/functions/std-solver-coincident) From 4cefe63c1547b7a8fe1419434b831d6bc236a6d4 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 7 Jul 2026 18:03:34 +0200 Subject: [PATCH 62/78] update kcl-samples with angleDimension (1 left) --- public/kcl-samples/angle-gauge/main.kcl | 11 +++++++---- public/kcl-samples/artificial-heart/housing.kcl | 2 +- public/kcl-samples/artificial-heart/impeller.kcl | 2 +- public/kcl-samples/artificial-heart/plumbing.kcl | 2 +- public/kcl-samples/artificial-heart/stator.kcl | 2 +- public/kcl-samples/axial-fan/fan-housing.kcl | 2 +- public/kcl-samples/cycloidal-gear/main.kcl | 4 ++-- public/kcl-samples/field-monitor-stand/main.kcl | 2 +- public/kcl-samples/m4-insert/main.kcl | 2 +- public/kcl-samples/wheel-hub/main.kcl | 2 +- public/kcl-samples/zoo-logo/main.kcl | 4 ++-- 11 files changed, 19 insertions(+), 16 deletions(-) diff --git a/public/kcl-samples/angle-gauge/main.kcl b/public/kcl-samples/angle-gauge/main.kcl index e00195ea56b..8088291835f 100644 --- a/public/kcl-samples/angle-gauge/main.kcl +++ b/public/kcl-samples/angle-gauge/main.kcl @@ -88,10 +88,13 @@ gaugeProfileSketch = sketch(on = XY) { horizontal(cutoutTopEdge) horizontal(cutoutAngleReferenceEdge) vertical(cutoutLeftVerticalEdge) - angle([ - cutoutAngleReferenceEdge, - cutoutAngledEdge -]) == cutoutAngle + angleDimension( + lines = [ + cutoutAngleReferenceEdge, + cutoutAngledEdge + ], + sector = 1, + ) == cutoutAngle horizontalDistance([cutoutTopEdge.start, cutoutTopEdge.end]) == cutoutDepth verticalDistance([ diff --git a/public/kcl-samples/artificial-heart/housing.kcl b/public/kcl-samples/artificial-heart/housing.kcl index fdfacc3bec3..c0cd14b676f 100644 --- a/public/kcl-samples/artificial-heart/housing.kcl +++ b/public/kcl-samples/artificial-heart/housing.kcl @@ -213,7 +213,7 @@ sketch007 = sketch(on = XY) { line2 = line(start = [var 0.48in, var 0.75in], end = [var 0.53in, var 1.23in], construction = true) coincident([line2.start, arc1.center]) coincident([line2.end, arc2.start]) - angle([line2, line1]) == 6 + angleDimension(lines = [line2, line1], sector = 1, labelPosition = [0.28in, 1.38in]) == 6 } // Model the profile of the rear inlet bung, then sweep diff --git a/public/kcl-samples/artificial-heart/impeller.kcl b/public/kcl-samples/artificial-heart/impeller.kcl index a277b62b67e..ed82fe47b52 100644 --- a/public/kcl-samples/artificial-heart/impeller.kcl +++ b/public/kcl-samples/artificial-heart/impeller.kcl @@ -105,7 +105,7 @@ sketch003 = sketch(on = offsetPlane(XZ, offset = 0.4)) { coincident([arc3.center, arc1.center]) tangent([arc1, arc2]) tangent([arc3, arc4]) - angle([line2, line3]) == 85 + angleDimension(lines = [line2, line3], labelPosition = [0.12in, 0.16in], sector = 3) == 85 distance([line2.start, line2.end]) == 1.4 coincident([line2.start, arc4.center]) } diff --git a/public/kcl-samples/artificial-heart/plumbing.kcl b/public/kcl-samples/artificial-heart/plumbing.kcl index 126940a7535..cd0619233fc 100644 --- a/public/kcl-samples/artificial-heart/plumbing.kcl +++ b/public/kcl-samples/artificial-heart/plumbing.kcl @@ -17,7 +17,7 @@ sketch002 = sketch(on = XZ) { coincident([line3.start, line1.start]) horizontal([line3.end, ORIGIN]) horizontal(line3) - angle([line1, line3]) == 45 + angleDimension(lines = [line1, line3], sector = 1) == 45 distance([line1.start, line1.end]) == 1.65in radius(arc1) == 3.2 / 2 circle1 = circle(start = [var 1.18in, var 0.93in], center = [var 0in, var 0in], construction = true) diff --git a/public/kcl-samples/artificial-heart/stator.kcl b/public/kcl-samples/artificial-heart/stator.kcl index 94b17827750..cc829107759 100644 --- a/public/kcl-samples/artificial-heart/stator.kcl +++ b/public/kcl-samples/artificial-heart/stator.kcl @@ -42,7 +42,7 @@ sketch002 = sketch(on = XZ) { symmetric([line2, line1], axis = line3) symmetric([arc2, arc1], axis = line3) tangent([arc3, arc1]) - angle([line1, line2]) == 180 - 30 + angleDimension(lines = [line1, line2], sector = 2, labelPosition = [0in, 1.16in]) == 30 tangent([arc5, arc6]) verticalDistance([line3.start, arc2.center]) == 1 horizontalDistance([arc1.center, arc2.center]) == .1 diff --git a/public/kcl-samples/axial-fan/fan-housing.kcl b/public/kcl-samples/axial-fan/fan-housing.kcl index c350162b523..e37c8b706b0 100644 --- a/public/kcl-samples/axial-fan/fan-housing.kcl +++ b/public/kcl-samples/axial-fan/fan-housing.kcl @@ -201,7 +201,7 @@ sketch003 = sketch(on = XY) { coincident([line6.end, line4.start]) equalLength([line5, line6]) verticalDistance([line5.start, line5.end]) == 6 - angle([line3, line2]) == 60 + angleDimension(lines = [line3, line2], sector = 4, labelPosition = [7.16mm, 24.34mm]) == 120deg horizontalDistance([line1.start, arc4.center]) == 0.02mm coincident([arc4.center, line4]) } diff --git a/public/kcl-samples/cycloidal-gear/main.kcl b/public/kcl-samples/cycloidal-gear/main.kcl index 02f679a7ee8..35dd98ac88e 100644 --- a/public/kcl-samples/cycloidal-gear/main.kcl +++ b/public/kcl-samples/cycloidal-gear/main.kcl @@ -40,8 +40,8 @@ outerProfile = sketch(on = XY) { vertical(c2ToC1) vertical(c1ToC6) - angle([baseline, c2ToC3]) == 150deg - angle([baseline, c4ToC5]) == 30deg + angleDimension(lines = [baseline, c2ToC3], sector = 3, labelPosition = [-1.23in, -0.83in]) == 150deg + angleDimension(lines = [baseline, c4ToC5], sector = 1, labelPosition = [-0.22in, 0.19in]) == 30deg parallel([c2ToC3, c3ToC4]) parallel([c4ToC5, c5ToC6]) diff --git a/public/kcl-samples/field-monitor-stand/main.kcl b/public/kcl-samples/field-monitor-stand/main.kcl index 4ccf1f53eb7..fe94e9ff6e8 100644 --- a/public/kcl-samples/field-monitor-stand/main.kcl +++ b/public/kcl-samples/field-monitor-stand/main.kcl @@ -60,7 +60,7 @@ bodyProfile = sketch(on = YZ) { distance([line2.start, line2.end]) == plateLength distance([line3.start, line3.end]) == width distance([line6.start, line6.end]) == width - angle([line1, line2]) == plateAngle + angleDimension(lines = [line1, line2], sector = 1, labelPosition = [3.15mm, 3.38mm]) == plateAngle } bodyRegion = region(segments = [bodyProfile.line1, bodyProfile.line2]) diff --git a/public/kcl-samples/m4-insert/main.kcl b/public/kcl-samples/m4-insert/main.kcl index d71411af0e2..cc24c8b2da2 100644 --- a/public/kcl-samples/m4-insert/main.kcl +++ b/public/kcl-samples/m4-insert/main.kcl @@ -70,7 +70,7 @@ insertProfileSketch = sketch(on = XY) { horizontalDistance([midWall.start, centerGuide.end]) == insertGuideDiameter horizontalDistance([bottomBridge.end, centerGuide.end]) == insertLowerBandDiameter / 2 verticalDistance([innerWall.end, innerWall.start]) == insertOverallHeight - angle([midWall, taperFlank]) == taperAngle + angleDimension(lines = [midWall, taperFlank], sector = 1, labelPosition = [-2.83mm, -6.02mm]) == taperAngle } insertProfileRegion = region(point = [-3.1475mm, -1.14mm], sketch = insertProfileSketch) diff --git a/public/kcl-samples/wheel-hub/main.kcl b/public/kcl-samples/wheel-hub/main.kcl index 2bf35f917d7..a1f4c227f51 100644 --- a/public/kcl-samples/wheel-hub/main.kcl +++ b/public/kcl-samples/wheel-hub/main.kcl @@ -163,7 +163,7 @@ trimProfile = sketch(on = XY) { startOffsetGuide.end ]) == rotorBore / 2 distance([line1.start, line1.end]) == lugSpacing / 3 - angle([startOffsetGuide, line1]) == 10deg + angleDimension(lines = [startOffsetGuide, line1], sector = 1, labelPosition = [2.17in, -0.69in]) == 10deg distance([line2.start, line2.end]) == hubSpacing * 1.5 } diff --git a/public/kcl-samples/zoo-logo/main.kcl b/public/kcl-samples/zoo-logo/main.kcl index 5a5178fb1a3..3c454ef6dc5 100644 --- a/public/kcl-samples/zoo-logo/main.kcl +++ b/public/kcl-samples/zoo-logo/main.kcl @@ -187,7 +187,7 @@ logoSketch = sketch(on = XY) { parallel([o1Guide01, o1Guide02]) equalLength([o1Guide01, o1Guide02]) - angle([frameBottom, o1Line01]) == 47deg + angleDimension(lines = [frameBottom, o1Line01], sector = 1, labelPosition = [1.06in, 0.06in]) == 47deg horizontalDistance([frameLeft.end, o1GuideArc04.center]) == logoHeight * 1.448 verticalDistance([frameLeft.end, o1GuideArc04.center]) == logoHeight * 0.5 radius(o1Arc03) == logoHeight * 0.5 @@ -269,7 +269,7 @@ logoSketch = sketch(on = XY) { horizontalDistance([o2Arc04.center, frameRight.start]) == logoHeight * 0.5 verticalDistance([frameRight.start, o2Arc04.center]) == logoHeight * 0.5 distance([o2GuideArc04.end, o2GuideArc04.start]) == logoHeight * 0.1 - angle([frameBottom, o2Line03]) == 47deg + angleDimension(lines = [frameBottom, o2Line03], sector = 1, labelPosition = [2.2in, 0.04in]) == 47deg radius(o2Arc02) == logoHeight * 0.5 radius(o2Arc03) == logoHeight * 0.27 From 287dac51161629e42f1936b76aec35fc9376400b Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 7 Jul 2026 22:12:19 +0200 Subject: [PATCH 63/78] update robot-arm sample to angleDimension --- .../multi-axis-robot/robot-arm-base.kcl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/public/kcl-samples/multi-axis-robot/robot-arm-base.kcl b/public/kcl-samples/multi-axis-robot/robot-arm-base.kcl index 24a87c3e1e0..45a9709beaa 100644 --- a/public/kcl-samples/multi-axis-robot/robot-arm-base.kcl +++ b/public/kcl-samples/multi-axis-robot/robot-arm-base.kcl @@ -49,7 +49,7 @@ sketch004 = sketch(on = XY) { horizontal([line14.end, ORIGIN]) horizontal(line14) horizontal(line13) - angle([line13, line5]) == 34 + angleDimension(lines = [line13, line5], sector = 1) == 34 line15 = line(start = [var 0in, var 0in], end = [var 0in, var 4.46in], construction = true) coincident([line15.start, line5.start]) vertical([line15.end, ORIGIN]) @@ -58,13 +58,13 @@ sketch004 = sketch(on = XY) { vertical([line16.end, ORIGIN]) vertical(line16) vertical(line15) - angle([line6, line15]) == 34 - angle([line15, line7]) == 34 - angle([line8, line14]) == 34 - angle([line14, line9]) == 34 - angle([line10, line16]) == 34 - angle([line16, line11]) == 34 - angle([line12, line13]) == 34 + angleDimension(lines = [line6, line15], sector = 1) == 34 + angleDimension(lines = [line15, line7], sector = 1) == 34 + angleDimension(lines = [line8, line14], sector = 1) == 34 + angleDimension(lines = [line14, line9], sector = 1) == 34 + angleDimension(lines = [line10, line16], sector = 1) == 34 + angleDimension(lines = [line16, line11], sector = 1) == 34 + angleDimension(lines = [line12, line13], sector = 1) == 34 distance([line12.start, line12.end]) == 5.35 circle1 = circle(start = [var 4.54in, var 2.61in], center = [var 4.43in, var 2.99in]) coincident([circle1.center, line5.end]) From 503929a31adf5bca1ae8f45295dc08f526f0246d Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 8 Jul 2026 00:07:25 +0200 Subject: [PATCH 64/78] angleDimension autocomplete --- rust/kcl-lib/src/docs/kcl_doc.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rust/kcl-lib/src/docs/kcl_doc.rs b/rust/kcl-lib/src/docs/kcl_doc.rs index 3999fa9f1a0..b7f95853169 100644 --- a/rust/kcl-lib/src/docs/kcl_doc.rs +++ b/rust/kcl-lib/src/docs/kcl_doc.rs @@ -703,7 +703,12 @@ impl FnData { } pub(super) fn to_autocomplete_snippet(&self) -> String { - if self.name == "loft" { + if self.name == "angleDimension" { + return format!( + "{}(lines = [${{1:line1}}, ${{2:line2}}], sector = ${{3:1}})", + self.preferred_name + ); + } else if self.name == "loft" { return "loft([${0:sketch000}, ${1:sketch001}])".to_owned(); } else if self.name == "union" { return "union([${0:extrude001}, ${1:extrude002}])".to_owned(); From 7d34b2467f6368d22119d9f3037b101866540059 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 8 Jul 2026 16:04:08 +0200 Subject: [PATCH 65/78] fmt --- src/machines/sketchSolve/tools/dimensionTool.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/machines/sketchSolve/tools/dimensionTool.ts b/src/machines/sketchSolve/tools/dimensionTool.ts index 7e93dd5cd88..c444e5cbe9b 100644 --- a/src/machines/sketchSolve/tools/dimensionTool.ts +++ b/src/machines/sketchSolve/tools/dimensionTool.ts @@ -800,7 +800,9 @@ function addDimensionListener({ function removeDimensionListener({ context, -}: { context: DimensionToolContext }) { +}: { + context: DimensionToolContext +}) { deactivateRuntime(context.runtime) toastToolbar.dismiss(ANGLE_SECTOR_PROMPT_TOAST_ID) context.sceneInfra.setCallbacks({ From 68657965f2cc5f4f81433c778ce39b2a8765dc59 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Wed, 8 Jul 2026 16:04:56 +0200 Subject: [PATCH 66/78] sector autocomplete should be 1 --- rust/kcl-lib/src/docs/kcl_doc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/kcl-lib/src/docs/kcl_doc.rs b/rust/kcl-lib/src/docs/kcl_doc.rs index b7f95853169..43176969194 100644 --- a/rust/kcl-lib/src/docs/kcl_doc.rs +++ b/rust/kcl-lib/src/docs/kcl_doc.rs @@ -1008,6 +1008,7 @@ impl ArgData { "angleEnd" => "180deg", "angle" => "180deg", "arcDegrees" => "360deg", + "sector" => "1", _ => "10", }; Some((index, format!(r#"{label}${{{index}:{value}}}"#))) From d50a159aa32283f6e5ca22a8377983871f176e35 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 12 Jul 2026 22:11:17 +0200 Subject: [PATCH 67/78] Z007 angle lint --- rust/kcl-lib/src/execution/cache.rs | 1 + rust/kcl-lib/src/execution/exec_ast.rs | 231 +++++++++++++++++- rust/kcl-lib/src/execution/mod.rs | 5 + rust/kcl-lib/src/execution/state.rs | 44 ++++ rust/kcl-lib/src/frontend.rs | 3 + rust/kcl-lib/src/lib.rs | 2 + rust/kcl-lib/src/lint/checks/legacy_angle.rs | 56 +++++ rust/kcl-lib/src/lint/checks/mod.rs | 3 + rust/kcl-lib/src/parsing/ast/types/mod.rs | 1 + .../consumed_solid_original_issue/lints.snap | 23 ++ .../sketch_block_angle_constraint/lints.snap | 40 +++ src/lang/KclManager.ts | 1 + src/lang/langHelpers.ts | 53 +++- src/lang/modifyAst/angle.test.ts | 82 +++++++ src/lang/modifyAst/angle.ts | 49 ++++ src/lang/queryAst.ts | 16 ++ src/lang/wasm.ts | 13 + src/machines/modelingSharedContext.ts | 1 + .../tools/centerArcToolImpl.spec.ts | 1 + .../tools/moveTool/moveTool.spec.ts | 1 + .../sketchSolve/tools/sketchToolTestUtils.ts | 1 + 21 files changed, 619 insertions(+), 8 deletions(-) create mode 100644 rust/kcl-lib/src/lint/checks/legacy_angle.rs create mode 100644 rust/kcl-lib/tests/consumed_solid_original_issue/lints.snap create mode 100644 rust/kcl-lib/tests/sketch_block_angle_constraint/lints.snap create mode 100644 src/lang/modifyAst/angle.test.ts create mode 100644 src/lang/modifyAst/angle.ts diff --git a/rust/kcl-lib/src/execution/cache.rs b/rust/kcl-lib/src/execution/cache.rs index f1db3ef18b8..3ef7662f558 100644 --- a/rust/kcl-lib/src/execution/cache.rs +++ b/rust/kcl-lib/src/execution/cache.rs @@ -130,6 +130,7 @@ impl GlobalState { filenames: self.exec_state.filenames(), operations: self.exec_state.operations_by_module(), artifact_graph: self.exec_state.artifacts.graph, + refactor_metadata: self.exec_state.root_module_artifacts.refactor_metadata, scene_objects: self.exec_state.root_module_artifacts.scene_objects, source_range_to_object: self.exec_state.root_module_artifacts.source_range_to_object, var_solutions: self.exec_state.root_module_artifacts.var_solutions, diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 9d079505639..408df55468a 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -9,6 +9,7 @@ use kcl_api::Group; use kcl_api::NumericType; use kcl_api::Operation; use kcl_api::UnitAngle; +use kcl_api::UnitLength; use crate::CompilationIssue; use crate::NodePath; @@ -33,10 +34,13 @@ use crate::execution::ExecState; use crate::execution::ExecutorContext; use crate::execution::KclValue; use crate::execution::KclValueControlFlow; +use crate::execution::LegacyAngleRefactorMeta; use crate::execution::Metadata; use crate::execution::ModelingCmdMeta; use crate::execution::ModuleArtifactState; +use crate::execution::PendingLegacyAngleRefactorMeta; use crate::execution::PreserveMem; +use crate::execution::RefactorMetadata; use crate::execution::SKETCH_BLOCK_PARAM_ON; use crate::execution::SKETCH_OBJECT_META; use crate::execution::SKETCH_OBJECT_META_SKETCH; @@ -78,6 +82,7 @@ use crate::execution::state::SketchBlockState; use crate::execution::types::NumericTypeExt; use crate::execution::types::PrimitiveType; use crate::execution::types::RuntimeType; +use crate::execution::types::adjust_length; use crate::front::LineCtor; use crate::front::Object; use crate::front::ObjectId; @@ -113,6 +118,7 @@ use crate::parsing::ast::types::TagDeclarator; use crate::parsing::ast::types::Type; use crate::parsing::ast::types::UnaryExpression; use crate::parsing::ast::types::UnaryOperator; +use crate::pretty::NumericSuffix; use crate::std::StdFnProps; use crate::std::args::FromKclValue; use crate::std::args::TyF64; @@ -387,10 +393,114 @@ struct PointsAtAngleLineData { } enum AngleConstraintLowering { - LinesAtAngle, + LinesAtAngle(Box), PointsAtAngle(PointsAtAngleLineData), } +fn number_in_solver_units(number: &crate::front::Number, solver_unit: UnitLength) -> Option { + let source_unit = match number.units { + NumericSuffix::Mm => UnitLength::Millimeters, + NumericSuffix::Cm => UnitLength::Centimeters, + NumericSuffix::M => UnitLength::Meters, + NumericSuffix::Inch => UnitLength::Inches, + NumericSuffix::Ft => UnitLength::Feet, + NumericSuffix::Yd => UnitLength::Yards, + NumericSuffix::None | NumericSuffix::Length => return Some(number.value), + _ => return None, + }; + Some(adjust_length(source_unit, number.value, solver_unit).0) +} + +fn label_position_in_solver_units( + label_position: &Option>, + solver_unit: UnitLength, +) -> Option<[f64; 2]> { + let point = label_position.as_ref()?; + Some([ + number_in_solver_units(&point.x, solver_unit)?, + number_in_solver_units(&point.y, solver_unit)?, + ]) +} + +fn solved_angle_line(line: &ConstrainableLine2d, final_values: &[f64]) -> Option<([f64; 2], [f64; 2])> { + let point = |index: usize| { + let point = line.vars.get(index)?; + Some([*final_values.get(point.x.0)?, *final_values.get(point.y.0)?]) + }; + Some((point(0)?, point(1)?)) +} + +fn angle_ray_vector(lines: [[f64; 2]; 2], ray: AngleSectorRay) -> [f64; 2] { + let direction = lines[ray.line_index]; + match ray.direction { + AngleRayDirection::Forward => direction, + AngleRayDirection::Reverse => [-direction[0], -direction[1]], + } +} + +fn directed_angle(from: [f64; 2], to: [f64; 2]) -> f64 { + let cross = from[0] * to[1] - from[1] * to[0]; + libm::atan2(cross, vec2_dot(from, to)).rem_euclid(std::f64::consts::TAU) +} + +fn circular_angle_distance(a: f64, b: f64) -> f64 { + let delta = (a - b).abs().rem_euclid(std::f64::consts::TAU); + libm::fmin(delta, std::f64::consts::TAU - delta) +} + +fn finalize_legacy_angle_refactor_meta( + pending: &PendingLegacyAngleRefactorMeta, + final_values: &[f64], +) -> Option { + let line0 = solved_angle_line(&pending.lines[0], final_values)?; + let line1 = solved_angle_line(&pending.lines[1], final_values)?; + let vertex = intersect_lines_2d(line0, line1)?; + let directions = [vec2_sub(line0.1, line0.0), vec2_sub(line1.1, line1.0)]; + if directions.iter().any(|direction| vec2_len(*direction) <= 1e-9) { + return None; + } + + let desired = pending.desired_angle_radians.rem_euclid(std::f64::consts::TAU); + let sectors = [ + AngleSector::One, + AngleSector::Two, + AngleSector::Three, + AngleSector::Four, + ]; + let mut candidates = Vec::new(); + for sector in sectors { + for inverse in [false, true] { + let rays = angle_sector_rays(sector, inverse); + let from = angle_ray_vector(directions, rays[0]); + let to = angle_ray_vector(directions, rays[1]); + if circular_angle_distance(directed_angle(from, to), desired) <= 1e-5 { + let midpoint = libm::atan2(from[1], from[0]) + desired * 0.5; + candidates.push((sector, inverse, midpoint.rem_euclid(std::f64::consts::TAU))); + } + } + } + + let selected = if let Some(label_position) = pending.label_position { + let label_direction = vec2_sub(label_position, vertex); + if vec2_len(label_direction) > 1e-9 { + let label_angle = libm::atan2(label_direction[1], label_direction[0]).rem_euclid(std::f64::consts::TAU); + candidates.into_iter().min_by(|a, b| { + circular_angle_distance(a.2, label_angle).total_cmp(&circular_angle_distance(b.2, label_angle)) + })? + } else { + candidates.into_iter().next()? + } + } else { + candidates.into_iter().next()? + }; + + Some(LegacyAngleRefactorMeta { + source_range: pending.source_range, + sector: front_angle_sector(selected.0), + inverse: selected.1, + }) +} + fn push_points_at_angle_for_lines( sketch_block_state: &mut SketchBlockState, sketch_var_ty: NumericType, @@ -2116,6 +2226,17 @@ impl Node { }; exec_state.warn(CompilationIssue::err(range, message), annotations::WARN_SOLVER); } + if solve_outcome.converged { + exec_state.mod_local.artifacts.refactor_metadata.extend( + sketch_block_state + .pending_legacy_angle_refactor_metadata + .iter() + .filter_map(|pending| { + finalize_legacy_angle_refactor_meta(pending, &solve_outcome.final_values) + .map(RefactorMetadata::LegacyAngle) + }), + ); + } // Substitute solutions back into sketch variables. let sketch_engine_id = exec_state.next_uuid(); let solution_ty = solver_numeric_type(exec_state); @@ -3995,7 +4116,21 @@ impl Node { } }; let angle_lowering = match *mode { - AngleConstraintMode::LinesAtAngle => AngleConstraintLowering::LinesAtAngle, + AngleConstraintMode::LinesAtAngle => { + AngleConstraintLowering::LinesAtAngle(Box::new(PendingLegacyAngleRefactorMeta { + source_range: constraint + .meta + .first() + .map(|meta| meta.source_range) + .unwrap_or(range), + lines: [line0.clone(), line1.clone()], + desired_angle_radians: desired_angle.to_radians(), + label_position: label_position_in_solver_units( + label_position, + exec_state.length_unit(), + ), + })) + } AngleConstraintMode::PointsAtAngle { sector, inverse } => { let sketch_vars = exec_state .mod_local @@ -4057,12 +4192,15 @@ impl Node { return Err(internal_err(message, self)); }; match angle_lowering { - AngleConstraintLowering::LinesAtAngle => { + AngleConstraintLowering::LinesAtAngle(refactor_meta) => { sketch_block_state.solver_constraints.push(Constraint::LinesAtAngle( datum_line_from_constrainable(line0, range)?, datum_line_from_constrainable(line1, range)?, ezpz::datatypes::AngleKind::Other(desired_angle), )); + sketch_block_state + .pending_legacy_angle_refactor_metadata + .push(*refactor_meta); } AngleConstraintLowering::PointsAtAngle(points_at_angle_data) => { push_points_at_angle_for_lines( @@ -6173,18 +6311,99 @@ mod test { #[tokio::test(flavor = "multi_thread")] async fn angle_unlabeled_keeps_legacy_lines_at_angle() { - parse_execute( - r#" + let code = r#" sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) - line2 = line(start = [var 0mm, var 1mm], end = [var 2mm, var 3mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) lines = [line1, line2] angle(lines) == 60deg } +"#; + let result = parse_execute(code).await.unwrap(); + + let metadata = result + .exec_state + .global + .root_module_artifacts + .legacy_angle_refactor_metadata(); + assert_eq!(metadata.len(), 1); + assert_eq!(metadata[0].sector, 1); + assert!(!metadata[0].inverse); + let program = crate::Program::parse_no_errs(code).unwrap(); + let findings = program.lint(crate::lint::checks::lint_legacy_angle).unwrap(); + assert_eq!(metadata[0].source_range, findings[0].pos); + } + + #[tokio::test(flavor = "multi_thread")] + async fn legacy_angle_refactor_metadata_follows_the_solved_branch() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var -2mm, var -3.464mm]) + angle([line1, line2]) == 60deg +} "#, ) .await .unwrap(); + + let metadata = result + .exec_state + .global + .root_module_artifacts + .legacy_angle_refactor_metadata(); + assert_eq!(metadata.len(), 1); + assert_eq!(metadata[0].sector, 2); + assert!(metadata[0].inverse); + } + + #[tokio::test(flavor = "multi_thread")] + async fn legacy_angle_label_position_selects_the_visible_sector() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + angle([line1, line2], labelPosition = [-3mm, -1.7mm]) == 60deg +} +"#, + ) + .await + .unwrap(); + + let metadata = result + .exec_state + .global + .root_module_artifacts + .legacy_angle_refactor_metadata(); + assert_eq!(metadata.len(), 1); + assert_eq!(metadata[0].sector, 3); + assert!(!metadata[0].inverse); + } + + #[tokio::test(flavor = "multi_thread")] + async fn parallel_legacy_angle_has_no_refactor_metadata() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) + line2 = line(start = [var 0mm, var 1mm], end = [var 4mm, var 1mm]) + angle([line1, line2]) == 0deg +} +"#, + ) + .await + .unwrap(); + + assert!( + result + .exec_state + .global + .root_module_artifacts + .legacy_angle_refactor_metadata() + .is_empty() + ); } #[tokio::test(flavor = "multi_thread")] diff --git a/rust/kcl-lib/src/execution/mod.rs b/rust/kcl-lib/src/execution/mod.rs index ecbfca0ceb8..35178466078 100644 --- a/rust/kcl-lib/src/execution/mod.rs +++ b/rust/kcl-lib/src/execution/mod.rs @@ -57,8 +57,11 @@ pub(crate) use state::ConsumedSolidKey; pub(crate) use state::ConsumedSolidOperation; pub use state::ExecState; pub(crate) use state::KclVersion; +pub use state::LegacyAngleRefactorMeta; pub use state::MetaSettings; pub(crate) use state::ModuleArtifactState; +pub(crate) use state::PendingLegacyAngleRefactorMeta; +pub use state::RefactorMetadata; pub(crate) use state::TangencyMode; use crate::CompilationIssue; @@ -304,6 +307,8 @@ pub struct ExecOutcome { pub operations: OperationsByModule, /// Output artifact graph. pub artifact_graph: ArtifactGraph, + /// Information collected during execution for actionable refactors. + pub refactor_metadata: Vec, /// Objects in the scene, created from execution. #[serde(skip)] pub scene_objects: Vec, diff --git a/rust/kcl-lib/src/execution/state.rs b/rust/kcl-lib/src/execution/state.rs index c64f30248e2..0abf2b0929f 100644 --- a/rust/kcl-lib/src/execution/state.rs +++ b/rust/kcl-lib/src/execution/state.rs @@ -28,6 +28,7 @@ use crate::execution::Artifact; use crate::execution::ArtifactCommand; use crate::execution::ArtifactGraph; use crate::execution::ArtifactId; +use crate::execution::ConstrainableLine2d; use crate::execution::EnvironmentRef; use crate::execution::ExecOutcome; use crate::execution::ExecutorSettings; @@ -170,6 +171,36 @@ pub struct ModuleArtifactState { pub artifact_id_to_scene_object: IndexMap, /// Solutions for sketch variables. pub var_solutions: Vec<(SourceRange, Option, Number)>, + /// Information collected during execution for actionable refactors. + pub refactor_metadata: Vec, +} + +/// Information needed to rewrite one legacy `angle` call while preserving its +/// currently solved directed-angle branch. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)] +#[ts(export)] +#[serde(rename_all = "camelCase")] +pub struct LegacyAngleRefactorMeta { + pub source_range: SourceRange, + pub sector: u8, + pub inverse: bool, +} + +/// Metadata collected during execution for refactors that cannot be derived +/// from syntax alone. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)] +#[ts(export)] +#[serde(tag = "kind", content = "data", rename_all = "camelCase")] +pub enum RefactorMetadata { + LegacyAngle(LegacyAngleRefactorMeta), +} + +#[derive(Debug, Clone)] +pub(crate) struct PendingLegacyAngleRefactorMeta { + pub source_range: SourceRange, + pub lines: [ConstrainableLine2d; 2], + pub desired_angle_radians: f64, + pub label_position: Option<[f64; 2]>, } #[derive(Debug, Clone)] @@ -334,6 +365,7 @@ pub(crate) struct SketchBlockState { pub solver_optional_constraints: Vec, pub needed_by_engine: Vec, pub segment_tags: IndexMap, + pub pending_legacy_angle_refactor_metadata: Vec, } impl ExecState { @@ -488,6 +520,7 @@ impl ExecState { filenames: self.global.filenames(), operations: self.global.operations_by_module(), artifact_graph: self.global.artifacts.graph, + refactor_metadata: self.global.root_module_artifacts.refactor_metadata, scene_objects: self.global.root_module_artifacts.scene_objects, source_range_to_object: self.global.root_module_artifacts.source_range_to_object, var_solutions: self.global.root_module_artifacts.var_solutions, @@ -1036,11 +1069,21 @@ impl ArtifactState { } impl ModuleArtifactState { + pub fn legacy_angle_refactor_metadata(&self) -> Vec { + self.refactor_metadata + .iter() + .map(|metadata| match metadata { + RefactorMetadata::LegacyAngle(metadata) => *metadata, + }) + .collect() + } + pub(crate) fn clear(&mut self) { self.artifacts.clear(); self.unprocessed_commands.clear(); self.commands.clear(); self.operations.clear(); + self.refactor_metadata.clear(); } pub(crate) fn restore_scene_objects(&mut self, scene_objects: &[Object]) { @@ -1098,6 +1141,7 @@ impl ModuleArtifactState { self.artifact_id_to_scene_object .extend(other.artifact_id_to_scene_object); self.var_solutions.extend(other.var_solutions); + self.refactor_metadata.extend(other.refactor_metadata); } // Move unprocessed artifact commands so that we don't try to process them diff --git a/rust/kcl-lib/src/frontend.rs b/rust/kcl-lib/src/frontend.rs index 301a225dfe7..916c432523c 100644 --- a/rust/kcl-lib/src/frontend.rs +++ b/rust/kcl-lib/src/frontend.rs @@ -2023,6 +2023,7 @@ impl FrontendState { filenames, operations, artifact_graph, + refactor_metadata: Default::default(), scene_objects, source_range_to_object, var_solutions, @@ -9172,6 +9173,7 @@ cylinder = startSketchOn(XY) variables: Default::default(), operations: Default::default(), artifact_graph: Default::default(), + refactor_metadata: Default::default(), scene_objects: Default::default(), source_range_to_object: Default::default(), var_solutions: Default::default(), @@ -9324,6 +9326,7 @@ sketch(on = XY) { variables: Default::default(), operations: Default::default(), artifact_graph: Default::default(), + refactor_metadata: Default::default(), scene_objects: Default::default(), source_range_to_object: Default::default(), var_solutions, diff --git a/rust/kcl-lib/src/lib.rs b/rust/kcl-lib/src/lib.rs index f8af6587843..85f9bd073a6 100644 --- a/rust/kcl-lib/src/lib.rs +++ b/rust/kcl-lib/src/lib.rs @@ -110,10 +110,12 @@ pub use execution::ExecutionCallbacks; pub use execution::ExecutorContext; pub use execution::ExecutorSettings; pub use execution::KclValueView; +pub use execution::LegacyAngleRefactorMeta; pub use execution::MetaSettings; pub use execution::MockConfig; pub use execution::OperationCallbackArgs; pub use execution::Point2d; +pub use execution::RefactorMetadata; pub use execution::SegmentDragAnchor; pub use execution::SketchConstraintReport; pub use execution::SketchConstraintStatus; diff --git a/rust/kcl-lib/src/lint/checks/legacy_angle.rs b/rust/kcl-lib/src/lint/checks/legacy_angle.rs new file mode 100644 index 00000000000..22eb7130f83 --- /dev/null +++ b/rust/kcl-lib/src/lint/checks/legacy_angle.rs @@ -0,0 +1,56 @@ +use anyhow::Result; + +use crate::SourceRange; +use crate::lint::rule::Discovered; +use crate::lint::rule::Finding; +use crate::lint::rule::FindingFamily; +use crate::lint::rule::def_finding; +use crate::parsing::ast::types::Node as AstNode; +use crate::parsing::ast::types::Program; +use crate::walk::Node; + +def_finding!( + Z0007, + "Legacy angle constraint can be converted to angleDimension", + "The angle function does not identify a directed angle sector. Convert it to angleDimension to preserve the currently solved sector explicitly.", + FindingFamily::Simplify +); + +pub fn lint_legacy_angle(node: Node, _prog: &AstNode) -> Result> { + let Node::CallExpressionKw(call) = node else { + return Ok(vec![]); + }; + if call.callee.name.name != "angle" || call.unlabeled.is_none() { + return Ok(vec![]); + } + + let source_range = SourceRange::new(call.start, call.end, call.module_id); + Ok(vec![Z0007.at( + "angle can be converted to an explicit angleDimension sector".to_owned(), + source_range, + None, + )]) +} + +#[cfg(test)] +mod tests { + use super::Z0007; + use super::lint_legacy_angle; + + #[test] + fn finds_legacy_angle_calls() { + let program = crate::Program::parse_no_errs("sketch(on = XY) { angle([line1, line2]) == 60deg }").unwrap(); + let findings = program.lint(lint_legacy_angle).unwrap(); + assert_eq!(findings.len(), 1); + assert_eq!(findings[0].finding.code, Z0007.code); + } + + #[test] + fn ignores_angle_dimension_calls() { + let program = crate::Program::parse_no_errs( + "sketch(on = XY) { angleDimension(lines = [line1, line2], sector = 1) == 60deg }", + ) + .unwrap(); + assert!(program.lint(lint_legacy_angle).unwrap().is_empty()); + } +} diff --git a/rust/kcl-lib/src/lint/checks/mod.rs b/rust/kcl-lib/src/lint/checks/mod.rs index 5009d38186b..e321460ac1f 100644 --- a/rust/kcl-lib/src/lint/checks/mod.rs +++ b/rust/kcl-lib/src/lint/checks/mod.rs @@ -1,6 +1,7 @@ mod camel_case; mod chained_profiles; mod default_plane; +mod legacy_angle; mod offset_plane; pub use camel_case::Z0001; @@ -10,5 +11,7 @@ pub use chained_profiles::Z0004; pub use chained_profiles::lint_profiles_should_not_be_chained; pub use default_plane::Z0002; pub use default_plane::lint_should_be_default_plane; +pub use legacy_angle::Z0007; +pub use legacy_angle::lint_legacy_angle; pub use offset_plane::Z0003; pub use offset_plane::lint_should_be_offset_plane; diff --git a/rust/kcl-lib/src/parsing/ast/types/mod.rs b/rust/kcl-lib/src/parsing/ast/types/mod.rs index 10f19708505..dea6400e39b 100644 --- a/rust/kcl-lib/src/parsing/ast/types/mod.rs +++ b/rust/kcl-lib/src/parsing/ast/types/mod.rs @@ -419,6 +419,7 @@ impl Node { crate::lint::checks::lint_should_be_default_plane, crate::lint::checks::lint_should_be_offset_plane, crate::lint::checks::lint_profiles_should_not_be_chained, + crate::lint::checks::lint_legacy_angle, ]; let mut findings = vec![]; diff --git a/rust/kcl-lib/tests/consumed_solid_original_issue/lints.snap b/rust/kcl-lib/tests/consumed_solid_original_issue/lints.snap new file mode 100644 index 00000000000..f18c4880624 --- /dev/null +++ b/rust/kcl-lib/tests/consumed_solid_original_issue/lints.snap @@ -0,0 +1,23 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Lints consumed_solid_original_issue.kcl +--- +[ + { + "finding": { + "code": "Z0007", + "title": "Legacy angle constraint can be converted to angleDimension", + "description": "The angle function does not identify a directed angle sector. Convert it to angleDimension to preserve the currently solved sector explicitly.", + "experimental": false, + "family": "simplify" + }, + "description": "angle can be converted to an explicit angleDimension sector", + "pos": [ + 769, + 790, + 0 + ], + "overridden": false, + "suggestion": null + } +] diff --git a/rust/kcl-lib/tests/sketch_block_angle_constraint/lints.snap b/rust/kcl-lib/tests/sketch_block_angle_constraint/lints.snap new file mode 100644 index 00000000000..2a1cb10255a --- /dev/null +++ b/rust/kcl-lib/tests/sketch_block_angle_constraint/lints.snap @@ -0,0 +1,40 @@ +--- +source: kcl-lib/src/simulation_tests.rs +description: Lints sketch_block_angle_constraint.kcl +--- +[ + { + "finding": { + "code": "Z0007", + "title": "Legacy angle constraint can be converted to angleDimension", + "description": "The angle function does not identify a directed angle sector. Convert it to angleDimension to preserve the currently solved sector explicitly.", + "experimental": false, + "family": "simplify" + }, + "description": "angle can be converted to an explicit angleDimension sector", + "pos": [ + 212, + 227, + 0 + ], + "overridden": false, + "suggestion": null + }, + { + "finding": { + "code": "Z0007", + "title": "Legacy angle constraint can be converted to angleDimension", + "description": "The angle function does not identify a directed angle sector. Convert it to angleDimension to preserve the currently solved sector explicitly.", + "experimental": false, + "family": "simplify" + }, + "description": "angle can be converted to an explicit angleDimension sector", + "pos": [ + 239, + 254, + 0 + ], + "overridden": false, + "suggestion": null + } +] diff --git a/src/lang/KclManager.ts b/src/lang/KclManager.ts index 874ea03c2c0..ef9f3a10db5 100644 --- a/src/lang/KclManager.ts +++ b/src/lang/KclManager.ts @@ -2327,6 +2327,7 @@ export class KclManager extends File { sourceCode: this.code, instance: await this.systemDeps.wasmInstancePromise, rustContext: this.rustContext, + legacyAngleRefactorMetadata: execState.legacyAngleRefactorMetadata, }) ) if (this.sceneEntitiesManager) { diff --git a/src/lang/langHelpers.ts b/src/lang/langHelpers.ts index de337de8a2b..4fb8146b89c 100644 --- a/src/lang/langHelpers.ts +++ b/src/lang/langHelpers.ts @@ -1,13 +1,17 @@ import type { Diagnostic } from '@codemirror/lint' import { lspCodeActionEvent } from '@kittycad/codemirror-lsp-client' +import type { LegacyAngleRefactorMeta } from '@rust/kcl-lib/bindings/LegacyAngleRefactorMeta' import type { Node } from '@rust/kcl-lib/bindings/Node' +import type { SourceRange } from '@rust/kcl-lib/bindings/SourceRange' import { KCLError, toUtf16 } from '@src/lang/errors' +import { convertLegacyAngleToAngleDimension } from '@src/lang/modifyAst/angle' import type { ExecCallbacks, ExecState, Program } from '@src/lang/wasm' -import { emptyExecState, kclLint } from '@src/lang/wasm' +import { emptyExecState, kclLint, recast } from '@src/lang/wasm' import { EXECUTE_AST_INTERRUPT_ERROR_STRING } from '@src/lib/constants' import type RustContext from '@src/lib/rustContext' import { jsAppSettings } from '@src/lib/settings/settingsUtils' +import { isErr } from '@src/lib/trap' import type { ModuleType } from '@src/lib/wasm_lib_wrapper' import { REJECTED_TOO_EARLY_WEBSOCKET_MESSAGE } from '@src/network/utils' import type { EditorView } from 'codemirror' @@ -33,6 +37,9 @@ export type ToolTip = | 'arc' | 'startProfile' +const sourceRangesEqual = (left: SourceRange, right: SourceRange) => + left[0] === right[0] && left[1] === right[1] && left[2] === right[2] + export const toolTips: Array = [ 'line', 'lineTo', @@ -182,15 +189,25 @@ export async function lintAst({ sourceCode, instance, rustContext, + legacyAngleRefactorMetadata = [], }: { - ast: Program + ast: Node sourceCode: string instance: ModuleType rustContext?: RustContext + legacyAngleRefactorMetadata?: LegacyAngleRefactorMeta[] }): Promise> { try { let discovered_findings = await kclLint(ast, instance) + discovered_findings = discovered_findings.filter( + (lint) => + lint.finding.code !== 'Z0007' || + legacyAngleRefactorMetadata.some((metadata) => + sourceRangesEqual(metadata.sourceRange, lint.pos) + ) + ) + // Filter out Z0005 if sketch solve mode is not enabled // Only show Z0005 when useSketchSolveMode setting is enabled let shouldShowZ0005 = false @@ -217,6 +234,9 @@ export async function lintAst({ 'Deprecated sketch syntax. This sketch cannot be converted to new sketch block syntax at this time.' let message = lint.finding.title const suggestion = lint.suggestion + const legacyAngleMetadata = legacyAngleRefactorMetadata.find((metadata) => + sourceRangesEqual(metadata.sourceRange, lint.pos) + ) if (suggestion) { actions = [ @@ -234,6 +254,35 @@ export async function lintAst({ }, }, ] + } else if (lint.finding.code === 'Z0007' && legacyAngleMetadata) { + const modifiedAst = convertLegacyAngleToAngleDimension( + ast, + legacyAngleMetadata.sourceRange, + legacyAngleMetadata.sector, + legacyAngleMetadata.inverse, + instance + ) + const convertedSource = isErr(modifiedAst) + ? modifiedAst + : recast(modifiedAst, instance) + if (!isErr(convertedSource)) { + actions = [ + { + name: 'Convert to angleDimension', + apply: (view: EditorView, _from: number, _to: number) => { + if (view.state.doc.toString() !== sourceCode) return + view.dispatch({ + changes: { + from: 0, + to: view.state.doc.length, + insert: convertedSource, + }, + annotations: [lspCodeActionEvent], + }) + }, + }, + ] + } } else if ( lint.finding.code === 'Z0005' && rustContext && diff --git a/src/lang/modifyAst/angle.test.ts b/src/lang/modifyAst/angle.test.ts new file mode 100644 index 00000000000..b020c4f3f69 --- /dev/null +++ b/src/lang/modifyAst/angle.test.ts @@ -0,0 +1,82 @@ +import { convertLegacyAngleToAngleDimension } from '@src/lang/modifyAst/angle' +import type { Node } from '@rust/kcl-lib/bindings/Node' +import { assertParse, recast } from '@src/lang/wasm' +import type { Program, SourceRange } from '@src/lang/wasm' +import { err } from '@src/lib/trap' +import type { ModuleType } from '@src/lib/wasm_lib_wrapper' +import { buildTheWorldAndNoEngineConnection } from '@src/unitTestUtils' +import { beforeEach, describe, expect, it } from 'vitest' + +let instance: ModuleType = null! + +beforeEach(async () => { + if (instance) return + instance = (await buildTheWorldAndNoEngineConnection()).instance +}) + +function legacyAngleRange(ast: Node): SourceRange { + const call = ast.body[0] + if (call.type !== 'ExpressionStatement') throw new Error('Expected sketch') + const sketch = call.expression + if (sketch.type !== 'SketchBlock') throw new Error('Expected sketch block') + const statement = sketch.body.items[0] + if (statement.type !== 'ExpressionStatement') + throw new Error('Expected expression') + const binary = statement.expression + if (binary.type !== 'BinaryExpression') throw new Error('Expected binary') + const angle = binary.left + if (angle.type !== 'CallExpressionKw') throw new Error('Expected angle call') + return [angle.start, angle.end, angle.moduleId] +} + +describe('convertLegacyAngleToAngleDimension', () => { + it('preserves the line and label expressions while adding the solved sector', () => { + const ast = assertParse( + `sketch(on = XY) { + angle([line1, line2], labelPosition = [10mm, 11mm]) == targetAngle +}`, + instance + ) + const result = convertLegacyAngleToAngleDimension( + ast, + legacyAngleRange(ast), + 2, + true, + instance + ) + if (err(result)) throw result + const code = recast(result, instance) + if (err(code)) throw code + + expect(code).toContain(`angleDimension( + lines = [line1, line2], + sector = 2, + inverse = true, + labelPosition = [10mm, 11mm], +) == targetAngle`) + }) + + it('omits inverse for the default directed angle', () => { + const ast = assertParse( + `sketch(on = XY) { + angle([line1, line2]) == 60deg +}`, + instance + ) + const result = convertLegacyAngleToAngleDimension( + ast, + legacyAngleRange(ast), + 1, + false, + instance + ) + if (err(result)) throw result + const code = recast(result, instance) + if (err(code)) throw code + + expect(code).toContain( + 'angleDimension(lines = [line1, line2], sector = 1) == 60deg' + ) + expect(code).not.toContain('inverse') + }) +}) diff --git a/src/lang/modifyAst/angle.ts b/src/lang/modifyAst/angle.ts new file mode 100644 index 00000000000..f44e28a5bc6 --- /dev/null +++ b/src/lang/modifyAst/angle.ts @@ -0,0 +1,49 @@ +import { createLabeledArg, createLiteral } from '@src/lang/create' +import { traverse } from '@src/lang/queryAst' +import type { Node } from '@rust/kcl-lib/bindings/Node' +import type { Program, SourceRange } from '@src/lang/wasm' +import type { ModuleType } from '@src/lib/wasm_lib_wrapper' + +export function convertLegacyAngleToAngleDimension( + ast: Node, + sourceRange: SourceRange, + sector: number, + inverse: boolean, + instance: ModuleType +): Node | Error { + const modifiedAst = structuredClone(ast) + let converted = false + + traverse(modifiedAst, { + enter(node) { + if ( + converted || + node.type !== 'CallExpressionKw' || + node.start !== sourceRange[0] || + node.end !== sourceRange[1] || + node.moduleId !== sourceRange[2] || + node.callee.name.name !== 'angle' || + node.unlabeled === null + ) { + return + } + + const lines = node.unlabeled + node.callee.name.name = 'angleDimension' + node.unlabeled = null + node.arguments = [ + createLabeledArg('lines', lines), + createLabeledArg('sector', createLiteral(sector, instance)), + ...(inverse + ? [createLabeledArg('inverse', createLiteral(true, instance))] + : []), + ...node.arguments, + ] + converted = true + }, + }) + + return converted + ? modifiedAst + : new Error('Could not find the legacy angle call for this refactor') +} diff --git a/src/lang/queryAst.ts b/src/lang/queryAst.ts index 67e47a1748f..8e9e7727a6b 100644 --- a/src/lang/queryAst.ts +++ b/src/lang/queryAst.ts @@ -1,6 +1,7 @@ import type { FunctionExpression } from '@rust/kcl-lib/bindings/FunctionExpression' import type { ImportStatement } from '@rust/kcl-lib/bindings/ImportStatement' import type { Node } from '@rust/kcl-lib/bindings/Node' +import type { Block } from '@rust/kcl-lib/bindings/Block' import type { TypeDeclaration } from '@rust/kcl-lib/bindings/TypeDeclaration' import { createLiteral, @@ -232,6 +233,7 @@ type KCLNode = Node< | TypeDeclaration | ReturnStatement | Identifier + | Block > export function traverse( @@ -285,6 +287,20 @@ export function traverse( ]) ) } + } else if (_node.type === 'SketchBlock') { + _node.arguments.forEach((arg, index) => + _traverse(arg.arg, [ + ...pathToNode, + ['arguments', 'SketchBlock'], + [index, ARG_INDEX_FIELD], + ['arg', LABELED_ARG_FIELD], + ]) + ) + _traverse(_node.body, [...pathToNode, ['body', 'SketchBlock']]) + } else if (_node.type === 'Block') { + _node.items.forEach((item, index) => + _traverse(item, [...pathToNode, ['items', 'Block'], [index, 'index']]) + ) } else if (_node.type === 'BinaryExpression') { _traverse(_node.left, [...pathToNode, ['left', 'BinaryExpression']]) _traverse(_node.right, [...pathToNode, ['right', 'BinaryExpression']]) diff --git a/src/lang/wasm.ts b/src/lang/wasm.ts index 9011ea21216..1c31adea279 100644 --- a/src/lang/wasm.ts +++ b/src/lang/wasm.ts @@ -8,6 +8,7 @@ import type { ExecOutcome as RustExecOutcome } from '@rust/kcl-lib/bindings/Exec import type { KclError as RustKclError } from '@rust/kcl-lib/bindings/KclError' import type { KclErrorWithOutputs } from '@rust/kcl-lib/bindings/KclErrorWithOutputs' import type { KclValueView } from '@rust/kcl-lib/bindings/KclValueView' +import type { LegacyAngleRefactorMeta } from '@rust/kcl-lib/bindings/LegacyAngleRefactorMeta' import type { MetaSettings } from '@rust/kcl-lib/bindings/MetaSettings' import type { UnitLength } from '@rust/kcl-lib/bindings/ModelingCmd' import type { ModulePath } from '@rust/kcl-lib/bindings/ModulePath' @@ -18,6 +19,7 @@ import type { Operation } from '@rust/kcl-lib/bindings/Operation' import type { OperationCallbackArgs } from '@rust/kcl-lib/bindings/OperationCallbackArgs' import type { Program } from '@rust/kcl-lib/bindings/Program' import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration' +import type { RefactorMetadata } from '@rust/kcl-lib/bindings/RefactorMetadata' import type { Sketch } from '@rust/kcl-lib/bindings/Sketch' import type { SourceRange } from '@rust/kcl-lib/bindings/SourceRange' @@ -271,6 +273,7 @@ export interface ExecState { variables: { [key in string]?: KclValueView } operations: OperationsByModule artifactGraph: ArtifactGraph + legacyAngleRefactorMetadata: LegacyAngleRefactorMeta[] issues: CompilationIssue[] filenames: { [x: number]: ModulePath | undefined } defaultPlanes: DefaultPlanes | null @@ -310,6 +313,7 @@ export function emptyExecState(): ExecState { variables: {}, operations: emptyOperationsByModule(), artifactGraph: defaultArtifactGraph(), + legacyAngleRefactorMetadata: [], issues: [], filenames: [], defaultPlanes: null, @@ -376,11 +380,20 @@ export function countOperations( export function execStateFromRust(execOutcome: RustExecOutcome): ExecState { const artifactGraph = artifactGraphFromRust(execOutcome.artifactGraph) + const legacyAngleRefactorMetadata = execOutcome.refactorMetadata + .filter( + ( + metadata + ): metadata is Extract => + metadata.kind === 'legacyAngle' + ) + .map((metadata) => metadata.data) return { variables: execOutcome.variables, operations: execOutcome.operations, artifactGraph, + legacyAngleRefactorMetadata, issues: execOutcome.issues, filenames: execOutcome.filenames, defaultPlanes: execOutcome.defaultPlanes, diff --git a/src/machines/modelingSharedContext.ts b/src/machines/modelingSharedContext.ts index d3bcf177e58..3da6b2d4760 100644 --- a/src/machines/modelingSharedContext.ts +++ b/src/machines/modelingSharedContext.ts @@ -33,6 +33,7 @@ export const dummyInitSketchGraphDelta: SceneGraphDelta = Object.freeze({ exec_outcome: { issues: [], variables: {}, + refactorMetadata: [], operations: emptyOperationsByModule(), artifactGraph: { map: {}, itemCount: 0 }, filenames: {}, diff --git a/src/machines/sketchSolve/tools/centerArcToolImpl.spec.ts b/src/machines/sketchSolve/tools/centerArcToolImpl.spec.ts index 1f7af4dc134..049f1dfe4f2 100644 --- a/src/machines/sketchSolve/tools/centerArcToolImpl.spec.ts +++ b/src/machines/sketchSolve/tools/centerArcToolImpl.spec.ts @@ -66,6 +66,7 @@ function createSceneGraphDelta( exec_outcome: { issues: [], variables: {}, + refactorMetadata: [], operations: emptyOperationsByModule(), artifactGraph: { map: {}, itemCount: 0 }, filenames: {}, diff --git a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts index 9aef9990bb6..de9f7c0fdd7 100644 --- a/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts +++ b/src/machines/sketchSolve/tools/moveTool/moveTool.spec.ts @@ -800,6 +800,7 @@ function createSceneGraphDelta(objects: Array): SceneGraphDelta { exec_outcome: { issues: [], variables: {}, + refactorMetadata: [], operations: emptyOperationsByModule(), artifactGraph: { map: {}, itemCount: 0 }, filenames: {}, diff --git a/src/machines/sketchSolve/tools/sketchToolTestUtils.ts b/src/machines/sketchSolve/tools/sketchToolTestUtils.ts index 72d59efab96..ab5aeaaea79 100644 --- a/src/machines/sketchSolve/tools/sketchToolTestUtils.ts +++ b/src/machines/sketchSolve/tools/sketchToolTestUtils.ts @@ -44,6 +44,7 @@ export function createSceneGraphDelta( exec_outcome: { issues: [], variables: {}, + refactorMetadata: [], operations: emptyOperationsByModule(), artifactGraph: { map: {}, itemCount: 0 }, filenames: {}, From 1324bf45c1f4f6a091e65db0ae6c9597c6a19a8a Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 12 Jul 2026 23:43:34 +0200 Subject: [PATCH 68/78] better sector chosen for angleDimension when converting legacy angle() --- rust/kcl-lib/src/execution/exec_ast.rs | 79 ++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 408df55468a..eaa4403f2d7 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -448,6 +448,46 @@ fn circular_angle_distance(a: f64, b: f64) -> f64 { libm::fmin(delta, std::f64::consts::TAU - delta) } +fn legacy_angle_default_label_angle( + lines: [([f64; 2], [f64; 2]); 2], + directions: [[f64; 2]; 2], + vertex: [f64; 2], + desired: f64, +) -> f64 { + let signed_distances = lines.map(|line| { + let direction = vec2_sub(line.1, line.0); + let length = vec2_len(direction); + [ + vec2_dot(vec2_sub(line.0, vertex), direction) / length, + vec2_dot(vec2_sub(line.1, vertex), direction) / length, + ] + }); + let overlap = [ + libm::fmax(signed_distances[0][0], signed_distances[1][0]), + libm::fmin(signed_distances[0][1], signed_distances[1][1]), + ]; + let radius = if overlap[1] >= overlap[0] { + let near_start = overlap[0] + (overlap[1] - overlap[0]) * 0.15; + let near_end = overlap[0] + (overlap[1] - overlap[0]) * 0.85; + if near_start.abs() < near_end.abs() { + near_start + } else { + near_end + } + } else { + let mut distances = signed_distances.into_iter().flatten().collect::>(); + distances.sort_by(f64::total_cmp); + distances[1] + }; + let start = if radius < 0.0 { + [-directions[0][0], -directions[0][1]] + } else { + directions[0] + }; + + (libm::atan2(start[1], start[0]) + desired * 0.5).rem_euclid(std::f64::consts::TAU) +} + fn finalize_legacy_angle_refactor_meta( pending: &PendingLegacyAngleRefactorMeta, final_values: &[f64], @@ -480,6 +520,7 @@ fn finalize_legacy_angle_refactor_meta( } } + let default_label_angle = legacy_angle_default_label_angle([line0, line1], directions, vertex, desired); let selected = if let Some(label_position) = pending.label_position { let label_direction = vec2_sub(label_position, vertex); if vec2_len(label_direction) > 1e-9 { @@ -488,10 +529,16 @@ fn finalize_legacy_angle_refactor_meta( circular_angle_distance(a.2, label_angle).total_cmp(&circular_angle_distance(b.2, label_angle)) })? } else { - candidates.into_iter().next()? + candidates.into_iter().min_by(|a, b| { + circular_angle_distance(a.2, default_label_angle) + .total_cmp(&circular_angle_distance(b.2, default_label_angle)) + })? } } else { - candidates.into_iter().next()? + candidates.into_iter().min_by(|a, b| { + circular_angle_distance(a.2, default_label_angle) + .total_cmp(&circular_angle_distance(b.2, default_label_angle)) + })? }; Some(LegacyAngleRefactorMeta { @@ -6335,7 +6382,7 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn legacy_angle_refactor_metadata_follows_the_solved_branch() { + async fn legacy_angle_refactor_metadata_matches_the_default_label_side() { let result = parse_execute( r#" sketch(on = XY) { @@ -6354,10 +6401,34 @@ sketch(on = XY) { .root_module_artifacts .legacy_angle_refactor_metadata(); assert_eq!(metadata.len(), 1); - assert_eq!(metadata[0].sector, 2); + assert_eq!(metadata[0].sector, 4); assert!(metadata[0].inverse); } + #[tokio::test(flavor = "multi_thread")] + async fn legacy_angle_refactor_metadata_uses_reverse_segment_rays() { + let result = parse_execute( + r#" +sketch(on = XY) { + line1 = line(start = [var -4mm, var 0mm], end = [var 0mm, var 0mm]) + line2 = line(start = [var -2mm, var -3.464mm], end = [var 0mm, var 0mm]) + angle([line1, line2]) == 60deg +} +"#, + ) + .await + .unwrap(); + + let metadata = result + .exec_state + .global + .root_module_artifacts + .legacy_angle_refactor_metadata(); + assert_eq!(metadata.len(), 1); + assert_eq!(metadata[0].sector, 3); + assert!(!metadata[0].inverse); + } + #[tokio::test(flavor = "multi_thread")] async fn legacy_angle_label_position_selects_the_visible_sector() { let result = parse_execute( From 67fe322a51a41fbc301caf18b191f93fa27b54c7 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 12 Jul 2026 23:44:56 +0200 Subject: [PATCH 69/78] labelPosition shouldnt have been used for z007 --- rust/kcl-lib/src/execution/exec_ast.rs | 58 +++----------------------- rust/kcl-lib/src/execution/state.rs | 1 - 2 files changed, 5 insertions(+), 54 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index eaa4403f2d7..37e838a2ee9 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -9,7 +9,6 @@ use kcl_api::Group; use kcl_api::NumericType; use kcl_api::Operation; use kcl_api::UnitAngle; -use kcl_api::UnitLength; use crate::CompilationIssue; use crate::NodePath; @@ -82,7 +81,6 @@ use crate::execution::state::SketchBlockState; use crate::execution::types::NumericTypeExt; use crate::execution::types::PrimitiveType; use crate::execution::types::RuntimeType; -use crate::execution::types::adjust_length; use crate::front::LineCtor; use crate::front::Object; use crate::front::ObjectId; @@ -118,7 +116,6 @@ use crate::parsing::ast::types::TagDeclarator; use crate::parsing::ast::types::Type; use crate::parsing::ast::types::UnaryExpression; use crate::parsing::ast::types::UnaryOperator; -use crate::pretty::NumericSuffix; use crate::std::StdFnProps; use crate::std::args::FromKclValue; use crate::std::args::TyF64; @@ -397,31 +394,6 @@ enum AngleConstraintLowering { PointsAtAngle(PointsAtAngleLineData), } -fn number_in_solver_units(number: &crate::front::Number, solver_unit: UnitLength) -> Option { - let source_unit = match number.units { - NumericSuffix::Mm => UnitLength::Millimeters, - NumericSuffix::Cm => UnitLength::Centimeters, - NumericSuffix::M => UnitLength::Meters, - NumericSuffix::Inch => UnitLength::Inches, - NumericSuffix::Ft => UnitLength::Feet, - NumericSuffix::Yd => UnitLength::Yards, - NumericSuffix::None | NumericSuffix::Length => return Some(number.value), - _ => return None, - }; - Some(adjust_length(source_unit, number.value, solver_unit).0) -} - -fn label_position_in_solver_units( - label_position: &Option>, - solver_unit: UnitLength, -) -> Option<[f64; 2]> { - let point = label_position.as_ref()?; - Some([ - number_in_solver_units(&point.x, solver_unit)?, - number_in_solver_units(&point.y, solver_unit)?, - ]) -} - fn solved_angle_line(line: &ConstrainableLine2d, final_values: &[f64]) -> Option<([f64; 2], [f64; 2])> { let point = |index: usize| { let point = line.vars.get(index)?; @@ -521,25 +493,9 @@ fn finalize_legacy_angle_refactor_meta( } let default_label_angle = legacy_angle_default_label_angle([line0, line1], directions, vertex, desired); - let selected = if let Some(label_position) = pending.label_position { - let label_direction = vec2_sub(label_position, vertex); - if vec2_len(label_direction) > 1e-9 { - let label_angle = libm::atan2(label_direction[1], label_direction[0]).rem_euclid(std::f64::consts::TAU); - candidates.into_iter().min_by(|a, b| { - circular_angle_distance(a.2, label_angle).total_cmp(&circular_angle_distance(b.2, label_angle)) - })? - } else { - candidates.into_iter().min_by(|a, b| { - circular_angle_distance(a.2, default_label_angle) - .total_cmp(&circular_angle_distance(b.2, default_label_angle)) - })? - } - } else { - candidates.into_iter().min_by(|a, b| { - circular_angle_distance(a.2, default_label_angle) - .total_cmp(&circular_angle_distance(b.2, default_label_angle)) - })? - }; + let selected = candidates.into_iter().min_by(|a, b| { + circular_angle_distance(a.2, default_label_angle).total_cmp(&circular_angle_distance(b.2, default_label_angle)) + })?; Some(LegacyAngleRefactorMeta { source_range: pending.source_range, @@ -4172,10 +4128,6 @@ impl Node { .unwrap_or(range), lines: [line0.clone(), line1.clone()], desired_angle_radians: desired_angle.to_radians(), - label_position: label_position_in_solver_units( - label_position, - exec_state.length_unit(), - ), })) } AngleConstraintMode::PointsAtAngle { sector, inverse } => { @@ -6430,7 +6382,7 @@ sketch(on = XY) { } #[tokio::test(flavor = "multi_thread")] - async fn legacy_angle_label_position_selects_the_visible_sector() { + async fn legacy_angle_label_position_does_not_change_the_sector() { let result = parse_execute( r#" sketch(on = XY) { @@ -6449,7 +6401,7 @@ sketch(on = XY) { .root_module_artifacts .legacy_angle_refactor_metadata(); assert_eq!(metadata.len(), 1); - assert_eq!(metadata[0].sector, 3); + assert_eq!(metadata[0].sector, 1); assert!(!metadata[0].inverse); } diff --git a/rust/kcl-lib/src/execution/state.rs b/rust/kcl-lib/src/execution/state.rs index 0abf2b0929f..a6b950b1099 100644 --- a/rust/kcl-lib/src/execution/state.rs +++ b/rust/kcl-lib/src/execution/state.rs @@ -200,7 +200,6 @@ pub(crate) struct PendingLegacyAngleRefactorMeta { pub source_range: SourceRange, pub lines: [ConstrainableLine2d; 2], pub desired_angle_radians: f64, - pub label_position: Option<[f64; 2]>, } #[derive(Debug, Clone)] From d521f37c85e07b5b300085b6a4a7fae355664240 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Sun, 12 Jul 2026 23:47:03 +0200 Subject: [PATCH 70/78] clarifications --- rust/kcl-lib/src/execution/exec_ast.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index 37e838a2ee9..e777ab11e85 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -420,7 +420,7 @@ fn circular_angle_distance(a: f64, b: f64) -> f64 { libm::fmin(delta, std::f64::consts::TAU - delta) } -fn legacy_angle_default_label_angle( +fn legacy_angle_arc_midpoint_angle( lines: [([f64; 2], [f64; 2]); 2], directions: [[f64; 2]; 2], vertex: [f64; 2], @@ -438,6 +438,8 @@ fn legacy_angle_default_label_angle( libm::fmax(signed_distances[0][0], signed_distances[1][0]), libm::fmin(signed_distances[0][1], signed_distances[1][1]), ]; + // Match calculateArcRenderInput in src/machines/sketchSolve/constraints/AngleConstraintBuilder.ts; + // the radius sign chooses the line 0 ray on which the legacy arc starts. let radius = if overlap[1] >= overlap[0] { let near_start = overlap[0] + (overlap[1] - overlap[0]) * 0.15; let near_end = overlap[0] + (overlap[1] - overlap[0]) * 0.85; @@ -492,9 +494,9 @@ fn finalize_legacy_angle_refactor_meta( } } - let default_label_angle = legacy_angle_default_label_angle([line0, line1], directions, vertex, desired); + let arc_midpoint_angle = legacy_angle_arc_midpoint_angle([line0, line1], directions, vertex, desired); let selected = candidates.into_iter().min_by(|a, b| { - circular_angle_distance(a.2, default_label_angle).total_cmp(&circular_angle_distance(b.2, default_label_angle)) + circular_angle_distance(a.2, arc_midpoint_angle).total_cmp(&circular_angle_distance(b.2, arc_midpoint_angle)) })?; Some(LegacyAngleRefactorMeta { From bdb87210c1204c4e5f2f5c3902eca7de9c87c782 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 15:59:32 +0200 Subject: [PATCH 71/78] fix angleDimension docs example code - region was not valid --- rust/kcl-lib/std/solver.kcl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/kcl-lib/std/solver.kcl b/rust/kcl-lib/std/solver.kcl index 610397290e5..c0548b83f61 100644 --- a/rust/kcl-lib/std/solver.kcl +++ b/rust/kcl-lib/std/solver.kcl @@ -458,6 +458,10 @@ export fn angle( /// profile = sketch(on = XY) { /// line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) /// line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) +/// line3 = line(start = [var 2mm, var 3.464mm], end = [var 4mm, var 0mm]) +/// coincident([line1.start, line2.start]) +/// coincident([line2.end, line3.start]) +/// coincident([line3.end, line1.end]) /// angleDimension(lines = [line1, line2], sector = 1) == 60deg /// } /// From 1b14b2f91b591cf4ce0055413cc3ec0c3c1dcf72 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 16:11:48 +0200 Subject: [PATCH 72/78] revert distance implementation to avoid numerical changes in snap tests --- rust/kcl-lib/src/std/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kcl-lib/src/std/utils.rs b/rust/kcl-lib/src/std/utils.rs index 510a582306e..17b2d4e5e05 100644 --- a/rust/kcl-lib/src/std/utils.rs +++ b/rust/kcl-lib/src/std/utils.rs @@ -56,7 +56,7 @@ pub(crate) fn point_3d_to_mm(p: [TyF64; 3]) -> [f64; 3] { /// Get the distance between two points. pub(crate) fn distance(a: Coords2d, b: Coords2d) -> f64 { - vec2_len(vec2_sub(b, a)) + ((b[0] - a[0]).squared() + (b[1] - a[1]).squared()).sqrt() } pub(crate) fn vec2_sub(a: Coords2d, b: Coords2d) -> Coords2d { From 7d7cd697fea9bec0576f8150f94c8d950ab6ef58 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 16:43:00 +0200 Subject: [PATCH 73/78] regenerate snaps --- public/kcl-samples/angle-gauge/main.kcl | 12 +- .../angle-gauge/artifact_commands.snap | 44 +- .../artifact_graph_flowchart.snap.md | 36 +- .../tests/kcl_samples/angle-gauge/ast.snap | 133 +- .../tests/kcl_samples/angle-gauge/ops.snap | 41 +- .../angle-gauge/program_memory.snap | 312 +-- .../artificial-heart/artifact_commands.snap | 296 +-- .../artifact_graph_flowchart.snap.md | 150 +- .../kcl_samples/artificial-heart/ops.snap | 242 ++- .../axial-fan/artifact_commands.snap | 42 +- .../artifact_graph_flowchart.snap.md | 14 +- .../tests/kcl_samples/axial-fan/ops.snap | 67 +- .../cycloidal-gear/artifact_commands.snap | 68 +- .../artifact_graph_flowchart.snap.md | 122 +- .../tests/kcl_samples/cycloidal-gear/ast.snap | 387 +++- .../tests/kcl_samples/cycloidal-gear/ops.snap | 134 +- .../cycloidal-gear/program_memory.snap | 920 ++++---- .../artifact_commands.snap | 24 +- .../artifact_graph_flowchart.snap.md | 96 +- .../kcl_samples/field-monitor-stand/ast.snap | 180 +- .../kcl_samples/field-monitor-stand/ops.snap | 67 +- .../field-monitor-stand/program_memory.snap | 484 ++--- .../m4-insert/artifact_commands.snap | 56 +- .../artifact_graph_flowchart.snap.md | 36 +- .../tests/kcl_samples/m4-insert/ast.snap | 198 +- .../tests/kcl_samples/m4-insert/ops.snap | 67 +- .../kcl_samples/m4-insert/program_memory.snap | 640 +++--- .../multi-axis-robot/artifact_commands.snap | 112 +- .../artifact_graph_flowchart.snap.md | 50 +- .../kcl_samples/multi-axis-robot/ops.snap | 328 ++- .../wheel-hub/artifact_commands.snap | 20 +- .../artifact_graph_flowchart.snap.md | 218 +- .../tests/kcl_samples/wheel-hub/ast.snap | 189 +- .../tests/kcl_samples/wheel-hub/ops.snap | 67 +- .../kcl_samples/wheel-hub/program_memory.snap | 642 +++--- .../zoo-logo/artifact_commands.snap | 264 +-- .../zoo-logo/artifact_graph_flowchart.snap.md | 246 +-- .../tests/kcl_samples/zoo-logo/ast.snap | 360 +++- .../tests/kcl_samples/zoo-logo/ops.snap | 134 +- .../kcl_samples/zoo-logo/program_memory.snap | 1896 ++++++++--------- 40 files changed, 5316 insertions(+), 4078 deletions(-) diff --git a/public/kcl-samples/angle-gauge/main.kcl b/public/kcl-samples/angle-gauge/main.kcl index 8088291835f..fab1f7298f3 100644 --- a/public/kcl-samples/angle-gauge/main.kcl +++ b/public/kcl-samples/angle-gauge/main.kcl @@ -89,12 +89,12 @@ gaugeProfileSketch = sketch(on = XY) { horizontal(cutoutAngleReferenceEdge) vertical(cutoutLeftVerticalEdge) angleDimension( - lines = [ - cutoutAngleReferenceEdge, - cutoutAngledEdge - ], - sector = 1, - ) == cutoutAngle + lines = [ + cutoutAngleReferenceEdge, + cutoutAngledEdge + ], + sector = 1, +) == cutoutAngle horizontalDistance([cutoutTopEdge.start, cutoutTopEdge.end]) == cutoutDepth verticalDistance([ diff --git a/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_commands.snap index 5688d87ea33..dfb47c1164a 100644 --- a/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_commands.snap @@ -68,8 +68,8 @@ description: Artifact commands angle-gauge.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -0.000000000000005470563661224636, - "y": -0.0000000000002671510715623786, + "x": -0.000000000000008871143589702368, + "y": 0.0000000000017594939780231368, "z": 0.0 } } @@ -90,8 +90,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": -0.000000000000005563073285335113, - "y": 31.749999999999734, + "x": -0.00000000000000896273599483877, + "y": 31.75000000000176, "z": 0.0 }, "relative": false @@ -107,8 +107,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": 38.100000000000136, - "y": 31.749999999999734, + "x": 38.099999999998694, + "y": 31.75000000000176, "z": 0.0 }, "relative": false @@ -124,8 +124,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": 38.10000000000014, - "y": 20.827999999998664, + "x": 38.099999999998694, + "y": 20.828000000008817, "z": 0.0 }, "relative": false @@ -139,8 +139,8 @@ description: Artifact commands angle-gauge.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 38.09999999999997, - "y": 7.619999999998664, + "x": 38.09999999999995, + "y": 7.6200000000087975, "z": 0.0 } } @@ -154,8 +154,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": 38.09999999999997, - "y": -0.0000000000010682787109752386, + "x": 38.099999999999966, + "y": 0.000000000007038363044587781, "z": 0.0 }, "relative": false @@ -171,8 +171,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": -0.000000000000010802362883657258, - "y": -0.000000000000534228148747105, + "x": -0.00000000000001760489857432643, + "y": 0.0000000000035190759406999834, "z": 0.0 }, "relative": false @@ -186,8 +186,8 @@ description: Artifact commands angle-gauge.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 38.09999999999992, - "y": 7.619999999998398, + "x": 38.100000000000264, + "y": 7.620000000010539, "z": 0.0 } } @@ -201,8 +201,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": 12.70000000000033, - "y": 12.098705309990343, + "x": 12.699999999997452, + "y": 12.098705307844186, "z": 0.0 }, "relative": false @@ -218,8 +218,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": 12.700000000000236, - "y": 20.827999999998664, + "x": 12.699999999998075, + "y": 20.828000000008817, "z": 0.0 }, "relative": false @@ -235,8 +235,8 @@ description: Artifact commands angle-gauge.kcl "segment": { "type": "line", "end": { - "x": 38.10000000000014, - "y": 20.827999999998664, + "x": 38.099999999998694, + "y": 20.828000000008817, "z": 0.0 }, "relative": false diff --git a/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_graph_flowchart.snap.md index 1c8dbe11e56..76eea807493 100644 --- a/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/angle-gauge/artifact_graph_flowchart.snap.md @@ -1,7 +1,7 @@ ```mermaid flowchart LR subgraph path2 [Path] - 2["Path
[361, 3073, 0]
Consumed: false"] + 2["Path
[361, 3115, 0]
Consumed: false"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] 3["Segment
[418, 479, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit] @@ -21,28 +21,28 @@ flowchart LR %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 21 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path11 [Path] - 11["Path Region
[3089, 3142, 0]
Consumed: true"] + 11["Path Region
[3131, 3184, 0]
Consumed: true"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 12["Segment
[3089, 3142, 0]"] + 12["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 13["Segment
[3089, 3142, 0]"] + 13["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 14["Segment
[3089, 3142, 0]"] + 14["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 15["Segment
[3089, 3142, 0]"] + 15["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 16["Segment
[3089, 3142, 0]"] + 16["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 17["Segment
[3089, 3142, 0]"] + 17["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 18["Segment
[3089, 3142, 0]"] + 18["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 19["Segment
[3089, 3142, 0]"] + 19["Segment
[3131, 3184, 0]"] %% [ProgramBodyItem { index: 8 }, VariableDeclarationDeclaration, VariableDeclarationInit] end - 1["Plane
[361, 3073, 0]"] + 1["Plane
[361, 3115, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 20["Sweep Extrusion
[3180, 3225, 0]
Consumed: false"] + 20["Sweep Extrusion
[3222, 3267, 0]
Consumed: false"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit] 21[Wall] %% face_code_ref=Missing NodePath @@ -80,7 +80,7 @@ flowchart LR 44["SweepEdge Adjacent"] 45["SweepEdge Opposite"] 46["SweepEdge Adjacent"] - 47["SketchBlock
[361, 3073, 0]"] + 47["SketchBlock
[361, 3115, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] 48["SketchBlockConstraint Coincident
[953, 994, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] @@ -126,15 +126,15 @@ flowchart LR %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 30 }, ExpressionStatementExpr] 69["SketchBlockConstraint Vertical
[2608, 2640, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 31 }, ExpressionStatementExpr] - 70["SketchBlockConstraint Angle
[2643, 2715, 0]"] + 70["SketchBlockConstraint Angle
[2643, 2757, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 32 }, ExpressionStatementExpr] - 71["SketchBlockConstraint HorizontalDistance
[2719, 2794, 0]"] + 71["SketchBlockConstraint HorizontalDistance
[2761, 2836, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 33 }, ExpressionStatementExpr] - 72["SketchBlockConstraint VerticalDistance
[2797, 2904, 0]"] + 72["SketchBlockConstraint VerticalDistance
[2839, 2946, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 34 }, ExpressionStatementExpr] - 73["SketchBlockConstraint VerticalDistance
[2907, 2979, 0]"] + 73["SketchBlockConstraint VerticalDistance
[2949, 3021, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 35 }, ExpressionStatementExpr] - 74["SketchBlockConstraint Coincident
[2982, 3071, 0]"] + 74["SketchBlockConstraint Coincident
[3024, 3113, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 36 }, ExpressionStatementExpr] 1 --- 2 1 <--x 11 diff --git a/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap b/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap index 2e3f59502f2..b154dcaa3c5 100644 --- a/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/angle-gauge/ast.snap @@ -4290,7 +4290,89 @@ description: Result of parsing angle-gauge.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cutoutAngleReferenceEdge", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "cutoutAngledEdge", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -4300,7 +4382,7 @@ description: Result of parsing angle-gauge.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -4314,52 +4396,7 @@ description: Result of parsing angle-gauge.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "cutoutAngleReferenceEdge", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "cutoutAngledEdge", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", diff --git a/rust/kcl-lib/tests/kcl_samples/angle-gauge/ops.snap b/rust/kcl-lib/tests/kcl_samples/angle-gauge/ops.snap index 666ab40e36a..f40429de113 100644 --- a/rust/kcl-lib/tests/kcl_samples/angle-gauge/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/angle-gauge/ops.snap @@ -2037,22 +2037,35 @@ description: Operations executed angle-gauge.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/angle-gauge/program_memory.snap b/rust/kcl-lib/tests/kcl_samples/angle-gauge/program_memory.snap index 9a09085552d..289edd6ac20 100644 --- a/rust/kcl-lib/tests/kcl_samples/angle-gauge/program_memory.snap +++ b/rust/kcl-lib/tests/kcl_samples/angle-gauge/program_memory.snap @@ -213,8 +213,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "tag": { "commentStart": 402, @@ -225,8 +225,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "leftOuterEdge" }, "to": [ - -0.00000000000000021901863328090998, - 1.2499999999999896 + -0.0000000000000003528636218440461, + 1.2500000000000693 ], "type": "ToPoint", "units": "in" @@ -237,8 +237,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000021901863328090998, - 1.2499999999999896 + -0.0000000000000003528636218440461, + 1.2500000000000693 ], "tag": { "commentStart": 482, @@ -249,8 +249,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "topOuterEdge" }, "to": [ - 1.5000000000000056, - 1.2499999999999896 + 1.4999999999999487, + 1.2500000000000693 ], "type": "ToPoint", "units": "in" @@ -261,8 +261,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.5000000000000056, - 1.2499999999999896 + 1.4999999999999487, + 1.2500000000000693 ], "tag": { "commentStart": 566, @@ -273,8 +273,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "upperRightOuterEdge" }, "to": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -285,8 +285,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.499999999999999, - 0.2999999999999474 + 1.4999999999999982, + 0.3000000000003464 ], "tag": { "commentStart": 781, @@ -297,8 +297,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "lowerRightOuterEdge" }, "to": [ - 1.4999999999999991, - -0.00000000000004205821696752908 + 1.4999999999999987, + 0.00000000000027710090726723547 ], "type": "ToPoint", "units": "in" @@ -309,8 +309,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.4999999999999991, - -0.00000000000004205821696752908 + 1.4999999999999987, + 0.00000000000027710090726723547 ], "tag": { "commentStart": 871, @@ -321,8 +321,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "bottomOuterEdge" }, "to": [ - -0.00000000000000042528987730934088, - -0.00000000000002103260428138209 + -0.0000000000000006931062430837178, + 0.00000000000013854629687795212 ], "type": "ToPoint", "units": "in" @@ -333,8 +333,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.4999999999999971, - 0.29999999999993693 + 1.5000000000000104, + 0.30000000000041493 ], "tag": { "commentStart": 1672, @@ -345,8 +345,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutAngledEdge" }, "to": [ - 0.500000000000013, - 0.4763269807082813 + 0.4999999999998997, + 0.4763269806237869 ], "type": "ToPoint", "units": "in" @@ -357,8 +357,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 0.500000000000013, - 0.4763269807082813 + 0.4999999999998997, + 0.4763269806237869 ], "tag": { "commentStart": 1762, @@ -369,8 +369,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutLeftVerticalEdge" }, "to": [ - 0.5000000000000093, - 0.8199999999999474 + 0.4999999999999242, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -381,8 +381,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 0.5000000000000093, - 0.8199999999999474 + 0.4999999999999242, + 0.8200000000003471 ], "tag": { "commentStart": 1859, @@ -393,8 +393,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutTopEdge" }, "to": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -433,12 +433,12 @@ description: Variables in memory after executing angle-gauge.kcl }, "start": { "from": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "to": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "units": "in", "tag": null, @@ -516,7 +516,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 1.4999999999999993, + "n": 1.499999999999999, "ty": { "in": null, "type": "Known", @@ -524,7 +524,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": -0.00000000000003154628457385997, + "n": 0.0000000000002078225628836257, "ty": { "in": null, "type": "Known", @@ -534,7 +534,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": -0.00000000000000042528987730934088, + "n": -0.0000000000000006931062430837178, "ty": { "in": null, "type": "Known", @@ -542,7 +542,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": -0.00000000000002103260428138209, + "n": 0.00000000000013854629687795212, "ty": { "in": null, "type": "Known", @@ -636,7 +636,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 1.5000000000000007, + "n": 1.499999999999986, "ty": { "in": null, "type": "Known", @@ -644,7 +644,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.29999999999994736, + "n": 0.3000000000003471, "ty": { "in": null, "type": "Known", @@ -654,7 +654,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 2.2410554645145, + "n": 2.2230002705167826, "ty": { "in": null, "type": "Known", @@ -662,7 +662,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.29999999999996196, + "n": 0.3000000000002284, "ty": { "in": null, "type": "Known", @@ -757,7 +757,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 1.4999999999999971, + "n": 1.5000000000000104, "ty": { "in": null, "type": "Known", @@ -765,7 +765,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.29999999999993693, + "n": 0.30000000000041493, "ty": { "in": null, "type": "Known", @@ -775,7 +775,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 0.500000000000013, + "n": 0.4999999999998997, "ty": { "in": null, "type": "Known", @@ -783,7 +783,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.4763269807082813, + "n": 0.4763269806237869, "ty": { "in": null, "type": "Known", @@ -877,7 +877,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 0.5000000000000111, + "n": 0.49999999999991196, "ty": { "in": null, "type": "Known", @@ -885,7 +885,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.47632698070827606, + "n": 0.47632698062382156, "ty": { "in": null, "type": "Known", @@ -895,7 +895,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 0.5000000000000093, + "n": 0.4999999999999242, "ty": { "in": null, "type": "Known", @@ -903,7 +903,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.8199999999999474, + "n": 0.8200000000003471, "ty": { "in": null, "type": "Known", @@ -997,7 +997,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 0.5000000000000075, + "n": 0.4999999999999365, "ty": { "in": null, "type": "Known", @@ -1005,7 +1005,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.8199999999999474, + "n": 0.8200000000003471, "ty": { "in": null, "type": "Known", @@ -1015,7 +1015,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 1.5000000000000058, + "n": 1.4999999999999487, "ty": { "in": null, "type": "Known", @@ -1023,7 +1023,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.8199999999999474, + "n": 0.8200000000003471, "ty": { "in": null, "type": "Known", @@ -1117,7 +1117,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": -0.00000000000000021537652209545812, + "n": -0.00000000000000034925762164182555, "ty": { "in": null, "type": "Known", @@ -1125,7 +1125,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": -0.000000000000010517758722928291, + "n": 0.00000000000006927141645760381, "ty": { "in": null, "type": "Known", @@ -1135,7 +1135,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": -0.00000000000000021901863328090998, + "n": -0.0000000000000003528636218440461, "ty": { "in": null, "type": "Known", @@ -1143,7 +1143,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 1.2499999999999896, + "n": 1.2500000000000693, "ty": { "in": null, "type": "Known", @@ -1237,7 +1237,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 1.499999999999999, + "n": 1.4999999999999982, "ty": { "in": null, "type": "Known", @@ -1245,7 +1245,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.2999999999999474, + "n": 0.3000000000003464, "ty": { "in": null, "type": "Known", @@ -1255,7 +1255,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 1.4999999999999991, + "n": 1.4999999999999987, "ty": { "in": null, "type": "Known", @@ -1263,7 +1263,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": -0.00000000000004205821696752908, + "n": 0.00000000000027710090726723547, "ty": { "in": null, "type": "Known", @@ -1360,8 +1360,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "tag": { "commentStart": 402, @@ -1372,8 +1372,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "leftOuterEdge" }, "to": [ - -0.00000000000000021901863328090998, - 1.2499999999999896 + -0.0000000000000003528636218440461, + 1.2500000000000693 ], "type": "ToPoint", "units": "in" @@ -1384,8 +1384,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000021901863328090998, - 1.2499999999999896 + -0.0000000000000003528636218440461, + 1.2500000000000693 ], "tag": { "commentStart": 482, @@ -1396,8 +1396,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "topOuterEdge" }, "to": [ - 1.5000000000000056, - 1.2499999999999896 + 1.4999999999999487, + 1.2500000000000693 ], "type": "ToPoint", "units": "in" @@ -1408,8 +1408,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.5000000000000056, - 1.2499999999999896 + 1.4999999999999487, + 1.2500000000000693 ], "tag": { "commentStart": 566, @@ -1420,8 +1420,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "upperRightOuterEdge" }, "to": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -1432,13 +1432,13 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "tag": null, "to": [ - 1.499999999999999, - 0.2999999999999474 + 1.4999999999999982, + 0.3000000000003464 ], "type": "ToPoint", "units": "in" @@ -1449,8 +1449,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.499999999999999, - 0.2999999999999474 + 1.4999999999999982, + 0.3000000000003464 ], "tag": { "commentStart": 781, @@ -1461,8 +1461,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "lowerRightOuterEdge" }, "to": [ - 1.4999999999999991, - -0.00000000000004205821696752908 + 1.4999999999999987, + 0.00000000000027710090726723547 ], "type": "ToPoint", "units": "in" @@ -1473,8 +1473,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.4999999999999991, - -0.00000000000004205821696752908 + 1.4999999999999987, + 0.00000000000027710090726723547 ], "tag": { "commentStart": 871, @@ -1485,8 +1485,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "bottomOuterEdge" }, "to": [ - -0.00000000000000042528987730934088, - -0.00000000000002103260428138209 + -0.0000000000000006931062430837178, + 0.00000000000013854629687795212 ], "type": "ToPoint", "units": "in" @@ -1497,13 +1497,13 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000042528987730934088, - -0.00000000000002103260428138209 + -0.0000000000000006931062430837178, + 0.00000000000013854629687795212 ], "tag": null, "to": [ - 1.4999999999999971, - 0.29999999999993693 + 1.5000000000000104, + 0.30000000000041493 ], "type": "ToPoint", "units": "in" @@ -1514,8 +1514,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.4999999999999971, - 0.29999999999993693 + 1.5000000000000104, + 0.30000000000041493 ], "tag": { "commentStart": 1672, @@ -1526,8 +1526,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutAngledEdge" }, "to": [ - 0.500000000000013, - 0.4763269807082813 + 0.4999999999998997, + 0.4763269806237869 ], "type": "ToPoint", "units": "in" @@ -1538,8 +1538,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 0.500000000000013, - 0.4763269807082813 + 0.4999999999998997, + 0.4763269806237869 ], "tag": { "commentStart": 1762, @@ -1550,8 +1550,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutLeftVerticalEdge" }, "to": [ - 0.5000000000000093, - 0.8199999999999474 + 0.4999999999999242, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -1562,8 +1562,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 0.5000000000000093, - 0.8199999999999474 + 0.4999999999999242, + 0.8200000000003471 ], "tag": { "commentStart": 1859, @@ -1574,8 +1574,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutTopEdge" }, "to": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -1614,12 +1614,12 @@ description: Variables in memory after executing angle-gauge.kcl }, "start": { "from": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "to": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "units": "in", "tag": null, @@ -1683,7 +1683,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 1.500000000000004, + "n": 1.4999999999999611, "ty": { "in": null, "type": "Known", @@ -1691,7 +1691,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.8199999999999474, + "n": 0.8200000000003471, "ty": { "in": null, "type": "Known", @@ -1701,7 +1701,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 1.5000000000000022, + "n": 1.4999999999999736, "ty": { "in": null, "type": "Known", @@ -1709,7 +1709,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.29999999999994736, + "n": 0.3000000000003471, "ty": { "in": null, "type": "Known", @@ -1804,7 +1804,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": -0.00000000000000022083968877023834, + "n": -0.0000000000000003546666218417588, "ty": { "in": null, "type": "Known", @@ -1812,7 +1812,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 1.2499999999999896, + "n": 1.2500000000000693, "ty": { "in": null, "type": "Known", @@ -1822,7 +1822,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 1.5000000000000056, + "n": 1.4999999999999487, "ty": { "in": null, "type": "Known", @@ -1830,7 +1830,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 1.2499999999999896, + "n": 1.2500000000000693, "ty": { "in": null, "type": "Known", @@ -1924,7 +1924,7 @@ description: Variables in memory after executing angle-gauge.kcl "line": { "start": [ { - "n": 1.5000000000000056, + "n": 1.4999999999999487, "ty": { "in": null, "type": "Known", @@ -1932,7 +1932,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 1.2499999999999896, + "n": 1.2500000000000693, "ty": { "in": null, "type": "Known", @@ -1942,7 +1942,7 @@ description: Variables in memory after executing angle-gauge.kcl ], "end": [ { - "n": 1.5000000000000058, + "n": 1.4999999999999487, "ty": { "in": null, "type": "Known", @@ -1950,7 +1950,7 @@ description: Variables in memory after executing angle-gauge.kcl } }, { - "n": 0.8199999999999474, + "n": 0.8200000000003471, "ty": { "in": null, "type": "Known", @@ -2047,8 +2047,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "tag": { "commentStart": 402, @@ -2059,8 +2059,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "leftOuterEdge" }, "to": [ - -0.00000000000000021901863328090998, - 1.2499999999999896 + -0.0000000000000003528636218440461, + 1.2500000000000693 ], "type": "ToPoint", "units": "in" @@ -2071,8 +2071,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - -0.00000000000000021901863328090998, - 1.2499999999999896 + -0.0000000000000003528636218440461, + 1.2500000000000693 ], "tag": { "commentStart": 482, @@ -2083,8 +2083,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "topOuterEdge" }, "to": [ - 1.5000000000000056, - 1.2499999999999896 + 1.4999999999999487, + 1.2500000000000693 ], "type": "ToPoint", "units": "in" @@ -2095,8 +2095,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.5000000000000056, - 1.2499999999999896 + 1.4999999999999487, + 1.2500000000000693 ], "tag": { "commentStart": 566, @@ -2107,8 +2107,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "upperRightOuterEdge" }, "to": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -2119,8 +2119,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.499999999999999, - 0.2999999999999474 + 1.4999999999999982, + 0.3000000000003464 ], "tag": { "commentStart": 781, @@ -2131,8 +2131,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "lowerRightOuterEdge" }, "to": [ - 1.4999999999999991, - -0.00000000000004205821696752908 + 1.4999999999999987, + 0.00000000000027710090726723547 ], "type": "ToPoint", "units": "in" @@ -2143,8 +2143,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.4999999999999991, - -0.00000000000004205821696752908 + 1.4999999999999987, + 0.00000000000027710090726723547 ], "tag": { "commentStart": 871, @@ -2155,8 +2155,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "bottomOuterEdge" }, "to": [ - -0.00000000000000042528987730934088, - -0.00000000000002103260428138209 + -0.0000000000000006931062430837178, + 0.00000000000013854629687795212 ], "type": "ToPoint", "units": "in" @@ -2167,8 +2167,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 1.4999999999999971, - 0.29999999999993693 + 1.5000000000000104, + 0.30000000000041493 ], "tag": { "commentStart": 1672, @@ -2179,8 +2179,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutAngledEdge" }, "to": [ - 0.500000000000013, - 0.4763269807082813 + 0.4999999999998997, + 0.4763269806237869 ], "type": "ToPoint", "units": "in" @@ -2191,8 +2191,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 0.500000000000013, - 0.4763269807082813 + 0.4999999999998997, + 0.4763269806237869 ], "tag": { "commentStart": 1762, @@ -2203,8 +2203,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutLeftVerticalEdge" }, "to": [ - 0.5000000000000093, - 0.8199999999999474 + 0.4999999999999242, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -2215,8 +2215,8 @@ description: Variables in memory after executing angle-gauge.kcl "sourceRange": [] }, "from": [ - 0.5000000000000093, - 0.8199999999999474 + 0.4999999999999242, + 0.8200000000003471 ], "tag": { "commentStart": 1859, @@ -2227,8 +2227,8 @@ description: Variables in memory after executing angle-gauge.kcl "value": "cutoutTopEdge" }, "to": [ - 1.5000000000000058, - 0.8199999999999474 + 1.4999999999999487, + 0.8200000000003471 ], "type": "ToPoint", "units": "in" @@ -2267,12 +2267,12 @@ description: Variables in memory after executing angle-gauge.kcl }, "start": { "from": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "to": [ - -0.00000000000000021537652209545812, - -0.000000000000010517758722928291 + -0.00000000000000034925762164182555, + 0.00000000000006927141645760381 ], "units": "in", "tag": null, diff --git a/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_commands.snap index 9b781b005b0..705ea8b1d02 100644 --- a/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_commands.snap @@ -2149,8 +2149,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -0.0000000009693377544070806, - "y": 17.779999999996544, + "x": -0.0000000008776478761612218, + "y": 17.779999999995265, "z": 0.0 } } @@ -2171,8 +2171,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": 0.0000000009729454849979131, - "y": 19.049999999993087, + "x": 0.0000000008823159536764125, + "y": 19.049999999990536, "z": 0.0 }, "relative": false @@ -2186,8 +2186,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 13.510950201157776, - "y": 31.214146180638938, + "x": 13.509643205740621, + "y": 31.212863407285756, "z": 0.0 } } @@ -2201,17 +2201,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 12.232324095789393, - "y": 19.04883196621969 + "x": 12.231140826637322, + "y": 19.048725980725802 }, - "radius": 12.232324172162887, + "radius": 12.231140897954264, "start": { "unit": "degrees", - "value": 83.99999972937486 + "value": 83.99999991978497 }, "end": { "unit": "degrees", - "value": 179.99452897055335 + "value": 179.99403196091203 }, "relative": false } @@ -2224,8 +2224,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 13.510950226873518, - "y": 31.21414642530402, + "x": 13.509643229510235, + "y": 31.212863633438378, "z": 0.0 } } @@ -2239,17 +2239,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 33.42476695395223, - "y": 220.01558444078742 + "x": 33.41621670626058, + "y": 219.9719239938059 }, - "radius": 189.84873740258084, + "radius": 189.80583377682078, "start": { "unit": "degrees", - "value": -96.02100584942686 + "value": -96.02017325363231 }, "end": { "unit": "degrees", - "value": -93.87877453165292 + "value": -93.87709373749416 }, "relative": false } @@ -3123,8 +3123,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -0.9182591421686775, - "y": -18.03252574947049, + "x": -0.9182591423357014, + "y": -18.03252574936985, "z": 0.0 } } @@ -3145,17 +3145,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 12.060212497123256, - "y": 3.5053615433981147 + "x": 12.060212497123215, + "y": 3.505361543398137 }, - "radius": 25.14599998274509, + "radius": 25.145999982745092, "start": { "unit": "degrees", - "value": -121.07266101448798 + "value": -121.07266101493218 }, "end": { "unit": "degrees", - "value": -0.9950070776550731 + "value": -0.9950070776553854 }, "relative": false } @@ -3168,8 +3168,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 0.918259138931376, - "y": -14.987474255914684, + "x": 0.9182591390983952, + "y": -14.987474256015322, "z": 0.0 } } @@ -3183,17 +3183,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -0.000000000004013869792096614, + "x": -0.000000000004014046040001773, "y": -16.50999999999859 }, - "radius": 1.7780001371306542, + "radius": 1.778000137130734, "start": { "unit": "degrees", - "value": 58.90516290596299 + "value": 58.90516289967926 }, "end": { "unit": "degrees", - "value": 238.90516290655265 + "value": 238.90516290026872 }, "relative": false } @@ -3206,8 +3206,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 0.9182591391935951, - "y": -14.987474255480794, + "x": 0.918259139360614, + "y": -14.987474255581434, "z": 0.0 } } @@ -3221,17 +3221,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 12.060212496353996, - "y": 3.5053615429725644 + "x": 12.06021249635396, + "y": 3.5053615429725844 }, - "radius": 21.59000001115554, + "radius": 21.590000011155542, "start": { "unit": "degrees", - "value": -121.06900848241992 + "value": -121.06900848190232 }, "end": { "unit": "degrees", - "value": -0.9966608909601627 + "value": -0.9966608909581333 }, "relative": false } @@ -3246,17 +3246,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 35.42468346909333, - "y": 3.0992582120183103 + "x": 35.42468346909331, + "y": 3.099258212018647 }, - "radius": 1.7780000177446762, + "radius": 1.7780000177446726, "start": { "unit": "degrees", - "value": 179.0150339385861 + "value": 179.01503393857166 }, "end": { "unit": "degrees", - "value": -0.9849660611277614 + "value": -0.9849660611423702 }, "relative": false } @@ -3712,8 +3712,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -29.634845205605977, - "y": 29.634845193455018, + "x": -29.63484520560841, + "y": 29.63484519345258, "z": 0.0 } } @@ -3734,17 +3734,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -58.373393461184605, - "y": 0.8997543045501923 + "x": -58.373393459583305, + "y": 0.8997543029443681 }, - "radius": 40.640000052064984, + "radius": 40.64000005206461, "start": { "unit": "degrees", - "value": 44.9965533326 + "value": 44.996553335797195 }, "end": { "unit": "degrees", - "value": 210.17340915106521 + "value": 210.17340917798805 }, "relative": false } @@ -3757,8 +3757,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -93.50700515052357, - "y": -19.526673146987697, + "x": -93.50700513932391, + "y": -19.52667316510242, "z": 0.0 } } @@ -3772,8 +3772,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": -53.0469502359323, - "y": -89.13131971544587, + "x": -53.04695020452482, + "y": -89.13131969717116, "z": 0.0 }, "relative": false @@ -5391,8 +5391,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -5.424710661510406, - "y": 31.091784902401184, + "x": -5.424710025595025, + "y": 31.091782529071622, "z": 0.0 } } @@ -5413,8 +5413,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": -3.72329556637873, - "y": 24.742017322172238, + "x": -3.723296132589528, + "y": 24.742019435171052, "z": 0.0 }, "relative": false @@ -5428,8 +5428,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 3.7232936482061607, - "y": 24.742010168153637, + "x": 3.7232942208705415, + "y": 24.742012305300868, "z": 0.0 } } @@ -5443,8 +5443,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": 5.424708875746087, - "y": 31.091778241655177, + "x": 5.424708245796701, + "y": 31.09177589053439, "z": 0.0 }, "relative": false @@ -5458,8 +5458,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -3.7232955639926475, - "y": 24.742017322812178, + "x": -3.7232961302035235, + "y": 24.74201943581097, "z": 0.0 } } @@ -5473,17 +5473,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -1.2700000003607235, - "y": 25.399999999801317 + "x": -1.27000000034952, + "y": 25.39999999980705 }, - "radius": 2.540000064124777, + "radius": 2.54000006365221, "start": { "unit": "degrees", - "value": -164.98640136980242 + "value": -164.98645071508236 }, "end": { "unit": "degrees", - "value": -91.54119094894406 + "value": -91.54119244363042 }, "relative": false } @@ -5496,8 +5496,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 1.3383195534209114, - "y": 22.860918966610527, + "x": 1.3383195539059614, + "y": 22.86091896662131, "z": 0.0 } } @@ -5511,17 +5511,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 1.2699999996385447, - "y": 25.399999999994453 + "x": 1.2699999996500109, + "y": 25.399999999994193 }, - "radius": 2.5400000109289382, + "radius": 2.5400000109306404, "start": { "unit": "degrees", - "value": -88.45870306158143 + "value": -88.45870305089579 }, "end": { "unit": "degrees", - "value": -15.01376570626965 + "value": -15.013715797149693 }, "relative": false } @@ -5534,8 +5534,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -1.33831485726197, - "y": 22.86091883718223, + "x": -1.3383149234880718, + "y": 22.860918838977835, "z": 0.0 } } @@ -5549,17 +5549,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -0.0000000031307902381705333, - "y": 72.389544255343 + "x": -0.000000002981773163102108, + "y": 72.38954425480674 }, - "radius": 49.546703446962745, + "radius": 49.546703446424594, "start": { "unit": "degrees", - "value": -91.54781478564223 + "value": -91.54781486244322 }, "end": { "unit": "degrees", - "value": -88.45217977442299 + "value": -88.45217977401745 }, "relative": false } @@ -5572,8 +5572,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -3.071696193639226, - "y": 34.288022130911166, + "x": -3.0716961552180813, + "y": 34.28802213240644, "z": 0.0 } } @@ -5587,17 +5587,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -2.971477369731435, - "y": 31.750000000033918 + "x": -2.9714773698179306, + "y": 31.7500000000341 }, - "radius": 2.540000029426803, + "radius": 2.5400000294013627, "start": { "unit": "degrees", - "value": 92.26126240069146 + "value": 92.2612615314052 }, "end": { "unit": "degrees", - "value": 195.0190263501423 + "value": 195.0190817752291 }, "relative": false } @@ -5610,8 +5610,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 5.424708872125542, - "y": 31.091778242627008, + "x": 5.4247082421759, + "y": 31.091775891506284, "z": 0.0 } } @@ -5625,17 +5625,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 2.971477369883488, - "y": 31.74999999999318 + "x": 2.9714773699701293, + "y": 31.74999999999327 }, - "radius": 2.540000134933662, + "radius": 2.5400001356962507, "start": { "unit": "degrees", - "value": -15.019181905378145 + "value": -15.019236811730883 }, "end": { "unit": "degrees", - "value": 87.7386775739038 + "value": 87.73867761594234 }, "relative": false } @@ -5648,8 +5648,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 3.071698852825573, - "y": 34.28802202836832, + "x": 3.0716988510484686, + "y": 34.28802202840215, "z": 0.0 } } @@ -5663,17 +5663,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 0.0000000054411080557814625, - "y": -43.18073591138913 + "x": 0.000000005336331848626585, + "y": -43.180734941210005 }, - "radius": 77.52963169355156, + "radius": 77.52963072410175, "start": { "unit": "degrees", - "value": 87.7293655022965 + "value": 87.7293654751259 }, "end": { "unit": "degrees", - "value": 92.27063253909354 + "value": 92.27063253900725 }, "relative": false } @@ -5686,8 +5686,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -2.9721324904278315, - "y": 36.82999998769232, + "x": -2.9722529034875835, + "y": 36.829999987413146, "z": 0.0 } } @@ -5701,17 +5701,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -2.9714773692738095, - "y": 31.75000000015776 + "x": -2.9714773693832335, + "y": 31.750000000151854 }, - "radius": 5.080000029777056, + "radius": 5.080000046459435, "start": { "unit": "degrees", - "value": 90.00738891281087 + "value": 90.00874701393975 }, "end": { "unit": "degrees", - "value": 194.99486247134405 + "value": 194.99481573711867 }, "relative": false } @@ -5724,8 +5724,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -6.177065836759492, - "y": 24.08580633994818, + "x": -6.177061916834697, + "y": 24.08579170767952, "z": 0.0 } } @@ -5739,17 +5739,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": -1.2700000018774762, - "y": 25.399999999395764 + "x": -1.2700000018146629, + "y": 25.399999999415307 }, - "radius": 5.080000008110095, + "radius": 5.080000007077478, "start": { "unit": "degrees", - "value": -165.0070886297157 + "value": -165.00691777731066 }, "end": { "unit": "degrees", - "value": -89.99999071260578 + "value": -89.99998832091126 }, "relative": false } @@ -5762,8 +5762,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 1.2700007112857352, - "y": 20.32000000460918, + "x": 1.2700009971425699, + "y": 20.320000004479535, "z": 0.0 } } @@ -5777,17 +5777,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 1.2699999988788293, - "y": 25.400000000198585 + "x": 1.2699999989114572, + "y": 25.40000000019261 }, - "radius": 5.079999995589454, + "radius": 5.07999999571317, "start": { "unit": "degrees", - "value": -89.99999196497853 + "value": -89.99998874125399 }, "end": { "unit": "degrees", - "value": -14.994549131711334 + "value": -14.994614546454347 }, "relative": false } @@ -5800,8 +5800,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 7.878489852087481, - "y": 30.4356071497154, + "x": 7.878489408146426, + "y": 30.435605492418453, "z": 0.0 } } @@ -5815,17 +5815,17 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "arc", "center": { - "x": 2.9714773695869963, - "y": 31.750000000073335 + "x": 2.971477369681687, + "y": 31.75000000007137 }, - "radius": 5.0800000067409075, + "radius": 5.080000006632484, "start": { "unit": "degrees", - "value": -14.99523717580697 + "value": -14.99525652721885 }, "end": { "unit": "degrees", - "value": 89.99260129335995 + "value": 89.99124431618002 }, "relative": false } @@ -5838,8 +5838,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -7.878498451163981, - "y": 30.43563923987623, + "x": -7.878499523718158, + "y": 30.435643242263275, "z": 0.0 } } @@ -5853,8 +5853,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": -6.177065841271341, - "y": 24.08580633873981, + "x": -6.177061921199583, + "y": 24.085791706510484, "z": 0.0 }, "relative": false @@ -5868,8 +5868,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 6.177028266061296, - "y": 24.085666076196194, + "x": 6.177026765305146, + "y": 24.085660473879383, "z": 0.0 } } @@ -5883,8 +5883,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": 7.87848985598222, - "y": 30.43560714867209, + "x": 7.878489412033162, + "y": 30.43560549137729, "z": 0.0 }, "relative": false @@ -5898,8 +5898,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -1.2699991784317872, - "y": 20.319999999705814, + "x": -1.2699989663148168, + "y": 20.319999999715282, "z": 0.0 } } @@ -5913,8 +5913,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": 1.2700007112857352, - "y": 20.32000000439994, + "x": 1.2700009971425699, + "y": 20.320000004271506, "z": 0.0 }, "relative": false @@ -5928,8 +5928,8 @@ description: Artifact commands artificial-heart.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -2.9721324904283892, - "y": 36.829999992365146, + "x": -2.9722529034882768, + "y": 36.82999999220788, "z": 0.0 } } @@ -5943,8 +5943,8 @@ description: Artifact commands artificial-heart.kcl "segment": { "type": "line", "end": { - "x": 2.9721333590891867, - "y": 36.82999999230949, + "x": 2.9722536724819637, + "y": 36.829999992147016, "z": 0.0 }, "relative": false diff --git a/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_graph_flowchart.snap.md index 17727e3ecc4..7657d5198ca 100644 --- a/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/artificial-heart/artifact_graph_flowchart.snap.md @@ -1091,17 +1091,17 @@ flowchart LR %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 12 }, ExpressionStatementExpr] 563["SketchBlockConstraint Coincident
[9505, 9540, 1]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 13 }, ExpressionStatementExpr] - 564["SketchBlockConstraint Angle
[9543, 9569, 1]"] + 564["SketchBlockConstraint Angle
[9543, 9632, 1]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 14 }, ExpressionStatementExpr] 565["SketchBlock
[173, 204, 0]"] %% [ProgramBodyItem { index: 0 }] - 566["SketchBlockConstraint Coincident
[9771, 9807, 1]"] + 566["SketchBlockConstraint Coincident
[9834, 9870, 1]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 567["SketchBlockConstraint Coincident
[9892, 9936, 1]"] + 567["SketchBlockConstraint Coincident
[9955, 9999, 1]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 568["SketchBlockConstraint Radius
[9939, 9961, 1]"] + 568["SketchBlockConstraint Radius
[10002, 10024, 1]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 569["SketchBlockConstraint Radius
[9964, 9987, 1]"] + 569["SketchBlockConstraint Radius
[10027, 10050, 1]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] 570["SketchBlock
[205, 234, 0]"] %% [ProgramBodyItem { index: 1 }] @@ -1151,69 +1151,69 @@ flowchart LR %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 27 }, ExpressionStatementExpr] 593["SketchBlockConstraint Tangent
[2043, 2064, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 28 }, ExpressionStatementExpr] - 594["SketchBlockConstraint Angle
[2067, 2100, 2]"] + 594["SketchBlockConstraint Angle
[2067, 2154, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 29 }, ExpressionStatementExpr] - 595["SketchBlockConstraint Tangent
[2103, 2124, 2]"] + 595["SketchBlockConstraint Tangent
[2157, 2178, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 30 }, ExpressionStatementExpr] - 596["SketchBlockConstraint VerticalDistance
[2127, 2176, 2]"] + 596["SketchBlockConstraint VerticalDistance
[2181, 2230, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 31 }, ExpressionStatementExpr] - 597["SketchBlockConstraint HorizontalDistance
[2179, 2231, 2]"] + 597["SketchBlockConstraint HorizontalDistance
[2233, 2285, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 32 }, ExpressionStatementExpr] - 598["SketchBlockConstraint VerticalDistance
[2234, 2286, 2]"] + 598["SketchBlockConstraint VerticalDistance
[2288, 2340, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 33 }, ExpressionStatementExpr] - 599["SketchBlockConstraint Radius
[2289, 2307, 2]"] + 599["SketchBlockConstraint Radius
[2343, 2361, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 34 }, ExpressionStatementExpr] - 600["SketchBlockConstraint EqualRadius
[2310, 2335, 2]"] + 600["SketchBlockConstraint EqualRadius
[2364, 2389, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 35 }, ExpressionStatementExpr] - 601["SketchBlockConstraint Coincident
[2454, 2492, 2]"] + 601["SketchBlockConstraint Coincident
[2508, 2546, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 37 }, ExpressionStatementExpr] - 602["SketchBlockConstraint Coincident
[2608, 2646, 2]"] + 602["SketchBlockConstraint Coincident
[2662, 2700, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 39 }, ExpressionStatementExpr] - 603["SketchBlockConstraint Coincident
[2759, 2797, 2]"] + 603["SketchBlockConstraint Coincident
[2813, 2851, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 41 }, ExpressionStatementExpr] - 604["SketchBlockConstraint Coincident
[2914, 2953, 2]"] + 604["SketchBlockConstraint Coincident
[2968, 3007, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 43 }, ExpressionStatementExpr] - 605["SketchBlockConstraint Coincident
[3038, 3073, 2]"] + 605["SketchBlockConstraint Coincident
[3092, 3127, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 45 }, ExpressionStatementExpr] - 606["SketchBlockConstraint Coincident
[3076, 3111, 2]"] + 606["SketchBlockConstraint Coincident
[3130, 3165, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 46 }, ExpressionStatementExpr] - 607["SketchBlockConstraint Coincident
[3194, 3229, 2]"] + 607["SketchBlockConstraint Coincident
[3248, 3283, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 48 }, ExpressionStatementExpr] - 608["SketchBlockConstraint Coincident
[3232, 3268, 2]"] + 608["SketchBlockConstraint Coincident
[3286, 3322, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 49 }, ExpressionStatementExpr] - 609["SketchBlockConstraint Coincident
[3351, 3386, 2]"] + 609["SketchBlockConstraint Coincident
[3405, 3440, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 51 }, ExpressionStatementExpr] - 610["SketchBlockConstraint Coincident
[3389, 3424, 2]"] + 610["SketchBlockConstraint Coincident
[3443, 3478, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 52 }, ExpressionStatementExpr] - 611["SketchBlockConstraint Coincident
[3509, 3546, 2]"] + 611["SketchBlockConstraint Coincident
[3563, 3600, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 54 }, ExpressionStatementExpr] - 612["SketchBlockConstraint Coincident
[3549, 3583, 2]"] + 612["SketchBlockConstraint Coincident
[3603, 3637, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 55 }, ExpressionStatementExpr] - 613["SketchBlockConstraint Symmetric
[3586, 3624, 2]"] + 613["SketchBlockConstraint Symmetric
[3640, 3678, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 56 }, ExpressionStatementExpr] - 614["SketchBlockConstraint Symmetric
[3627, 3666, 2]"] + 614["SketchBlockConstraint Symmetric
[3681, 3720, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 57 }, ExpressionStatementExpr] - 615["SketchBlockConstraint Symmetric
[3669, 3706, 2]"] + 615["SketchBlockConstraint Symmetric
[3723, 3760, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 58 }, ExpressionStatementExpr] - 616["SketchBlockConstraint Parallel
[3709, 3733, 2]"] + 616["SketchBlockConstraint Parallel
[3763, 3787, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 59 }, ExpressionStatementExpr] - 617["SketchBlockConstraint Tangent
[3736, 3758, 2]"] + 617["SketchBlockConstraint Tangent
[3790, 3812, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 60 }, ExpressionStatementExpr] - 618["SketchBlockConstraint Tangent
[3761, 3783, 2]"] + 618["SketchBlockConstraint Tangent
[3815, 3837, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 61 }, ExpressionStatementExpr] - 619["SketchBlockConstraint Tangent
[3786, 3809, 2]"] + 619["SketchBlockConstraint Tangent
[3840, 3863, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 62 }, ExpressionStatementExpr] - 620["SketchBlockConstraint Tangent
[3812, 3835, 2]"] + 620["SketchBlockConstraint Tangent
[3866, 3889, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 63 }, ExpressionStatementExpr] - 621["SketchBlockConstraint Tangent
[3838, 3860, 2]"] + 621["SketchBlockConstraint Tangent
[3892, 3914, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 64 }, ExpressionStatementExpr] - 622["SketchBlockConstraint Tangent
[3863, 3885, 2]"] + 622["SketchBlockConstraint Tangent
[3917, 3939, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 65 }, ExpressionStatementExpr] - 623["SketchBlockConstraint Tangent
[3888, 3910, 2]"] + 623["SketchBlockConstraint Tangent
[3942, 3964, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 66 }, ExpressionStatementExpr] - 624["SketchBlockConstraint EqualRadius
[3913, 3938, 2]"] + 624["SketchBlockConstraint EqualRadius
[3967, 3992, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 67 }, ExpressionStatementExpr] - 625["SketchBlockConstraint Radius
[3941, 3960, 2]"] + 625["SketchBlockConstraint Radius
[3995, 4014, 2]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 68 }, ExpressionStatementExpr] 626["SketchBlock
[235, 268, 0]"] %% [ProgramBodyItem { index: 2 }] @@ -1341,11 +1341,11 @@ flowchart LR %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 29 }, ExpressionStatementExpr] 688["SketchBlockConstraint Tangent
[4916, 4937, 3]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 30 }, ExpressionStatementExpr] - 689["SketchBlockConstraint Angle
[4940, 4967, 3]"] + 689["SketchBlockConstraint Angle
[4940, 5030, 3]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 31 }, ExpressionStatementExpr] - 690["SketchBlockConstraint Distance
[4970, 5011, 3]"] + 690["SketchBlockConstraint Distance
[5033, 5074, 3]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 32 }, ExpressionStatementExpr] - 691["SketchBlockConstraint Coincident
[5014, 5052, 3]"] + 691["SketchBlockConstraint Coincident
[5077, 5115, 3]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 33 }, ExpressionStatementExpr] 692["SketchBlock
[269, 302, 0]"] %% [ProgramBodyItem { index: 3 }] @@ -1365,83 +1365,83 @@ flowchart LR %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] 700["SketchBlockConstraint Horizontal
[781, 798, 4]"] %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] - 701["SketchBlockConstraint Angle
[801, 828, 4]"] + 701["SketchBlockConstraint Angle
[801, 857, 4]"] %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 12 }, ExpressionStatementExpr] - 702["SketchBlockConstraint Distance
[831, 875, 4]"] + 702["SketchBlockConstraint Distance
[860, 904, 4]"] %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 13 }, ExpressionStatementExpr] - 703["SketchBlockConstraint Radius
[878, 901, 4]"] + 703["SketchBlockConstraint Radius
[907, 930, 4]"] %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 14 }, ExpressionStatementExpr] - 704["SketchBlockConstraint Coincident
[1007, 1048, 4]"] + 704["SketchBlockConstraint Coincident
[1036, 1077, 4]"] %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 16 }, ExpressionStatementExpr] - 705["SketchBlockConstraint Radius
[1051, 1075, 4]"] + 705["SketchBlockConstraint Radius
[1080, 1104, 4]"] %% [ProgramBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 17 }, ExpressionStatementExpr] 706["SketchBlock
[269, 302, 0]"] %% [ProgramBodyItem { index: 3 }] - 707["SketchBlockConstraint Coincident
[1297, 1330, 4]"] + 707["SketchBlockConstraint Coincident
[1326, 1359, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 708["SketchBlockConstraint Coincident
[1427, 1465, 4]"] + 708["SketchBlockConstraint Coincident
[1456, 1494, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 709["SketchBlockConstraint Coincident
[1468, 1494, 4]"] + 709["SketchBlockConstraint Coincident
[1497, 1523, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 710["SketchBlockConstraint LinesEqualLength
[1497, 1524, 4]"] + 710["SketchBlockConstraint LinesEqualLength
[1526, 1553, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] - 711["SketchBlockConstraint Coincident
[1613, 1652, 4]"] + 711["SketchBlockConstraint Coincident
[1642, 1681, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] - 712["SketchBlockConstraint Coincident
[1745, 1784, 4]"] + 712["SketchBlockConstraint Coincident
[1774, 1813, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, ExpressionStatementExpr] - 713["SketchBlockConstraint Coincident
[1877, 1916, 4]"] + 713["SketchBlockConstraint Coincident
[1906, 1945, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] - 714["SketchBlockConstraint Coincident
[2005, 2044, 4]"] + 714["SketchBlockConstraint Coincident
[2034, 2073, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 13 }, ExpressionStatementExpr] - 715["SketchBlockConstraint EqualRadius
[2047, 2078, 4]"] + 715["SketchBlockConstraint EqualRadius
[2076, 2107, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 14 }, ExpressionStatementExpr] - 716["SketchBlockConstraint EqualRadius
[2081, 2112, 4]"] + 716["SketchBlockConstraint EqualRadius
[2110, 2141, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 15 }, ExpressionStatementExpr] - 717["SketchBlockConstraint Radius
[2115, 2137, 4]"] + 717["SketchBlockConstraint Radius
[2144, 2166, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 16 }, ExpressionStatementExpr] - 718["SketchBlockConstraint Radius
[2140, 2162, 4]"] + 718["SketchBlockConstraint Radius
[2169, 2191, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 17 }, ExpressionStatementExpr] - 719["SketchBlockConstraint HorizontalDistance
[2165, 2224, 4]"] + 719["SketchBlockConstraint HorizontalDistance
[2194, 2253, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 18 }, ExpressionStatementExpr] - 720["SketchBlockConstraint VerticalDistance
[2227, 2283, 4]"] + 720["SketchBlockConstraint VerticalDistance
[2256, 2312, 4]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 19 }, ExpressionStatementExpr] 721["SketchBlock
[269, 302, 0]"] %% [ProgramBodyItem { index: 3 }] - 722["SketchBlockConstraint Horizontal
[2899, 2932, 4]"] + 722["SketchBlockConstraint Horizontal
[2928, 2961, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 723["SketchBlockConstraint Horizontal
[2935, 2966, 4]"] + 723["SketchBlockConstraint Horizontal
[2964, 2995, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, ExpressionStatementExpr] - 724["SketchBlockConstraint Coincident
[3082, 3115, 4]"] + 724["SketchBlockConstraint Coincident
[3111, 3144, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 725["SketchBlockConstraint Tangent
[3118, 3140, 4]"] + 725["SketchBlockConstraint Tangent
[3147, 3169, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] - 726["SketchBlockConstraint Coincident
[3260, 3296, 4]"] + 726["SketchBlockConstraint Coincident
[3289, 3325, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] - 727["SketchBlockConstraint Tangent
[3299, 3320, 4]"] + 727["SketchBlockConstraint Tangent
[3328, 3349, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 8 }, ExpressionStatementExpr] - 728["SketchBlockConstraint Distance
[3323, 3364, 4]"] + 728["SketchBlockConstraint Distance
[3352, 3393, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, ExpressionStatementExpr] - 729["SketchBlockConstraint HorizontalDistance
[3367, 3414, 4]"] + 729["SketchBlockConstraint HorizontalDistance
[3396, 3443, 4]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] 730["SketchBlock
[269, 302, 0]"] %% [ProgramBodyItem { index: 3 }] - 731["SketchBlockConstraint Horizontal
[3626, 3662, 4]"] + 731["SketchBlockConstraint Horizontal
[3655, 3691, 4]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 732["SketchBlockConstraint Coincident
[3751, 3795, 4]"] + 732["SketchBlockConstraint Coincident
[3780, 3824, 4]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 733["SketchBlockConstraint Radius
[3798, 3820, 4]"] + 733["SketchBlockConstraint Radius
[3827, 3849, 4]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 734["SketchBlockConstraint Radius
[3823, 3847, 4]"] + 734["SketchBlockConstraint Radius
[3852, 3876, 4]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] 735["SketchBlock
[269, 302, 0]"] %% [ProgramBodyItem { index: 3 }] - 736["SketchBlockConstraint Horizontal
[4381, 4417, 4]"] + 736["SketchBlockConstraint Horizontal
[4410, 4446, 4]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 737["SketchBlockConstraint Coincident
[4504, 4548, 4]"] + 737["SketchBlockConstraint Coincident
[4533, 4577, 4]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 738["SketchBlockConstraint Radius
[4551, 4573, 4]"] + 738["SketchBlockConstraint Radius
[4580, 4602, 4]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 739["SketchBlockConstraint Radius
[4576, 4600, 4]"] + 739["SketchBlockConstraint Radius
[4605, 4629, 4]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] 1 --- 2 1 <--x 19 diff --git a/rust/kcl-lib/tests/kcl_samples/artificial-heart/ops.snap b/rust/kcl-lib/tests/kcl_samples/artificial-heart/ops.snap index 33ad8b9f743..7513fe5f8f1 100644 --- a/rust/kcl-lib/tests/kcl_samples/artificial-heart/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/artificial-heart/ops.snap @@ -10705,22 +10705,61 @@ description: Operations executed artificial-heart.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 0.28, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 1.38, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -16878,22 +16917,61 @@ description: Operations executed artificial-heart.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 0.12, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 0.16, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 3.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -18373,22 +18451,35 @@ description: Operations executed artificial-heart.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -25065,22 +25156,61 @@ description: Operations executed artificial-heart.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 0.0, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 1.16, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 2.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_commands.snap index ea180992d88..517c3ef6249 100644 --- a/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_commands.snap @@ -999,7 +999,7 @@ description: Artifact commands axial-fan.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -0.020000000000253978, + "x": -0.020000000000253988, "y": 5.999966666574135, "z": 0.0 } @@ -1021,7 +1021,7 @@ description: Artifact commands axial-fan.kcl "segment": { "type": "arc", "center": { - "x": -0.00000000000012543438510093097, + "x": -0.00000000000012544479344178683, "y": 0.00000000000001687538997430238 }, "radius": 6.000000000000045, @@ -1031,7 +1031,7 @@ description: Artifact commands axial-fan.kcl }, "end": { "unit": "degrees", - "value": 120.00000000000286 + "value": 120.00000000000293 }, "relative": false } @@ -1044,7 +1044,7 @@ description: Artifact commands axial-fan.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -0.020000000000254273, + "x": -0.020000000000254283, "y": 5.999966666574224, "z": 0.0 } @@ -1077,12 +1077,12 @@ description: Artifact commands axial-fan.kcl "type": "arc", "center": { "x": -0.00000000000012789769243681803, - "y": -0.00000000000006750155989720952 + "y": -0.00000000000006927791673660977 }, "radius": 60.0, "start": { "unit": "degrees", - "value": 5.739138485831794 + "value": 5.739138485831795 }, "end": { "unit": "degrees", @@ -1101,7 +1101,7 @@ description: Artifact commands axial-fan.kcl "segment": { "type": "line", "end": { - "x": 3.5343792230418556, + "x": 3.534379227231865, "y": 11.999966666574428, "z": 0.0 }, @@ -1118,17 +1118,17 @@ description: Artifact commands axial-fan.kcl "segment": { "type": "arc", "center": { - "x": 3.5346422861098485, - "y": 17.99996666109768 + "x": 3.5346422861088356, + "y": 17.999966661097837 }, - "radius": 6.0000000002901, + "radius": 6.000000000290071, "start": { "unit": "degrees", - "value": -90.00251206725764 + "value": -90.00251202723634 }, "end": { "unit": "degrees", - "value": -150.0014306796444 + "value": -150.00143120583013 }, "relative": false } @@ -1143,8 +1143,8 @@ description: Artifact commands axial-fan.kcl "segment": { "type": "line", "end": { - "x": -24.59749479124019, - "y": 54.726257408988936, + "x": -24.59749479124027, + "y": 54.7262574089889, "z": 0.0 }, "relative": false @@ -1160,17 +1160,17 @@ description: Artifact commands axial-fan.kcl "segment": { "type": "arc", "center": { - "x": -0.0000000000003765876499528531, - "y": -0.00000000000012079226507921703 + "x": -0.0000000000003836930773104541, + "y": -0.00000000000013500311979441904 }, - "radius": 59.99999999999999, + "radius": 60.0, "start": { "unit": "degrees", - "value": 114.20221194047181 + "value": 114.20221194047188 }, "end": { "unit": "degrees", - "value": 120.00000000000017 + "value": 120.00000000000028 }, "relative": false } @@ -1185,8 +1185,8 @@ description: Artifact commands axial-fan.kcl "segment": { "type": "line", "end": { - "x": -3.000000000000406, - "y": 5.196152422706539, + "x": -3.0000000000004134, + "y": 5.196152422706535, "z": 0.0 }, "relative": false diff --git a/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_graph_flowchart.snap.md index 25b23bffed1..b8a92d8a7f6 100644 --- a/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_graph_flowchart.snap.md @@ -696,21 +696,21 @@ flowchart LR %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 34 }, ExpressionStatementExpr] 363["SketchBlockConstraint VerticalDistance
[9898, 9945, 1]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 35 }, ExpressionStatementExpr] - 364["SketchBlockConstraint Angle
[9948, 9975, 1]"] + 364["SketchBlockConstraint Angle
[9948, 10043, 1]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 36 }, ExpressionStatementExpr] - 365["SketchBlockConstraint HorizontalDistance
[9978, 10034, 1]"] + 365["SketchBlockConstraint HorizontalDistance
[10046, 10102, 1]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 37 }, ExpressionStatementExpr] - 366["SketchBlockConstraint Coincident
[10037, 10069, 1]"] + 366["SketchBlockConstraint Coincident
[10105, 10137, 1]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 38 }, ExpressionStatementExpr] 367["SketchBlock
[238, 276, 0]"] %% [ProgramBodyItem { index: 0 }] - 368["SketchBlockConstraint Coincident
[10514, 10550, 1]"] + 368["SketchBlockConstraint Coincident
[10582, 10618, 1]"] %% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 369["SketchBlockConstraint Coincident
[10635, 10679, 1]"] + 369["SketchBlockConstraint Coincident
[10703, 10747, 1]"] %% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 370["SketchBlockConstraint Diameter
[10682, 10705, 1]"] + 370["SketchBlockConstraint Diameter
[10750, 10773, 1]"] %% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 371["SketchBlockConstraint Diameter
[10708, 10731, 1]"] + 371["SketchBlockConstraint Diameter
[10776, 10799, 1]"] %% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] 372["SketchBlock
[277, 304, 0]"] %% [ProgramBodyItem { index: 1 }] diff --git a/rust/kcl-lib/tests/kcl_samples/axial-fan/ops.snap b/rust/kcl-lib/tests/kcl_samples/axial-fan/ops.snap index ecfa5d7918f..a9def946256 100644 --- a/rust/kcl-lib/tests/kcl_samples/axial-fan/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/axial-fan/ops.snap @@ -10951,22 +10951,61 @@ description: Operations executed axial-fan.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 7.16, + "ty": { + "mm": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 24.34, + "ty": { + "mm": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 4.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_commands.snap index 9e7606e0330..4aa67e518a2 100644 --- a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_commands.snap @@ -68,8 +68,8 @@ description: Artifact commands cycloidal-gear.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 11.810999999999842, - "y": -7.620000000001257, + "x": 11.810999999999796, + "y": -7.620000000001226, "z": 0.0 } } @@ -90,17 +90,17 @@ description: Artifact commands cycloidal-gear.kcl "segment": { "type": "arc", "center": { - "x": 11.810999999999854, - "y": -0.00000000000027353674880714604 + "x": 11.810999999999844, + "y": -0.00000000000007190914530497138 }, - "radius": 7.620000000000983, + "radius": 7.620000000001154, "start": { "unit": "degrees", - "value": -90.0000000000001 + "value": -90.00000000000037 }, "end": { "unit": "degrees", - "value": 90.00000000000121 + "value": 90.00000000000064 }, "relative": false } @@ -113,8 +113,8 @@ description: Artifact commands cycloidal-gear.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 11.810999999999842, - "y": -7.6200000000023005, + "x": 11.810999999999796, + "y": -7.620000000002378, "z": 0.0 } } @@ -128,17 +128,17 @@ description: Artifact commands cycloidal-gear.kcl "segment": { "type": "arc", "center": { - "x": 11.810999999999776, - "y": -20.345400000002446 + "x": 11.810999999999718, + "y": -20.34540000000259 }, - "radius": 12.725400000000143, + "radius": 12.725400000000214, "start": { "unit": "degrees", - "value": 89.9999999999997 + "value": 89.99999999999966 }, "end": { "unit": "degrees", - "value": 150.00000000000756 + "value": 149.99999999999793 }, "relative": false } @@ -153,17 +153,17 @@ description: Artifact commands cycloidal-gear.kcl "segment": { "type": "arc", "center": { - "x": -5.8086332501562525, - "y": -10.172700000005293 + "x": -5.80863325015498, + "y": -10.172700000003974 }, - "radius": 7.61999999999853, + "radius": 7.619999999998036, "start": { "unit": "degrees", - "value": -29.999999999993683 + "value": -29.999999999992095 }, "end": { "unit": "degrees", - "value": -210.00000000000574 + "value": -210.0000000000157 }, "relative": false } @@ -178,17 +178,17 @@ description: Artifact commands cycloidal-gear.kcl "segment": { "type": "arc", "center": { - "x": -23.428266500323865, - "y": -0.0000000000047361337074391936 + "x": -23.428266500323552, + "y": 0.0000000000004314548718298283 }, - "radius": 12.725400000011874, + "radius": 12.725400000015126, "start": { "unit": "degrees", - "value": -29.999999999972406 + "value": -29.999999999979313 }, "end": { "unit": "degrees", - "value": 29.99999999997451 + "value": 29.999999999966832 }, "relative": false } @@ -203,17 +203,17 @@ description: Artifact commands cycloidal-gear.kcl "segment": { "type": "arc", "center": { - "x": -5.808633250148135, - "y": 10.172700000000992 + "x": -5.808633250144557, + "y": 10.17270000000651 }, - "radius": 7.6200000000081465, + "radius": 7.6200000000079, "start": { "unit": "degrees", - "value": -149.9999999999946 + "value": -149.9999999999918 }, "end": { "unit": "degrees", - "value": -330.0000000000063 + "value": -330.00000000001387 }, "relative": false } @@ -228,17 +228,17 @@ description: Artifact commands cycloidal-gear.kcl "segment": { "type": "arc", "center": { - "x": 11.811000000017302, - "y": 20.34540000000378 + "x": 11.811000000021695, + "y": 20.345400000006517 }, - "radius": 12.72540000000149, + "radius": 12.725400000001054, "start": { "unit": "degrees", - "value": -150.0000000000068 + "value": -150.00000000001495 }, "end": { "unit": "degrees", - "value": -89.99999999999925 + "value": -90.00000000000044 }, "relative": false } diff --git a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_graph_flowchart.snap.md index d2e055671df..727415e60de 100644 --- a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/artifact_graph_flowchart.snap.md @@ -1,54 +1,54 @@ ```mermaid flowchart LR subgraph path2 [Path] - 2["Path
[524, 3642, 0]
Consumed: false"] + 2["Path
[524, 3771, 0]
Consumed: false"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 3["Segment
[2079, 2182, 0]"] + 3["Segment
[2208, 2311, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 4["Segment
[2192, 2303, 0]"] + 4["Segment
[2321, 2432, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 5["Segment
[2313, 2428, 0]"] + 5["Segment
[2442, 2557, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 28 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 6["Segment
[2438, 2548, 0]"] + 6["Segment
[2567, 2677, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 7["Segment
[2558, 2670, 0]"] + 7["Segment
[2687, 2799, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 30 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 8["Segment
[2680, 2788, 0]"] + 8["Segment
[2809, 2917, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path10 [Path] - 10["Path
[3658, 3946, 0]
Consumed: false"] + 10["Path
[3787, 4075, 0]
Consumed: false"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 11["Segment
[3685, 3752, 0]"] + 11["Segment
[3814, 3881, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path12 [Path] - 12["Path Region
[3962, 4024, 0]
Consumed: true"] + 12["Path Region
[4091, 4153, 0]
Consumed: true"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 13["Segment
[3962, 4024, 0]"] + 13["Segment
[4091, 4153, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 14["Segment
[3962, 4024, 0]"] + 14["Segment
[4091, 4153, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 15["Segment
[3962, 4024, 0]"] + 15["Segment
[4091, 4153, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 16["Segment
[3962, 4024, 0]"] + 16["Segment
[4091, 4153, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 17["Segment
[3962, 4024, 0]"] + 17["Segment
[4091, 4153, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 18["Segment
[3962, 4024, 0]"] + 18["Segment
[4091, 4153, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path19 [Path] - 19["Path Region
[4038, 4098, 0]
Consumed: true"] + 19["Path Region
[4167, 4227, 0]
Consumed: true"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 20["Segment
[4038, 4098, 0]"] + 20["Segment
[4167, 4227, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] end - 1["Plane
[524, 3642, 0]"] + 1["Plane
[524, 3771, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 9["Plane
[3658, 3946, 0]"] + 9["Plane
[3787, 4075, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 21["Sweep ExtrusionTwist
[4112, 4215, 0]
Consumed: true"] + 21["Sweep ExtrusionTwist
[4241, 4344, 0]
Consumed: true"] %% [ProgramBodyItem { index: 14 }, VariableDeclarationDeclaration, VariableDeclarationInit] 22[Wall] %% face_code_ref=Missing NodePath @@ -78,7 +78,7 @@ flowchart LR 39["SweepEdge Adjacent"] 40["SweepEdge Opposite"] 41["SweepEdge Adjacent"] - 42["Sweep Extrusion
[4227, 4267, 0]
Consumed: true"] + 42["Sweep Extrusion
[4356, 4396, 0]
Consumed: true"] %% [ProgramBodyItem { index: 15 }, VariableDeclarationDeclaration, VariableDeclarationInit] 43[Wall] %% face_code_ref=Missing NodePath @@ -88,9 +88,9 @@ flowchart LR %% face_code_ref=Missing NodePath 46["SweepEdge Opposite"] 47["SweepEdge Adjacent"] - 48["CompositeSolid Subtract
[4346, 4399, 0]
Consumed: false"] + 48["CompositeSolid Subtract
[4475, 4528, 0]
Consumed: false"] %% [ProgramBodyItem { index: 18 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 49["SketchBlock
[524, 3642, 0]"] + 49["SketchBlock
[524, 3771, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit] 50["SketchBlockConstraint Coincident
[1277, 1313, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] @@ -114,79 +114,79 @@ flowchart LR %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 16 }, ExpressionStatementExpr] 60["SketchBlockConstraint Vertical
[1662, 1678, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 17 }, ExpressionStatementExpr] - 61["SketchBlockConstraint Angle
[1681, 1716, 0]"] + 61["SketchBlockConstraint Angle
[1681, 1781, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 18 }, ExpressionStatementExpr] - 62["SketchBlockConstraint Angle
[1719, 1753, 0]"] + 62["SketchBlockConstraint Angle
[1784, 1882, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 19 }, ExpressionStatementExpr] - 63["SketchBlockConstraint Parallel
[1756, 1782, 0]"] + 63["SketchBlockConstraint Parallel
[1885, 1911, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 20 }, ExpressionStatementExpr] - 64["SketchBlockConstraint Parallel
[1785, 1811, 0]"] + 64["SketchBlockConstraint Parallel
[1914, 1940, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 21 }, ExpressionStatementExpr] - 65["SketchBlockConstraint LinesEqualLength
[1815, 1904, 0]"] + 65["SketchBlockConstraint LinesEqualLength
[1944, 2033, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 22 }, ExpressionStatementExpr] - 66["SketchBlockConstraint Distance
[1907, 1960, 0]"] + 66["SketchBlockConstraint Distance
[2036, 2089, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 23 }, ExpressionStatementExpr] - 67["SketchBlockConstraint HorizontalDistance
[1963, 2020, 0]"] + 67["SketchBlockConstraint HorizontalDistance
[2092, 2149, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 24 }, ExpressionStatementExpr] - 68["SketchBlockConstraint VerticalDistance
[2023, 2068, 0]"] + 68["SketchBlockConstraint VerticalDistance
[2152, 2197, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 25 }, ExpressionStatementExpr] - 69["SketchBlockConstraint Coincident
[2792, 2829, 0]"] + 69["SketchBlockConstraint Coincident
[2921, 2958, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 32 }, ExpressionStatementExpr] - 70["SketchBlockConstraint Coincident
[2832, 2871, 0]"] + 70["SketchBlockConstraint Coincident
[2961, 3000, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 33 }, ExpressionStatementExpr] - 71["SketchBlockConstraint Coincident
[2874, 2911, 0]"] + 71["SketchBlockConstraint Coincident
[3003, 3040, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 34 }, ExpressionStatementExpr] - 72["SketchBlockConstraint Coincident
[2914, 2951, 0]"] + 72["SketchBlockConstraint Coincident
[3043, 3080, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 35 }, ExpressionStatementExpr] - 73["SketchBlockConstraint Coincident
[2954, 2991, 0]"] + 73["SketchBlockConstraint Coincident
[3083, 3120, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 36 }, ExpressionStatementExpr] - 74["SketchBlockConstraint Coincident
[2994, 3031, 0]"] + 74["SketchBlockConstraint Coincident
[3123, 3160, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 37 }, ExpressionStatementExpr] - 75["SketchBlockConstraint Radius
[3035, 3062, 0]"] + 75["SketchBlockConstraint Radius
[3164, 3191, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 38 }, ExpressionStatementExpr] - 76["SketchBlockConstraint Radius
[3065, 3092, 0]"] + 76["SketchBlockConstraint Radius
[3194, 3221, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 39 }, ExpressionStatementExpr] - 77["SketchBlockConstraint Radius
[3095, 3122, 0]"] + 77["SketchBlockConstraint Radius
[3224, 3251, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 40 }, ExpressionStatementExpr] - 78["SketchBlockConstraint Radius
[3125, 3152, 0]"] + 78["SketchBlockConstraint Radius
[3254, 3281, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 41 }, ExpressionStatementExpr] - 79["SketchBlockConstraint Radius
[3155, 3182, 0]"] + 79["SketchBlockConstraint Radius
[3284, 3311, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 42 }, ExpressionStatementExpr] - 80["SketchBlockConstraint Radius
[3185, 3212, 0]"] + 80["SketchBlockConstraint Radius
[3314, 3341, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 43 }, ExpressionStatementExpr] - 81["SketchBlockConstraint Coincident
[3216, 3252, 0]"] + 81["SketchBlockConstraint Coincident
[3345, 3381, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 44 }, ExpressionStatementExpr] - 82["SketchBlockConstraint Coincident
[3255, 3287, 0]"] + 82["SketchBlockConstraint Coincident
[3384, 3416, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 45 }, ExpressionStatementExpr] - 83["SketchBlockConstraint Coincident
[3290, 3326, 0]"] + 83["SketchBlockConstraint Coincident
[3419, 3455, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 46 }, ExpressionStatementExpr] - 84["SketchBlockConstraint Coincident
[3329, 3361, 0]"] + 84["SketchBlockConstraint Coincident
[3458, 3490, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 47 }, ExpressionStatementExpr] - 85["SketchBlockConstraint Coincident
[3364, 3400, 0]"] + 85["SketchBlockConstraint Coincident
[3493, 3529, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 48 }, ExpressionStatementExpr] - 86["SketchBlockConstraint Coincident
[3403, 3435, 0]"] + 86["SketchBlockConstraint Coincident
[3532, 3564, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 49 }, ExpressionStatementExpr] - 87["SketchBlockConstraint Coincident
[3439, 3471, 0]"] + 87["SketchBlockConstraint Coincident
[3568, 3600, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 50 }, ExpressionStatementExpr] - 88["SketchBlockConstraint Coincident
[3474, 3504, 0]"] + 88["SketchBlockConstraint Coincident
[3603, 3633, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 51 }, ExpressionStatementExpr] - 89["SketchBlockConstraint Coincident
[3507, 3539, 0]"] + 89["SketchBlockConstraint Coincident
[3636, 3668, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 52 }, ExpressionStatementExpr] - 90["SketchBlockConstraint Coincident
[3542, 3572, 0]"] + 90["SketchBlockConstraint Coincident
[3671, 3701, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 53 }, ExpressionStatementExpr] - 91["SketchBlockConstraint Coincident
[3575, 3607, 0]"] + 91["SketchBlockConstraint Coincident
[3704, 3736, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 54 }, ExpressionStatementExpr] - 92["SketchBlockConstraint Coincident
[3610, 3640, 0]"] + 92["SketchBlockConstraint Coincident
[3739, 3769, 0]"] %% [ProgramBodyItem { index: 10 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 55 }, ExpressionStatementExpr] - 93["SketchBlock
[3658, 3946, 0]"] + 93["SketchBlock
[3787, 4075, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 94["SketchBlockConstraint Coincident
[3755, 3788, 0]"] + 94["SketchBlockConstraint Coincident
[3884, 3917, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 95["SketchBlockConstraint Radius
[3791, 3823, 0]"] + 95["SketchBlockConstraint Radius
[3920, 3952, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, ExpressionStatementExpr] - 96["SketchBlockConstraint HorizontalDistance
[3826, 3891, 0]"] + 96["SketchBlockConstraint HorizontalDistance
[3955, 4020, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 97["SketchBlockConstraint VerticalDistance
[3894, 3944, 0]"] + 97["SketchBlockConstraint VerticalDistance
[4023, 4073, 0]"] %% [ProgramBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] 1 --- 2 1 <--x 12 diff --git a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap index e59ea85880f..bc7fe8ab4ff 100644 --- a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ast.snap @@ -3095,7 +3095,154 @@ description: Result of parsing cycloidal-gear.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "baseline", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "c2ToC3", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "3", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 3.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1.23in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.23, + "suffix": "Inch" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "-", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + }, + { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0.83in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.83, + "suffix": "Inch" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "-", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -3105,7 +3252,7 @@ description: Result of parsing cycloidal-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -3119,52 +3266,7 @@ description: Result of parsing cycloidal-gear.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "baseline", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "c2ToC3", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", @@ -3197,7 +3299,145 @@ description: Result of parsing cycloidal-gear.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "baseline", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "c4ToC5", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0.22in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.22, + "suffix": "Inch" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "-", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + }, + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0.19in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.19, + "suffix": "Inch" + } + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -3207,7 +3447,7 @@ description: Result of parsing cycloidal-gear.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -3221,52 +3461,7 @@ description: Result of parsing cycloidal-gear.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "baseline", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "c4ToC5", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", diff --git a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ops.snap b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ops.snap index a7b31faaf78..96a878564b3 100644 --- a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/ops.snap @@ -1459,22 +1459,61 @@ description: Operations executed cycloidal-gear.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": -1.23, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": -0.83, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 3.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -1506,22 +1545,61 @@ description: Operations executed cycloidal-gear.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": -0.22, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 0.19, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/program_memory.snap b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/program_memory.snap index ddb10434c9f..cfc6d86ffb5 100644 --- a/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/program_memory.snap +++ b/rust/kcl-lib/tests/kcl_samples/cycloidal-gear/program_memory.snap @@ -254,10 +254,10 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "radius": 0.1485000000005, "tag": { - "commentStart": 3678, - "end": 3682, + "commentStart": 3807, + "end": 3811, "moduleId": 0, - "start": 3678, + "start": 3807, "type": "TagDeclarator", "value": "hole" }, @@ -356,10 +356,10 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "radius": 0.1485000000005, "tag": { - "commentStart": 3678, - "end": 3682, + "commentStart": 3807, + "end": 3811, "moduleId": 0, - "start": 3678, + "start": 3807, "type": "TagDeclarator", "value": "hole" }, @@ -460,10 +460,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, @@ -474,10 +474,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, @@ -488,10 +488,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, @@ -502,10 +502,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, @@ -516,10 +516,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, @@ -530,10 +530,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, @@ -552,25 +552,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999943, - -0.000000000000010769163338864018 + 0.46499999999999386, + -0.000000000000002831068712794149 ], "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], - "radius": 0.30000000000003874, + "radius": 0.30000000000004545, "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, "to": [ - 0.464999999999988, - 0.30000000000002797 + 0.46499999999999053, + 0.3000000000000426 ], "type": "Arc", "units": "in" @@ -582,25 +582,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999912, - -0.8010000000000963 + 0.4649999999999889, + -0.8010000000001021 ], "from": [ - 0.4649999999999938, - -0.3000000000000906 + 0.464999999999992, + -0.30000000000009364 ], - "radius": 0.5010000000000057, + "radius": 0.5010000000000084, "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, "to": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], "type": "Arc", "units": "in" @@ -612,25 +612,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843134855, - -0.40050000000020836 + -0.22868634843129843, + -0.4005000000001565 ], "from": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], - "radius": 0.29999999999994215, + "radius": 0.2999999999999227, "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, "to": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], "type": "Arc", "units": "in" @@ -642,25 +642,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - -0.9223726968631443, - -0.00000000000018646195698579504 + -0.9223726968631321, + 0.000000000000016986412276764895 ], "from": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], - "radius": 0.5010000000004675, + "radius": 0.5010000000005955, "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, "to": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], "type": "Arc", "units": "in" @@ -672,25 +672,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843102892, - 0.4005000000000391 + -0.2286863484308881, + 0.4005000000002563 ], "from": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], - "radius": 0.30000000000032073, + "radius": 0.300000000000311, "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, "to": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], "type": "Arc", "units": "in" @@ -702,25 +702,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4650000000006812, - 0.8010000000001489 + 0.4650000000008542, + 0.8010000000002566 ], "from": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], - "radius": 0.5010000000000587, + "radius": 0.5010000000000415, "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, "to": [ - 0.4650000000006878, - 0.3000000000000902 + 0.4650000000008503, + 0.3000000000002151 ], "type": "Arc", "units": "in" @@ -759,12 +759,12 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "start": { "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "to": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "units": "in", "tag": null, @@ -822,10 +822,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3678, - "end": 3682, + "commentStart": 3807, + "end": 3811, "moduleId": 0, - "start": 3678, + "start": 3807, "type": "TagDeclarator", "value": "hole" }, @@ -853,10 +853,10 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "radius": 0.1485000000005, "tag": { - "commentStart": 3678, - "end": 3682, + "commentStart": 3807, + "end": 3811, "moduleId": 0, - "start": 3678, + "start": 3807, "type": "TagDeclarator", "value": "hole" }, @@ -953,10 +953,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, @@ -967,10 +967,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, @@ -981,10 +981,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, @@ -995,10 +995,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, @@ -1009,10 +1009,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, @@ -1023,10 +1023,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, @@ -1045,25 +1045,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999943, - -0.000000000000010769163338864018 + 0.46499999999999386, + -0.000000000000002831068712794149 ], "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], - "radius": 0.30000000000003874, + "radius": 0.30000000000004545, "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, "to": [ - 0.464999999999988, - 0.30000000000002797 + 0.46499999999999053, + 0.3000000000000426 ], "type": "Arc", "units": "in" @@ -1075,25 +1075,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999912, - -0.8010000000000963 + 0.4649999999999889, + -0.8010000000001021 ], "from": [ - 0.4649999999999938, - -0.3000000000000906 + 0.464999999999992, + -0.30000000000009364 ], - "radius": 0.5010000000000057, + "radius": 0.5010000000000084, "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, "to": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], "type": "Arc", "units": "in" @@ -1105,25 +1105,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843134855, - -0.40050000000020836 + -0.22868634843129843, + -0.4005000000001565 ], "from": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], - "radius": 0.29999999999994215, + "radius": 0.2999999999999227, "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, "to": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], "type": "Arc", "units": "in" @@ -1135,25 +1135,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - -0.9223726968631443, - -0.00000000000018646195698579504 + -0.9223726968631321, + 0.000000000000016986412276764895 ], "from": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], - "radius": 0.5010000000004675, + "radius": 0.5010000000005955, "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, "to": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], "type": "Arc", "units": "in" @@ -1165,25 +1165,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843102892, - 0.4005000000000391 + -0.2286863484308881, + 0.4005000000002563 ], "from": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], - "radius": 0.30000000000032073, + "radius": 0.300000000000311, "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, "to": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], "type": "Arc", "units": "in" @@ -1195,25 +1195,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4650000000006812, - 0.8010000000001489 + 0.4650000000008542, + 0.8010000000002566 ], "from": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], - "radius": 0.5010000000000587, + "radius": 0.5010000000000415, "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, "to": [ - 0.4650000000006878, - 0.3000000000000902 + 0.4650000000008503, + 0.3000000000002151 ], "type": "Arc", "units": "in" @@ -1252,12 +1252,12 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "start": { "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "to": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "units": "in", "tag": null, @@ -1333,10 +1333,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, @@ -1347,10 +1347,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, @@ -1361,10 +1361,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, @@ -1375,10 +1375,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, @@ -1389,10 +1389,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, @@ -1403,10 +1403,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, @@ -1425,25 +1425,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999943, - -0.000000000000010769163338864018 + 0.46499999999999386, + -0.000000000000002831068712794149 ], "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], - "radius": 0.30000000000003874, + "radius": 0.30000000000004545, "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, "to": [ - 0.464999999999988, - 0.30000000000002797 + 0.46499999999999053, + 0.3000000000000426 ], "type": "Arc", "units": "in" @@ -1455,25 +1455,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999912, - -0.8010000000000963 + 0.4649999999999889, + -0.8010000000001021 ], "from": [ - 0.4649999999999938, - -0.3000000000000906 + 0.464999999999992, + -0.30000000000009364 ], - "radius": 0.5010000000000057, + "radius": 0.5010000000000084, "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, "to": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], "type": "Arc", "units": "in" @@ -1485,25 +1485,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843134855, - -0.40050000000020836 + -0.22868634843129843, + -0.4005000000001565 ], "from": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], - "radius": 0.29999999999994215, + "radius": 0.2999999999999227, "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, "to": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], "type": "Arc", "units": "in" @@ -1515,25 +1515,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - -0.9223726968631443, - -0.00000000000018646195698579504 + -0.9223726968631321, + 0.000000000000016986412276764895 ], "from": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], - "radius": 0.5010000000004675, + "radius": 0.5010000000005955, "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, "to": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], "type": "Arc", "units": "in" @@ -1545,25 +1545,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843102892, - 0.4005000000000391 + -0.2286863484308881, + 0.4005000000002563 ], "from": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], - "radius": 0.30000000000032073, + "radius": 0.300000000000311, "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, "to": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], "type": "Arc", "units": "in" @@ -1575,25 +1575,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4650000000006812, - 0.8010000000001489 + 0.4650000000008542, + 0.8010000000002566 ], "from": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], - "radius": 0.5010000000000587, + "radius": 0.5010000000000415, "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, "to": [ - 0.4650000000006878, - 0.3000000000000902 + 0.4650000000008503, + 0.3000000000002151 ], "type": "Arc", "units": "in" @@ -1632,12 +1632,12 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "start": { "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "to": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "units": "in", "tag": null, @@ -1695,10 +1695,10 @@ description: Variables in memory after executing cycloidal-gear.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3678, - "end": 3682, + "commentStart": 3807, + "end": 3811, "moduleId": 0, - "start": 3678, + "start": 3807, "type": "TagDeclarator", "value": "hole" }, @@ -1726,10 +1726,10 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "radius": 0.1485000000005, "tag": { - "commentStart": 3678, - "end": 3682, + "commentStart": 3807, + "end": 3811, "moduleId": 0, - "start": 3678, + "start": 3807, "type": "TagDeclarator", "value": "hole" }, @@ -1852,7 +1852,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "arc": { "start": [ { - "n": 0.4649999999999938, + "n": 0.464999999999992, "ty": { "in": null, "type": "Known", @@ -1860,7 +1860,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.3000000000000495, + "n": -0.3000000000000483, "ty": { "in": null, "type": "Known", @@ -1870,7 +1870,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.4649999999999879, + "n": 0.46499999999999053, "ty": { "in": null, "type": "Known", @@ -1878,7 +1878,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.30000000000002186, + "n": 0.3000000000000459, "ty": { "in": null, "type": "Known", @@ -1888,7 +1888,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "center": [ { - "n": 0.46499999999999425, + "n": 0.4649999999999938, "ty": { "in": null, "type": "Known", @@ -1896,7 +1896,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.000000000000010767117473261786, + "n": -0.000000000000002818443137467397, "ty": { "in": null, "type": "Known", @@ -2004,7 +2004,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "arc": { "start": [ { - "n": 0.4649999999999938, + "n": 0.464999999999992, "ty": { "in": null, "type": "Known", @@ -2012,7 +2012,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.3000000000000906, + "n": -0.30000000000009364, "ty": { "in": null, "type": "Known", @@ -2022,7 +2022,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.031121272703900096, + "n": 0.03112127270390623, "ty": { "in": null, "type": "Known", @@ -2030,7 +2030,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.5505000000001221, + "n": -0.5505000000000354, "ty": { "in": null, "type": "Known", @@ -2040,7 +2040,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "center": [ { - "n": 0.4649999999999911, + "n": 0.464999999999989, "ty": { "in": null, "type": "Known", @@ -2048,7 +2048,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.8010000000000962, + "n": -0.8010000000001021, "ty": { "in": null, "type": "Known", @@ -2156,7 +2156,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "arc": { "start": [ { - "n": -0.48849396956697033, + "n": -0.48849396956691843, "ty": { "in": null, "type": "Known", @@ -2164,7 +2164,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.2505000000000061, + "n": -0.2504999999998955, "ty": { "in": null, "type": "Known", @@ -2174,7 +2174,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.031121272703898185, + "n": 0.031121272703905623, "ty": { "in": null, "type": "Known", @@ -2182,7 +2182,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.5505000000001211, + "n": -0.5505000000000354, "ty": { "in": null, "type": "Known", @@ -2192,7 +2192,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "center": [ { - "n": -0.22868634843139987, + "n": -0.2286863484313797, "ty": { "in": null, "type": "Known", @@ -2200,7 +2200,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.4005000000001787, + "n": -0.4005000000001099, "ty": { "in": null, "type": "Known", @@ -2308,7 +2308,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "arc": { "start": [ { - "n": -0.4884939695668806, + "n": -0.48849396956681523, "ty": { "in": null, "type": "Known", @@ -2316,7 +2316,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.2505000000000575, + "n": -0.2504999999999548, "ty": { "in": null, "type": "Known", @@ -2326,7 +2326,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": -0.4884939695669074, + "n": -0.4884939695669141, "ty": { "in": null, "type": "Known", @@ -2334,7 +2334,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.2504999999999979, + "n": 0.2505000000001443, "ty": { "in": null, "type": "Known", @@ -2344,7 +2344,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "center": [ { - "n": -0.92237269686341, + "n": -0.9223726968634252, "ty": { "in": null, "type": "Known", @@ -2352,7 +2352,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.0000000000000327210437399788, + "n": 0.00000000000018626856072921204, "ty": { "in": null, "type": "Known", @@ -2460,7 +2460,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "arc": { "start": [ { - "n": 0.03112127270389349, + "n": 0.031121272703894285, "ty": { "in": null, "type": "Known", @@ -2468,7 +2468,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.5505000000000714, + "n": 0.5505000000001935, "ty": { "in": null, "type": "Known", @@ -2478,7 +2478,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": -0.4884939695669993, + "n": -0.4884939695670053, "ty": { "in": null, "type": "Known", @@ -2486,7 +2486,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.2504999999999444, + "n": 0.25050000000009104, "ty": { "in": null, "type": "Known", @@ -2496,7 +2496,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "center": [ { - "n": -0.22868634843140415, + "n": -0.2286863484314259, "ty": { "in": null, "type": "Known", @@ -2504,7 +2504,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.40050000000012925, + "n": 0.40050000000028385, "ty": { "in": null, "type": "Known", @@ -2612,7 +2612,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "arc": { "start": [ { - "n": 0.031121272703896915, + "n": 0.031121272703889386, "ty": { "in": null, "type": "Known", @@ -2620,7 +2620,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.5505000000000735, + "n": 0.5505000000001907, "ty": { "in": null, "type": "Known", @@ -2630,7 +2630,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.4649999999999879, + "n": 0.4649999999999906, "ty": { "in": null, "type": "Known", @@ -2638,7 +2638,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.30000000000005217, + "n": 0.3000000000000912, "ty": { "in": null, "type": "Known", @@ -2648,7 +2648,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "center": [ { - "n": 0.46499999999998126, + "n": 0.4649999999999943, "ty": { "in": null, "type": "Known", @@ -2656,7 +2656,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.8010000000000513, + "n": 0.8010000000000984, "ty": { "in": null, "type": "Known", @@ -2764,7 +2764,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": 0.00000000000000000002679944086662229, + "n": 0.000000000000000000016094214475445227, "ty": { "in": null, "type": "Known", @@ -2772,7 +2772,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.000000000000000021300329064470077, + "n": 0.00000000000000037151061170417334, "ty": { "in": null, "type": "Known", @@ -2782,7 +2782,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.3000000000000007, + "n": 0.30000000000004967, "ty": { "in": null, "type": "Known", @@ -2790,7 +2790,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.000000000000008843445441018048, + "n": 0.000000000000012164791626907229, "ty": { "in": null, "type": "Known", @@ -2885,7 +2885,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": 0.46499999999998964, + "n": 0.4649999999999918, "ty": { "in": null, "type": "Known", @@ -2893,7 +2893,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.000000000000027272788801061538, + "n": -0.0000000000000033547617150677014, "ty": { "in": null, "type": "Known", @@ -2903,7 +2903,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.46499999999998504, + "n": 0.46499999999998987, "ty": { "in": null, "type": "Known", @@ -2911,7 +2911,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.8010000000000838, + "n": 0.8010000000001412, "ty": { "in": null, "type": "Known", @@ -3006,7 +3006,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": 0.46499999999999314, + "n": 0.46499999999998964, "ty": { "in": null, "type": "Known", @@ -3014,7 +3014,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.8010000000001384, + "n": -0.8010000000001478, "ty": { "in": null, "type": "Known", @@ -3024,7 +3024,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.46499999999999425, + "n": 0.4649999999999938, "ty": { "in": null, "type": "Known", @@ -3032,7 +3032,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.00000000000000003130802694811911, + "n": -0.0000000000000027414643766875046, "ty": { "in": null, "type": "Known", @@ -3127,7 +3127,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": 0.4649999999999941, + "n": 0.4649999999999861, "ty": { "in": null, "type": "Known", @@ -3135,7 +3135,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.8010000000001426, + "n": -0.8010000000001956, "ty": { "in": null, "type": "Known", @@ -3145,7 +3145,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": -0.22868634843149033, + "n": -0.2286863484314824, "ty": { "in": null, "type": "Known", @@ -3153,7 +3153,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.4005000000001264, + "n": -0.4005000000000503, "ty": { "in": null, "type": "Known", @@ -3248,7 +3248,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": -0.22868634843157953, + "n": -0.2286863484315888, "ty": { "in": null, "type": "Known", @@ -3256,7 +3256,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.40050000000007807, + "n": -0.4005000000000391, "ty": { "in": null, "type": "Known", @@ -3266,7 +3266,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": -0.9223726968632266, + "n": -0.9223726968632286, "ty": { "in": null, "type": "Known", @@ -3274,7 +3274,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": -0.00000000000003121794871254424, + "n": 0.00000000000017993157706677187, "ty": { "in": null, "type": "Known", @@ -3369,7 +3369,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": -0.9223726968631321, + "n": -0.9223726968631377, "ty": { "in": null, "type": "Known", @@ -3377,7 +3377,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.000000000000017954329274660603, + "n": 0.00000000000018480668917073763, "ty": { "in": null, "type": "Known", @@ -3387,7 +3387,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": -0.22868634843149882, + "n": -0.22868634843151125, "ty": { "in": null, "type": "Known", @@ -3395,7 +3395,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.40050000000007446, + "n": 0.40050000000023467, "ty": { "in": null, "type": "Known", @@ -3490,7 +3490,7 @@ description: Variables in memory after executing cycloidal-gear.kcl "line": { "start": [ { - "n": -0.2286863484314984, + "n": -0.22868634843150543, "ty": { "in": null, "type": "Known", @@ -3498,7 +3498,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.4005000000000696, + "n": 0.4005000000001922, "ty": { "in": null, "type": "Known", @@ -3508,7 +3508,7 @@ description: Variables in memory after executing cycloidal-gear.kcl ], "end": [ { - "n": 0.46499999999998426, + "n": 0.4649999999999836, "ty": { "in": null, "type": "Known", @@ -3516,7 +3516,7 @@ description: Variables in memory after executing cycloidal-gear.kcl } }, { - "n": 0.801000000000089, + "n": 0.8010000000001835, "ty": { "in": null, "type": "Known", @@ -3615,25 +3615,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999943, - -0.000000000000010769163338864018 + 0.46499999999999386, + -0.000000000000002831068712794149 ], "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], - "radius": 0.30000000000003874, + "radius": 0.30000000000004545, "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, "to": [ - 0.464999999999988, - 0.30000000000002797 + 0.46499999999999053, + 0.3000000000000426 ], "type": "Arc", "units": "in" @@ -3644,13 +3644,13 @@ description: Variables in memory after executing cycloidal-gear.kcl "sourceRange": [] }, "from": [ - 0.464999999999988, - 0.30000000000002797 + 0.46499999999999053, + 0.3000000000000426 ], "tag": null, "to": [ - 0.4649999999999938, - -0.3000000000000906 + 0.464999999999992, + -0.30000000000009364 ], "type": "ToPoint", "units": "in" @@ -3662,25 +3662,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999912, - -0.8010000000000963 + 0.4649999999999889, + -0.8010000000001021 ], "from": [ - 0.4649999999999938, - -0.3000000000000906 + 0.464999999999992, + -0.30000000000009364 ], - "radius": 0.5010000000000057, + "radius": 0.5010000000000084, "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, "to": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], "type": "Arc", "units": "in" @@ -3692,25 +3692,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843134855, - -0.40050000000020836 + -0.22868634843129843, + -0.4005000000001565 ], "from": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], - "radius": 0.29999999999994215, + "radius": 0.2999999999999227, "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, "to": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], "type": "Arc", "units": "in" @@ -3722,25 +3722,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - -0.9223726968631443, - -0.00000000000018646195698579504 + -0.9223726968631321, + 0.000000000000016986412276764895 ], "from": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], - "radius": 0.5010000000004675, + "radius": 0.5010000000005955, "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, "to": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], "type": "Arc", "units": "in" @@ -3752,25 +3752,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843102892, - 0.4005000000000391 + -0.2286863484308881, + 0.4005000000002563 ], "from": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], - "radius": 0.30000000000032073, + "radius": 0.300000000000311, "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, "to": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], "type": "Arc", "units": "in" @@ -3782,25 +3782,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4650000000006812, - 0.8010000000001489 + 0.4650000000008542, + 0.8010000000002566 ], "from": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], - "radius": 0.5010000000000587, + "radius": 0.5010000000000415, "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, "to": [ - 0.4650000000006878, - 0.3000000000000902 + 0.4650000000008503, + 0.3000000000002151 ], "type": "Arc", "units": "in" @@ -3839,12 +3839,12 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "start": { "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "to": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "units": "in", "tag": null, @@ -3904,25 +3904,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999943, - -0.000000000000010769163338864018 + 0.46499999999999386, + -0.000000000000002831068712794149 ], "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], - "radius": 0.30000000000003874, + "radius": 0.30000000000004545, "tag": { - "commentStart": 2072, - "end": 2076, + "commentStart": 2201, + "end": 2205, "moduleId": 0, - "start": 2072, + "start": 2201, "type": "TagDeclarator", "value": "arc1" }, "to": [ - 0.464999999999988, - 0.30000000000002797 + 0.46499999999999053, + 0.3000000000000426 ], "type": "Arc", "units": "in" @@ -3934,25 +3934,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4649999999999912, - -0.8010000000000963 + 0.4649999999999889, + -0.8010000000001021 ], "from": [ - 0.4649999999999938, - -0.3000000000000906 + 0.464999999999992, + -0.30000000000009364 ], - "radius": 0.5010000000000057, + "radius": 0.5010000000000084, "tag": { - "commentStart": 2185, - "end": 2189, + "commentStart": 2314, + "end": 2318, "moduleId": 0, - "start": 2185, + "start": 2314, "type": "TagDeclarator", "value": "arc2" }, "to": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], "type": "Arc", "units": "in" @@ -3964,25 +3964,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843134855, - -0.40050000000020836 + -0.22868634843129843, + -0.4005000000001565 ], "from": [ - 0.031121272703949487, - -0.5505000000001508 + 0.031121272703986957, + -0.550500000000082 ], - "radius": 0.29999999999994215, + "radius": 0.2999999999999227, "tag": { - "commentStart": 2306, - "end": 2310, + "commentStart": 2435, + "end": 2439, "moduleId": 0, - "start": 2306, + "start": 2435, "type": "TagDeclarator", "value": "arc3" }, "to": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], "type": "Arc", "units": "in" @@ -3994,25 +3994,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - -0.9223726968631443, - -0.00000000000018646195698579504 + -0.9223726968631321, + 0.000000000000016986412276764895 ], "from": [ - -0.48849396956661506, - -0.2505000000002113 + -0.488493969566522, + -0.25050000000012407 ], - "radius": 0.5010000000004675, + "radius": 0.5010000000005955, "tag": { - "commentStart": 2431, - "end": 2435, + "commentStart": 2560, + "end": 2564, "moduleId": 0, - "start": 2431, + "start": 2560, "type": "TagDeclarator", "value": "arc4" }, "to": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], "type": "Arc", "units": "in" @@ -4024,25 +4024,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": false, "center": [ - -0.22868634843102892, - 0.4005000000000391 + -0.2286863484308881, + 0.4005000000002563 ], "from": [ - -0.48849396956662416, - 0.2504999999998543 + -0.4884939695664675, + 0.25050000000006356 ], - "radius": 0.30000000000032073, + "radius": 0.300000000000311, "tag": { - "commentStart": 2551, - "end": 2555, + "commentStart": 2680, + "end": 2684, "moduleId": 0, - "start": 2551, + "start": 2680, "type": "TagDeclarator", "value": "arc5" }, "to": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], "type": "Arc", "units": "in" @@ -4054,25 +4054,25 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "ccw": true, "center": [ - 0.4650000000006812, - 0.8010000000001489 + 0.4650000000008542, + 0.8010000000002566 ], "from": [ - 0.03112127270459686, - 0.550500000000171 + 0.031121272704749126, + 0.5505000000003489 ], - "radius": 0.5010000000000587, + "radius": 0.5010000000000415, "tag": { - "commentStart": 2673, - "end": 2677, + "commentStart": 2802, + "end": 2806, "moduleId": 0, - "start": 2673, + "start": 2802, "type": "TagDeclarator", "value": "arc6" }, "to": [ - 0.4650000000006878, - 0.3000000000000902 + 0.4650000000008503, + 0.3000000000002151 ], "type": "Arc", "units": "in" @@ -4111,12 +4111,12 @@ description: Variables in memory after executing cycloidal-gear.kcl }, "start": { "from": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "to": [ - 0.4649999999999938, - -0.3000000000000495 + 0.464999999999992, + -0.3000000000000483 ], "units": "in", "tag": null, diff --git a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_commands.snap index 1abe08a3c1c..91ff5f06e23 100644 --- a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_commands.snap @@ -68,8 +68,8 @@ description: Artifact commands field-monitor-stand.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -60.00000000000002, - "y": -0.00000000000002497146472962705, + "x": -60.00000000000003, + "y": -0.000000000000024627188716874425, "z": 0.0 } } @@ -90,8 +90,8 @@ description: Artifact commands field-monitor-stand.kcl "segment": { "type": "line", "end": { - "x": -0.0000000000000238752171250505, - "y": -0.000000000000004292440421957927, + "x": -0.000000000000023746877142839638, + "y": -0.0000000000000042394081032752924, "z": 0.0 }, "relative": false @@ -107,7 +107,7 @@ description: Artifact commands field-monitor-stand.kcl "segment": { "type": "line", "end": { - "x": -41.384437342405995, + "x": -41.38443734240601, "y": 113.70280711509488, "z": 0.0 }, @@ -124,7 +124,7 @@ description: Artifact commands field-monitor-stand.kcl "segment": { "type": "line", "end": { - "x": -44.203515204763775, + "x": -44.20351520476378, "y": 112.67674668511785, "z": 0.0 }, @@ -141,8 +141,8 @@ description: Artifact commands field-monitor-stand.kcl "segment": { "type": "line", "end": { - "x": -4.28444402022648, - "y": 2.999999999999998, + "x": -4.284444020226475, + "y": 2.9999999999999987, "z": 0.0 }, "relative": false @@ -158,8 +158,8 @@ description: Artifact commands field-monitor-stand.kcl "segment": { "type": "line", "end": { - "x": -60.00000000000002, - "y": 2.9999999999999885, + "x": -60.00000000000003, + "y": 2.9999999999999893, "z": 0.0 }, "relative": false @@ -175,8 +175,8 @@ description: Artifact commands field-monitor-stand.kcl "segment": { "type": "line", "end": { - "x": -60.00000000000002, - "y": -0.000000000000020375276633059364, + "x": -60.00000000000003, + "y": -0.00000000000002003277505613585, "z": 0.0 }, "relative": false diff --git a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_graph_flowchart.snap.md index 57e14d2227f..3d504ba8e1f 100644 --- a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/artifact_graph_flowchart.snap.md @@ -1,7 +1,7 @@ ```mermaid flowchart LR subgraph path2 [Path] - 2["Path
[943, 2053, 0]
Consumed: false"] + 2["Path
[943, 2116, 0]
Consumed: false"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit] 3["Segment
[971, 1031, 0]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit] @@ -17,56 +17,56 @@ flowchart LR %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path9 [Path] - 9["Path Region
[2068, 2125, 0]
Consumed: true"] + 9["Path Region
[2131, 2188, 0]
Consumed: true"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 10["Segment
[2068, 2125, 0]"] + 10["Segment
[2131, 2188, 0]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 11["Segment
[2068, 2125, 0]"] + 11["Segment
[2131, 2188, 0]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 12["Segment
[2068, 2125, 0]"] + 12["Segment
[2131, 2188, 0]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 13["Segment
[2068, 2125, 0]"] + 13["Segment
[2131, 2188, 0]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 14["Segment
[2068, 2125, 0]"] + 14["Segment
[2131, 2188, 0]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 15["Segment
[2068, 2125, 0]"] + 15["Segment
[2131, 2188, 0]"] %% [ProgramBodyItem { index: 23 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path38 [Path] - 38["Path
[2363, 3001, 0]
Consumed: false"] + 38["Path
[2426, 3064, 0]
Consumed: false"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 39["Segment
[2391, 2458, 0]"] + 39["Segment
[2454, 2521, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 40["Segment
[2469, 2541, 0]"] + 40["Segment
[2532, 2604, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 41["Segment
[2591, 2662, 0]"] + 41["Segment
[2654, 2725, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path42 [Path] - 42["Path Region
[3018, 3085, 0]
Consumed: true"] + 42["Path Region
[3081, 3148, 0]
Consumed: true"] %% [ProgramBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 43["Segment
[3018, 3085, 0]"] + 43["Segment
[3081, 3148, 0]"] %% [ProgramBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 44["Segment
[3018, 3085, 0]"] + 44["Segment
[3081, 3148, 0]"] %% [ProgramBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 45["Segment
[3018, 3085, 0]"] + 45["Segment
[3081, 3148, 0]"] %% [ProgramBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path59 [Path] - 59["Path
[3423, 3788, 0]
Consumed: false"] + 59["Path
[3486, 3851, 0]
Consumed: false"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 60["Segment
[3463, 3538, 0]"] + 60["Segment
[3526, 3601, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path61 [Path] - 61["Path Region
[3839, 3876, 0]
Consumed: true"] + 61["Path Region
[3902, 3939, 0]
Consumed: true"] %% [ProgramBodyItem { index: 32 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 62["Segment
[3839, 3876, 0]"] + 62["Segment
[3902, 3939, 0]"] %% [ProgramBodyItem { index: 32 }, VariableDeclarationDeclaration, VariableDeclarationInit] end - 1["Plane
[943, 2053, 0]"] + 1["Plane
[943, 2116, 0]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 16["Sweep Extrusion
[2183, 2280, 0]
Consumed: true"] + 16["Sweep Extrusion
[2246, 2343, 0]
Consumed: true"] %% [ProgramBodyItem { index: 24 }, VariableDeclarationDeclaration, VariableDeclarationInit] 17[Wall] %% face_code_ref=Missing NodePath @@ -96,9 +96,9 @@ flowchart LR 34["SweepEdge Adjacent"] 35["SweepEdge Opposite"] 36["SweepEdge Adjacent"] - 37["Plane
[2363, 3001, 0]"] + 37["Plane
[2426, 3064, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 46["Sweep Extrusion
[3138, 3181, 0]
Consumed: false"] + 46["Sweep Extrusion
[3201, 3244, 0]
Consumed: false"] %% [ProgramBodyItem { index: 28 }, VariableDeclarationDeclaration, VariableDeclarationInit] 47[Wall] %% face_code_ref=Missing NodePath @@ -116,9 +116,9 @@ flowchart LR 55["SweepEdge Adjacent"] 56["SweepEdge Opposite"] 57["SweepEdge Adjacent"] - 58["Plane
[3423, 3788, 0]"] + 58["Plane
[3486, 3851, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 63["Sweep Extrusion
[3890, 3933, 0]
Consumed: true"] + 63["Sweep Extrusion
[3953, 3996, 0]
Consumed: true"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit] 64[Wall] %% face_code_ref=Missing NodePath @@ -128,17 +128,17 @@ flowchart LR %% face_code_ref=Missing NodePath 67["SweepEdge Opposite"] 68["SweepEdge Adjacent"] - 69["Pattern Transform
[4004, 4112, 0]
Copies: 1
Faces: 3
Edges: 3"] + 69["Pattern Transform
[4067, 4175, 0]
Copies: 1
Faces: 3
Edges: 3"] %% [ProgramBodyItem { index: 35 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 70["Pattern Transform
[4128, 4240, 0]
Copies: 1
Faces: 3
Edges: 3"] + 70["Pattern Transform
[4191, 4303, 0]
Copies: 1
Faces: 3
Edges: 3"] %% [ProgramBodyItem { index: 36 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 71["Pattern Transform
[4128, 4240, 0]
Copies: 1
Faces: 3
Edges: 3"] + 71["Pattern Transform
[4191, 4303, 0]
Copies: 1
Faces: 3
Edges: 3"] %% [ProgramBodyItem { index: 36 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 72["CompositeSolid Subtract
[4252, 4308, 0]
Consumed: false"] + 72["CompositeSolid Subtract
[4315, 4371, 0]
Consumed: false"] %% [ProgramBodyItem { index: 37 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 73["EdgeCut Fillet
[4351, 4667, 0]"] + 73["EdgeCut Fillet
[4414, 4730, 0]"] %% [ProgramBodyItem { index: 38 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 74["SketchBlock
[943, 2053, 0]"] + 74["SketchBlock
[943, 2116, 0]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit] 75["SketchBlockConstraint Coincident
[1112, 1148, 0]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, ExpressionStatementExpr] @@ -172,37 +172,37 @@ flowchart LR %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 20 }, ExpressionStatementExpr] 90["SketchBlockConstraint Distance
[1970, 2013, 0]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 21 }, ExpressionStatementExpr] - 91["SketchBlockConstraint Angle
[2016, 2051, 0]"] + 91["SketchBlockConstraint Angle
[2016, 2114, 0]"] %% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 22 }, ExpressionStatementExpr] - 92["SketchBlock
[2363, 3001, 0]"] + 92["SketchBlock
[2426, 3064, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 93["SketchBlockConstraint Coincident
[2544, 2580, 0]"] + 93["SketchBlockConstraint Coincident
[2607, 2643, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, ExpressionStatementExpr] - 94["SketchBlockConstraint Coincident
[2665, 2701, 0]"] + 94["SketchBlockConstraint Coincident
[2728, 2764, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 95["SketchBlockConstraint Coincident
[2704, 2740, 0]"] + 95["SketchBlockConstraint Coincident
[2767, 2803, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] - 96["SketchBlockConstraint Horizontal
[2744, 2761, 0]"] + 96["SketchBlockConstraint Horizontal
[2807, 2824, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] - 97["SketchBlockConstraint Vertical
[2764, 2779, 0]"] + 97["SketchBlockConstraint Vertical
[2827, 2842, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] - 98["SketchBlockConstraint HorizontalDistance
[2783, 2844, 0]"] + 98["SketchBlockConstraint HorizontalDistance
[2846, 2907, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 8 }, ExpressionStatementExpr] - 99["SketchBlockConstraint VerticalDistance
[2847, 2895, 0]"] + 99["SketchBlockConstraint VerticalDistance
[2910, 2958, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, ExpressionStatementExpr] - 100["SketchBlockConstraint Distance
[2898, 2948, 0]"] + 100["SketchBlockConstraint Distance
[2961, 3011, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] - 101["SketchBlockConstraint Distance
[2951, 2999, 0]"] + 101["SketchBlockConstraint Distance
[3014, 3062, 0]"] %% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] - 102["SketchBlock
[3423, 3788, 0]"] + 102["SketchBlock
[3486, 3851, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 103["SketchBlockConstraint HorizontalDistance
[3542, 3606, 0]"] + 103["SketchBlockConstraint HorizontalDistance
[3605, 3669, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 1 }, ExpressionStatementExpr] - 104["SketchBlockConstraint VerticalDistance
[3609, 3671, 0]"] + 104["SketchBlockConstraint VerticalDistance
[3672, 3734, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, ExpressionStatementExpr] - 105["SketchBlockConstraint HorizontalDistance
[3674, 3733, 0]"] + 105["SketchBlockConstraint HorizontalDistance
[3737, 3796, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 106["SketchBlockConstraint VerticalDistance
[3736, 3786, 0]"] + 106["SketchBlockConstraint VerticalDistance
[3799, 3849, 0]"] %% [ProgramBodyItem { index: 31 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] 1 --- 2 1 <--x 9 diff --git a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ast.snap b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ast.snap index 20aa649b687..48aa6ef913d 100644 --- a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ast.snap @@ -4498,7 +4498,136 @@ description: Result of parsing field-monitor-stand.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "line1", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "line2", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "3.15mm", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 3.15, + "suffix": "Mm" + } + }, + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "3.38mm", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 3.38, + "suffix": "Mm" + } + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -4508,7 +4637,7 @@ description: Result of parsing field-monitor-stand.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -4522,52 +4651,7 @@ description: Result of parsing field-monitor-stand.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "line1", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "line2", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", diff --git a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ops.snap b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ops.snap index b27373c4b82..6b7962baa1f 100644 --- a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/ops.snap @@ -1842,22 +1842,61 @@ description: Operations executed field-monitor-stand.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 3.15, + "ty": { + "mm": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 3.38, + "ty": { + "mm": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/program_memory.snap b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/program_memory.snap index 1acd56e952c..bbe6349af4e 100644 --- a/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/program_memory.snap +++ b/rust/kcl-lib/tests/kcl_samples/field-monitor-stand/program_memory.snap @@ -195,10 +195,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2242, - "end": 2254, + "commentStart": 2305, + "end": 2317, "moduleId": 0, - "start": 2242, + "start": 2305, "type": "TagDeclarator", "value": "capStart001" }, @@ -209,10 +209,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2267, - "end": 2277, + "commentStart": 2330, + "end": 2340, "moduleId": 0, - "start": 2267, + "start": 2330, "type": "TagDeclarator", "value": "capEnd001" }, @@ -240,8 +240,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "tag": { "commentStart": 963, @@ -252,8 +252,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line1" }, "to": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "type": "ToPoint", "units": "mm" @@ -264,8 +264,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "tag": { "commentStart": 1034, @@ -276,7 +276,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line2" }, "to": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "type": "ToPoint", @@ -288,7 +288,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "tag": { @@ -300,7 +300,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line3" }, "to": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "type": "ToPoint", @@ -312,7 +312,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "tag": { @@ -324,8 +324,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line4" }, "to": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "type": "ToPoint", "units": "mm" @@ -336,8 +336,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "tag": { "commentStart": 1398, @@ -348,8 +348,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line5" }, "to": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "type": "ToPoint", "units": "mm" @@ -360,8 +360,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "tag": { "commentStart": 1512, @@ -372,8 +372,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line6" }, "to": [ - -60.00000000000002, - -0.000000000000020375276633059364 + -60.00000000000003, + -0.00000000000002003277505613585 ], "type": "ToPoint", "units": "mm" @@ -412,12 +412,12 @@ description: Variables in memory after executing field-monitor-stand.kcl }, "start": { "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "to": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "units": "mm", "tag": null, @@ -567,10 +567,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2242, - "end": 2254, + "commentStart": 2305, + "end": 2317, "moduleId": 0, - "start": 2242, + "start": 2305, "type": "TagDeclarator", "value": "capStart001" }, @@ -581,10 +581,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2267, - "end": 2277, + "commentStart": 2330, + "end": 2340, "moduleId": 0, - "start": 2267, + "start": 2330, "type": "TagDeclarator", "value": "capEnd001" }, @@ -612,8 +612,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "tag": { "commentStart": 963, @@ -624,8 +624,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line1" }, "to": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "type": "ToPoint", "units": "mm" @@ -636,8 +636,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "tag": { "commentStart": 1034, @@ -648,7 +648,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line2" }, "to": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "type": "ToPoint", @@ -660,7 +660,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "tag": { @@ -672,7 +672,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line3" }, "to": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "type": "ToPoint", @@ -684,7 +684,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "tag": { @@ -696,8 +696,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line4" }, "to": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "type": "ToPoint", "units": "mm" @@ -708,8 +708,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "tag": { "commentStart": 1398, @@ -720,8 +720,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line5" }, "to": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "type": "ToPoint", "units": "mm" @@ -732,8 +732,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "tag": { "commentStart": 1512, @@ -744,8 +744,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line6" }, "to": [ - -60.00000000000002, - -0.000000000000020375276633059364 + -60.00000000000003, + -0.00000000000002003277505613585 ], "type": "ToPoint", "units": "mm" @@ -784,12 +784,12 @@ description: Variables in memory after executing field-monitor-stand.kcl }, "start": { "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "to": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "units": "mm", "tag": null, @@ -939,10 +939,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2242, - "end": 2254, + "commentStart": 2305, + "end": 2317, "moduleId": 0, - "start": 2242, + "start": 2305, "type": "TagDeclarator", "value": "capStart001" }, @@ -953,10 +953,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2267, - "end": 2277, + "commentStart": 2330, + "end": 2340, "moduleId": 0, - "start": 2267, + "start": 2330, "type": "TagDeclarator", "value": "capEnd001" }, @@ -984,8 +984,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "tag": { "commentStart": 963, @@ -996,8 +996,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line1" }, "to": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "type": "ToPoint", "units": "mm" @@ -1008,8 +1008,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "tag": { "commentStart": 1034, @@ -1020,7 +1020,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line2" }, "to": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "type": "ToPoint", @@ -1032,7 +1032,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "tag": { @@ -1044,7 +1044,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line3" }, "to": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "type": "ToPoint", @@ -1056,7 +1056,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "tag": { @@ -1068,8 +1068,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line4" }, "to": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "type": "ToPoint", "units": "mm" @@ -1080,8 +1080,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "tag": { "commentStart": 1398, @@ -1092,8 +1092,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line5" }, "to": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "type": "ToPoint", "units": "mm" @@ -1104,8 +1104,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "tag": { "commentStart": 1512, @@ -1116,8 +1116,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line6" }, "to": [ - -60.00000000000002, - -0.000000000000020375276633059364 + -60.00000000000003, + -0.00000000000002003277505613585 ], "type": "ToPoint", "units": "mm" @@ -1156,12 +1156,12 @@ description: Variables in memory after executing field-monitor-stand.kcl }, "start": { "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "to": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "units": "mm", "tag": null, @@ -1288,7 +1288,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "line": { "start": [ { - "n": -60.00000000000002, + "n": -60.00000000000003, "ty": { "mm": null, "type": "Known", @@ -1296,7 +1296,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": -0.00000000000002497146472962705, + "n": -0.000000000000024627188716874425, "ty": { "mm": null, "type": "Known", @@ -1306,7 +1306,7 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "end": [ { - "n": -0.0000000000000238752171250505, + "n": -0.000000000000023746877142839638, "ty": { "mm": null, "type": "Known", @@ -1314,7 +1314,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": -0.000000000000004292440421957927, + "n": -0.0000000000000042394081032752924, "ty": { "mm": null, "type": "Known", @@ -1408,7 +1408,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "line": { "start": [ { - "n": -0.000000000000047750558530136477, + "n": -0.000000000000047493877015281016, "ty": { "mm": null, "type": "Known", @@ -1416,7 +1416,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": -0.000000000000013181110199538001, + "n": -0.00000000000001307312694734255, "ty": { "mm": null, "type": "Known", @@ -1426,7 +1426,7 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "end": [ { - "n": -41.384437342405995, + "n": -41.38443734240601, "ty": { "mm": null, "type": "Known", @@ -1528,7 +1528,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "line": { "start": [ { - "n": -41.38443734240602, + "n": -41.38443734240603, "ty": { "mm": null, "type": "Known", @@ -1546,7 +1546,7 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "end": [ { - "n": -44.203515204763775, + "n": -44.20351520476378, "ty": { "mm": null, "type": "Known", @@ -1648,7 +1648,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "line": { "start": [ { - "n": -44.20351520476379, + "n": -44.203515204763804, "ty": { "mm": null, "type": "Known", @@ -1666,7 +1666,7 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "end": [ { - "n": -4.28444402022648, + "n": -4.284444020226475, "ty": { "mm": null, "type": "Known", @@ -1674,7 +1674,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": 2.999999999999998, + "n": 2.9999999999999987, "ty": { "mm": null, "type": "Known", @@ -1768,7 +1768,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "line": { "start": [ { - "n": -4.284444020226486, + "n": -4.2844440202264815, "ty": { "mm": null, "type": "Known", @@ -1776,7 +1776,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": 2.9999999999999933, + "n": 2.999999999999994, "ty": { "mm": null, "type": "Known", @@ -1786,7 +1786,7 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "end": [ { - "n": -60.00000000000002, + "n": -60.00000000000003, "ty": { "mm": null, "type": "Known", @@ -1794,7 +1794,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": 2.9999999999999885, + "n": 2.9999999999999893, "ty": { "mm": null, "type": "Known", @@ -1888,7 +1888,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "line": { "start": [ { - "n": -60.00000000000002, + "n": -60.00000000000003, "ty": { "mm": null, "type": "Known", @@ -1896,7 +1896,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": 2.999999999999984, + "n": 2.999999999999985, "ty": { "mm": null, "type": "Known", @@ -1906,7 +1906,7 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "end": [ { - "n": -60.00000000000002, + "n": -60.00000000000003, "ty": { "mm": null, "type": "Known", @@ -1914,7 +1914,7 @@ description: Variables in memory after executing field-monitor-stand.kcl } }, { - "n": -0.000000000000020375276633059364, + "n": -0.00000000000002003277505613585, "ty": { "mm": null, "type": "Known", @@ -2011,8 +2011,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "tag": { "commentStart": 963, @@ -2023,8 +2023,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line1" }, "to": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "type": "ToPoint", "units": "mm" @@ -2035,8 +2035,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "tag": { "commentStart": 1034, @@ -2047,7 +2047,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line2" }, "to": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "type": "ToPoint", @@ -2059,7 +2059,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "tag": { @@ -2071,7 +2071,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line3" }, "to": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "type": "ToPoint", @@ -2083,7 +2083,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "tag": { @@ -2095,8 +2095,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line4" }, "to": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "type": "ToPoint", "units": "mm" @@ -2107,8 +2107,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "tag": { "commentStart": 1398, @@ -2119,8 +2119,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line5" }, "to": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "type": "ToPoint", "units": "mm" @@ -2131,8 +2131,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "tag": { "commentStart": 1512, @@ -2143,8 +2143,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line6" }, "to": [ - -60.00000000000002, - -0.000000000000020375276633059364 + -60.00000000000003, + -0.00000000000002003277505613585 ], "type": "ToPoint", "units": "mm" @@ -2183,12 +2183,12 @@ description: Variables in memory after executing field-monitor-stand.kcl }, "start": { "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "to": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "units": "mm", "tag": null, @@ -2247,8 +2247,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "tag": { "commentStart": 963, @@ -2259,8 +2259,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line1" }, "to": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "type": "ToPoint", "units": "mm" @@ -2271,8 +2271,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -0.0000000000000238752171250505, - -0.000000000000004292440421957927 + -0.000000000000023746877142839638, + -0.0000000000000042394081032752924 ], "tag": { "commentStart": 1034, @@ -2283,7 +2283,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line2" }, "to": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "type": "ToPoint", @@ -2295,7 +2295,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -41.384437342405995, + -41.38443734240601, 113.70280711509488 ], "tag": { @@ -2307,7 +2307,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line3" }, "to": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "type": "ToPoint", @@ -2319,7 +2319,7 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -44.203515204763775, + -44.20351520476378, 112.67674668511785 ], "tag": { @@ -2331,8 +2331,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line4" }, "to": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "type": "ToPoint", "units": "mm" @@ -2343,8 +2343,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -4.28444402022648, - 2.999999999999998 + -4.284444020226475, + 2.9999999999999987 ], "tag": { "commentStart": 1398, @@ -2355,8 +2355,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line5" }, "to": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "type": "ToPoint", "units": "mm" @@ -2367,8 +2367,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "sourceRange": [] }, "from": [ - -60.00000000000002, - 2.9999999999999885 + -60.00000000000003, + 2.9999999999999893 ], "tag": { "commentStart": 1512, @@ -2379,8 +2379,8 @@ description: Variables in memory after executing field-monitor-stand.kcl "value": "line6" }, "to": [ - -60.00000000000002, - -0.000000000000020375276633059364 + -60.00000000000003, + -0.00000000000002003277505613585 ], "type": "ToPoint", "units": "mm" @@ -2419,12 +2419,12 @@ description: Variables in memory after executing field-monitor-stand.kcl }, "start": { "from": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "to": [ - -60.00000000000002, - -0.00000000000002497146472962705 + -60.00000000000003, + -0.000000000000024627188716874425 ], "units": "mm", "tag": null, @@ -2504,10 +2504,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2383, - "end": 2388, + "commentStart": 2446, + "end": 2451, "moduleId": 0, - "start": 2383, + "start": 2446, "type": "TagDeclarator", "value": "line1" }, @@ -2518,10 +2518,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2461, - "end": 2466, + "commentStart": 2524, + "end": 2529, "moduleId": 0, - "start": 2461, + "start": 2524, "type": "TagDeclarator", "value": "line2" }, @@ -2532,10 +2532,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 2583, - "end": 2588, + "commentStart": 2646, + "end": 2651, "moduleId": 0, - "start": 2583, + "start": 2646, "type": "TagDeclarator", "value": "line3" }, @@ -2557,10 +2557,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 2.9999999999956772 ], "tag": { - "commentStart": 2383, - "end": 2388, + "commentStart": 2446, + "end": 2451, "moduleId": 0, - "start": 2383, + "start": 2446, "type": "TagDeclarator", "value": "line1" }, @@ -2581,10 +2581,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 2.999999999991355 ], "tag": { - "commentStart": 2461, - "end": 2466, + "commentStart": 2524, + "end": 2529, "moduleId": 0, - "start": 2461, + "start": 2524, "type": "TagDeclarator", "value": "line2" }, @@ -2605,10 +2605,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 44.21216129180205 ], "tag": { - "commentStart": 2583, - "end": 2588, + "commentStart": 2646, + "end": 2651, "moduleId": 0, - "start": 2583, + "start": 2646, "type": "TagDeclarator", "value": "line3" }, @@ -3083,10 +3083,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 2.9999999999956772 ], "tag": { - "commentStart": 2383, - "end": 2388, + "commentStart": 2446, + "end": 2451, "moduleId": 0, - "start": 2383, + "start": 2446, "type": "TagDeclarator", "value": "line1" }, @@ -3107,10 +3107,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 2.999999999991355 ], "tag": { - "commentStart": 2461, - "end": 2466, + "commentStart": 2524, + "end": 2529, "moduleId": 0, - "start": 2461, + "start": 2524, "type": "TagDeclarator", "value": "line2" }, @@ -3131,10 +3131,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 44.21216129180205 ], "tag": { - "commentStart": 2583, - "end": 2588, + "commentStart": 2646, + "end": 2651, "moduleId": 0, - "start": 2583, + "start": 2646, "type": "TagDeclarator", "value": "line3" }, @@ -3235,10 +3235,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 2.9999999999956772 ], "tag": { - "commentStart": 2383, - "end": 2388, + "commentStart": 2446, + "end": 2451, "moduleId": 0, - "start": 2383, + "start": 2446, "type": "TagDeclarator", "value": "line1" }, @@ -3259,10 +3259,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 2.999999999991355 ], "tag": { - "commentStart": 2461, - "end": 2466, + "commentStart": 2524, + "end": 2529, "moduleId": 0, - "start": 2461, + "start": 2524, "type": "TagDeclarator", "value": "line2" }, @@ -3283,10 +3283,10 @@ description: Variables in memory after executing field-monitor-stand.kcl 44.21216129180205 ], "tag": { - "commentStart": 2583, - "end": 2588, + "commentStart": 2646, + "end": 2651, "moduleId": 0, - "start": 2583, + "start": 2646, "type": "TagDeclarator", "value": "line3" }, @@ -3418,10 +3418,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3449,10 +3449,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3543,10 +3543,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3574,10 +3574,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3665,10 +3665,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3696,10 +3696,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3792,10 +3792,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3823,10 +3823,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3914,10 +3914,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -3945,10 +3945,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -4036,10 +4036,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -4067,10 +4067,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -4158,10 +4158,10 @@ description: Variables in memory after executing field-monitor-stand.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -4189,10 +4189,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -4436,10 +4436,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, @@ -4547,10 +4547,10 @@ description: Variables in memory after executing field-monitor-stand.kcl ], "radius": 2.0, "tag": { - "commentStart": 3456, - "end": 3460, + "commentStart": 3519, + "end": 3523, "moduleId": 0, - "start": 3456, + "start": 3519, "type": "TagDeclarator", "value": "hole" }, diff --git a/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_commands.snap index 55ffa4c759c..b284fecb6ff 100644 --- a/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_commands.snap @@ -68,8 +68,8 @@ description: Artifact commands m4-insert.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -3.150000000025, - "y": 0.00000000005169368042384991, + "x": -3.15, + "y": -0.00000000000011334396960489123, "z": 0.0 } } @@ -90,8 +90,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -3.150000000025, - "y": -2.279999999942562, + "x": -3.15, + "y": -2.280000000000126, "z": 0.0 }, "relative": false @@ -107,8 +107,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.550000000018368, - "y": -2.279999999931075, + "x": -2.550000000000013, + "y": -2.280000000000151, "z": 0.0 }, "relative": false @@ -124,8 +124,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.550000000018368, - "y": -3.132871870667607, + "x": -2.550000000000013, + "y": -3.1328718708048537, "z": 0.0 }, "relative": false @@ -141,8 +141,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -3.1100000000316324, - "y": -3.132871870664735, + "x": -3.109999999999987, + "y": -3.1328718708048635, "z": 0.0 }, "relative": false @@ -158,8 +158,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -3.110000000044407, - "y": -5.532871870673323, + "x": -3.1099999999999617, + "y": -5.532871870804853, "z": 0.0 }, "relative": false @@ -175,8 +175,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.1499999999653094, - "y": -6.087128129162952, + "x": -2.150000000000118, + "y": -6.087128129195516, "z": 0.0 }, "relative": false @@ -192,8 +192,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.149999999978574, - "y": -6.939999999919587, + "x": -2.150000000000092, + "y": -6.940000000000176, "z": 0.0 }, "relative": false @@ -209,8 +209,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.749999999998471, - "y": -6.939999999931075, + "x": -2.7500000000000524, + "y": -6.940000000000151, "z": 0.0 }, "relative": false @@ -226,8 +226,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.7500000000117355, - "y": -8.099999999942563, + "x": -2.750000000000026, + "y": -8.100000000000126, "z": 0.0 }, "relative": false @@ -241,8 +241,8 @@ description: Artifact commands m4-insert.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -3.150000000025, - "y": 0.00000000004594993807505346, + "x": -3.15, + "y": -0.00000000000010075004870403091, "z": 0.0 } } @@ -256,8 +256,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -1.555000000075, - "y": 0.00000000004020619577220696, + "x": -1.5550000000000002, + "y": -0.00000000000008815618544209148, "z": 0.0 }, "relative": false @@ -273,8 +273,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -1.55500000008, - "y": -8.099999999959794, + "x": -1.5550000000000002, + "y": -8.100000000000088, "z": 0.0 }, "relative": false @@ -290,8 +290,8 @@ description: Artifact commands m4-insert.kcl "segment": { "type": "line", "end": { - "x": -2.7500000000183675, - "y": -8.099999999948306, + "x": -2.7500000000000133, + "y": -8.100000000000113, "z": 0.0 }, "relative": false diff --git a/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_graph_flowchart.snap.md index 39101dfcc81..45725bd5071 100644 --- a/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/m4-insert/artifact_graph_flowchart.snap.md @@ -1,7 +1,7 @@ ```mermaid flowchart LR subgraph path2 [Path] - 2["Path
[559, 3574, 0]
Consumed: false"] + 2["Path
[559, 3639, 0]
Consumed: false"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] 3["Segment
[594, 664, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit] @@ -29,36 +29,36 @@ flowchart LR %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 20 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path15 [Path] - 15["Path Region
[3598, 3664, 0]
Consumed: true"] + 15["Path Region
[3663, 3729, 0]
Consumed: true"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 16["Segment
[3598, 3664, 0]"] + 16["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 17["Segment
[3598, 3664, 0]"] + 17["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 18["Segment
[3598, 3664, 0]"] + 18["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 19["Segment
[3598, 3664, 0]"] + 19["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 20["Segment
[3598, 3664, 0]"] + 20["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 21["Segment
[3598, 3664, 0]"] + 21["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 22["Segment
[3598, 3664, 0]"] + 22["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 23["Segment
[3598, 3664, 0]"] + 23["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 24["Segment
[3598, 3664, 0]"] + 24["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 25["Segment
[3598, 3664, 0]"] + 25["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 26["Segment
[3598, 3664, 0]"] + 26["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 27["Segment
[3598, 3664, 0]"] + 27["Segment
[3663, 3729, 0]"] %% [ProgramBodyItem { index: 13 }, VariableDeclarationDeclaration, VariableDeclarationInit] end - 1["Plane
[559, 3574, 0]"] + 1["Plane
[559, 3639, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 28["Sweep Revolve
[3678, 3732, 0]
Consumed: false"] + 28["Sweep Revolve
[3743, 3797, 0]
Consumed: false"] %% [ProgramBodyItem { index: 14 }, VariableDeclarationDeclaration, VariableDeclarationInit] 29[Wall] %% face_code_ref=Missing NodePath @@ -96,7 +96,7 @@ flowchart LR 50["SweepEdge Adjacent"] 51["SweepEdge Adjacent"] 52["SweepEdge Adjacent"] - 53["SketchBlock
[559, 3574, 0]"] + 53["SketchBlock
[559, 3639, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit] 54["SketchBlockConstraint Coincident
[758, 807, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, ExpressionStatementExpr] @@ -172,7 +172,7 @@ flowchart LR %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 48 }, ExpressionStatementExpr] 90["SketchBlockConstraint VerticalDistance
[3454, 3527, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 49 }, ExpressionStatementExpr] - 91["SketchBlockConstraint Angle
[3530, 3572, 0]"] + 91["SketchBlockConstraint Angle
[3530, 3637, 0]"] %% [ProgramBodyItem { index: 12 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 50 }, ExpressionStatementExpr] 1 --- 2 1 <--x 15 diff --git a/rust/kcl-lib/tests/kcl_samples/m4-insert/ast.snap b/rust/kcl-lib/tests/kcl_samples/m4-insert/ast.snap index 62d240df53c..dcb877829c2 100644 --- a/rust/kcl-lib/tests/kcl_samples/m4-insert/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/m4-insert/ast.snap @@ -6829,7 +6829,154 @@ description: Result of parsing m4-insert.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "midWall", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "taperFlank", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2.83mm", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.83, + "suffix": "Mm" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "-", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + }, + { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "6.02mm", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 6.02, + "suffix": "Mm" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "-", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -6839,7 +6986,7 @@ description: Result of parsing m4-insert.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -6853,52 +7000,7 @@ description: Result of parsing m4-insert.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "midWall", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "taperFlank", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", diff --git a/rust/kcl-lib/tests/kcl_samples/m4-insert/ops.snap b/rust/kcl-lib/tests/kcl_samples/m4-insert/ops.snap index 81851997fb9..736a4b04479 100644 --- a/rust/kcl-lib/tests/kcl_samples/m4-insert/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/m4-insert/ops.snap @@ -3088,22 +3088,61 @@ description: Operations executed m4-insert.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": -2.83, + "ty": { + "mm": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": -6.02, + "ty": { + "mm": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/m4-insert/program_memory.snap b/rust/kcl-lib/tests/kcl_samples/m4-insert/program_memory.snap index 71fbac20af7..b82e779e010 100644 --- a/rust/kcl-lib/tests/kcl_samples/m4-insert/program_memory.snap +++ b/rust/kcl-lib/tests/kcl_samples/m4-insert/program_memory.snap @@ -61,8 +61,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "tag": { "commentStart": 579, @@ -73,8 +73,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "outerTopWall" }, "to": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "type": "ToPoint", "units": "mm" @@ -85,8 +85,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "tag": { "commentStart": 667, @@ -97,8 +97,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topShoulder" }, "to": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "type": "ToPoint", "units": "mm" @@ -109,8 +109,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "tag": { "commentStart": 810, @@ -121,8 +121,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperNeckWall" }, "to": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "type": "ToPoint", "units": "mm" @@ -133,8 +133,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "tag": { "commentStart": 956, @@ -145,8 +145,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperRib" }, "to": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "type": "ToPoint", "units": "mm" @@ -157,8 +157,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "tag": { "commentStart": 1094, @@ -169,8 +169,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "midWall" }, "to": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "type": "ToPoint", "units": "mm" @@ -181,8 +181,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "tag": { "commentStart": 1225, @@ -193,8 +193,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "taperFlank" }, "to": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "type": "ToPoint", "units": "mm" @@ -205,8 +205,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "tag": { "commentStart": 1361, @@ -217,8 +217,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerNeckWall" }, "to": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "type": "ToPoint", "units": "mm" @@ -229,8 +229,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "tag": { "commentStart": 1506, @@ -241,8 +241,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerRib" }, "to": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "type": "ToPoint", "units": "mm" @@ -253,8 +253,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "tag": { "commentStart": 1644, @@ -265,8 +265,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerBandWall" }, "to": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "type": "ToPoint", "units": "mm" @@ -277,13 +277,13 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "tag": null, "to": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "type": "ToPoint", "units": "mm" @@ -294,8 +294,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "tag": { "commentStart": 1786, @@ -306,8 +306,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topBridge" }, "to": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "type": "ToPoint", "units": "mm" @@ -318,8 +318,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "tag": { "commentStart": 1867, @@ -330,8 +330,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "innerWall" }, "to": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "type": "ToPoint", "units": "mm" @@ -342,8 +342,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "tag": { "commentStart": 1998, @@ -354,8 +354,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "bottomBridge" }, "to": [ - -2.7500000000183675, - -8.099999999948306 + -2.7500000000000133, + -8.100000000000113 ], "type": "ToPoint", "units": "mm" @@ -394,12 +394,12 @@ description: Variables in memory after executing m4-insert.kcl }, "start": { "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "to": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "units": "mm", "tag": null, @@ -656,8 +656,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "tag": { "commentStart": 579, @@ -668,8 +668,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "outerTopWall" }, "to": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "type": "ToPoint", "units": "mm" @@ -680,8 +680,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "tag": { "commentStart": 667, @@ -692,8 +692,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topShoulder" }, "to": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "type": "ToPoint", "units": "mm" @@ -704,8 +704,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "tag": { "commentStart": 810, @@ -716,8 +716,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperNeckWall" }, "to": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "type": "ToPoint", "units": "mm" @@ -728,8 +728,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "tag": { "commentStart": 956, @@ -740,8 +740,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperRib" }, "to": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "type": "ToPoint", "units": "mm" @@ -752,8 +752,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "tag": { "commentStart": 1094, @@ -764,8 +764,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "midWall" }, "to": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "type": "ToPoint", "units": "mm" @@ -776,8 +776,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "tag": { "commentStart": 1225, @@ -788,8 +788,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "taperFlank" }, "to": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "type": "ToPoint", "units": "mm" @@ -800,8 +800,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "tag": { "commentStart": 1361, @@ -812,8 +812,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerNeckWall" }, "to": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "type": "ToPoint", "units": "mm" @@ -824,8 +824,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "tag": { "commentStart": 1506, @@ -836,8 +836,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerRib" }, "to": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "type": "ToPoint", "units": "mm" @@ -848,8 +848,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "tag": { "commentStart": 1644, @@ -860,8 +860,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerBandWall" }, "to": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "type": "ToPoint", "units": "mm" @@ -872,8 +872,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "tag": { "commentStart": 1786, @@ -884,8 +884,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topBridge" }, "to": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "type": "ToPoint", "units": "mm" @@ -896,8 +896,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "tag": { "commentStart": 1867, @@ -908,8 +908,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "innerWall" }, "to": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "type": "ToPoint", "units": "mm" @@ -920,8 +920,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "tag": { "commentStart": 1998, @@ -932,8 +932,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "bottomBridge" }, "to": [ - -2.7500000000183675, - -8.099999999948306 + -2.7500000000000133, + -8.100000000000113 ], "type": "ToPoint", "units": "mm" @@ -972,12 +972,12 @@ description: Variables in memory after executing m4-insert.kcl }, "start": { "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "to": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "units": "mm", "tag": null, @@ -1108,8 +1108,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "tag": { "commentStart": 579, @@ -1120,8 +1120,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "outerTopWall" }, "to": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "type": "ToPoint", "units": "mm" @@ -1132,8 +1132,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "tag": { "commentStart": 667, @@ -1144,8 +1144,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topShoulder" }, "to": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "type": "ToPoint", "units": "mm" @@ -1156,8 +1156,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "tag": { "commentStart": 810, @@ -1168,8 +1168,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperNeckWall" }, "to": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "type": "ToPoint", "units": "mm" @@ -1180,8 +1180,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "tag": { "commentStart": 956, @@ -1192,8 +1192,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperRib" }, "to": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "type": "ToPoint", "units": "mm" @@ -1204,8 +1204,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "tag": { "commentStart": 1094, @@ -1216,8 +1216,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "midWall" }, "to": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "type": "ToPoint", "units": "mm" @@ -1228,8 +1228,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "tag": { "commentStart": 1225, @@ -1240,8 +1240,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "taperFlank" }, "to": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "type": "ToPoint", "units": "mm" @@ -1252,8 +1252,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "tag": { "commentStart": 1361, @@ -1264,8 +1264,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerNeckWall" }, "to": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "type": "ToPoint", "units": "mm" @@ -1276,8 +1276,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "tag": { "commentStart": 1506, @@ -1288,8 +1288,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerRib" }, "to": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "type": "ToPoint", "units": "mm" @@ -1300,8 +1300,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "tag": { "commentStart": 1644, @@ -1312,8 +1312,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerBandWall" }, "to": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "type": "ToPoint", "units": "mm" @@ -1324,8 +1324,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "tag": { "commentStart": 1786, @@ -1336,8 +1336,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topBridge" }, "to": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "type": "ToPoint", "units": "mm" @@ -1348,8 +1348,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "tag": { "commentStart": 1867, @@ -1360,8 +1360,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "innerWall" }, "to": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "type": "ToPoint", "units": "mm" @@ -1372,8 +1372,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "tag": { "commentStart": 1998, @@ -1384,8 +1384,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "bottomBridge" }, "to": [ - -2.7500000000183675, - -8.099999999948306 + -2.7500000000000133, + -8.100000000000113 ], "type": "ToPoint", "units": "mm" @@ -1424,12 +1424,12 @@ description: Variables in memory after executing m4-insert.kcl }, "start": { "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "to": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "units": "mm", "tag": null, @@ -1509,7 +1509,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -1.555000000085, + "n": -1.5550000000000002, "ty": { "mm": null, "type": "Known", @@ -1517,7 +1517,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -8.099999999954049, + "n": -8.100000000000101, "ty": { "mm": null, "type": "Known", @@ -1527,7 +1527,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.7500000000183675, + "n": -2.7500000000000133, "ty": { "mm": null, "type": "Known", @@ -1535,7 +1535,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -8.099999999948306, + "n": -8.100000000000113, "ty": { "mm": null, "type": "Known", @@ -1629,7 +1629,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -1.55500000005, + "n": -1.5550000000000002, "ty": { "mm": null, "type": "Known", @@ -1637,7 +1637,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": 0.000000000022974968987231965, + "n": -0.00000000000005037489105991183, "ty": { "mm": null, "type": "Known", @@ -1647,7 +1647,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -0.000000000025000001771214184, + "n": -0.0000000000000002342456926681171, "ty": { "mm": null, "type": "Known", @@ -1655,7 +1655,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": 0.000000000011487484487872239, + "n": -0.00000000000002518743832509161, "ty": { "mm": null, "type": "Known", @@ -1750,7 +1750,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -1.55500000007, + "n": -1.5550000000000002, "ty": { "mm": null, "type": "Known", @@ -1758,7 +1758,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": 0.00000000003446245350956666, + "n": -0.00000000000007556237261419411, "ty": { "mm": null, "type": "Known", @@ -1768,7 +1768,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -1.55500000008, + "n": -1.5550000000000002, "ty": { "mm": null, "type": "Known", @@ -1776,7 +1776,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -8.099999999959794, + "n": -8.100000000000088, "ty": { "mm": null, "type": "Known", @@ -1870,7 +1870,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -2.750000000005103, + "n": -2.7500000000000395, "ty": { "mm": null, "type": "Known", @@ -1878,7 +1878,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -6.939999999936819, + "n": -6.940000000000139, "ty": { "mm": null, "type": "Known", @@ -1888,7 +1888,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.7500000000117355, + "n": -2.750000000000026, "ty": { "mm": null, "type": "Known", @@ -1896,7 +1896,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -8.099999999942563, + "n": -8.100000000000126, "ty": { "mm": null, "type": "Known", @@ -1990,7 +1990,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -2.1499999999719415, + "n": -2.1500000000001047, "ty": { "mm": null, "type": "Known", @@ -1998,7 +1998,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -6.0871281291715675, + "n": -6.0871281291954995, "ty": { "mm": null, "type": "Known", @@ -2008,7 +2008,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.149999999978574, + "n": -2.150000000000092, "ty": { "mm": null, "type": "Known", @@ -2016,7 +2016,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -6.939999999919587, + "n": -6.940000000000176, "ty": { "mm": null, "type": "Known", @@ -2110,7 +2110,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -2.1499999999852064, + "n": -2.1500000000000785, "ty": { "mm": null, "type": "Known", @@ -2118,7 +2118,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -6.939999999925331, + "n": -6.940000000000164, "ty": { "mm": null, "type": "Known", @@ -2128,7 +2128,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.749999999998471, + "n": -2.7500000000000524, "ty": { "mm": null, "type": "Known", @@ -2136,7 +2136,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -6.939999999931075, + "n": -6.940000000000151, "ty": { "mm": null, "type": "Known", @@ -2233,8 +2233,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "tag": { "commentStart": 579, @@ -2245,8 +2245,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "outerTopWall" }, "to": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "type": "ToPoint", "units": "mm" @@ -2257,8 +2257,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "tag": { "commentStart": 667, @@ -2269,8 +2269,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topShoulder" }, "to": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "type": "ToPoint", "units": "mm" @@ -2281,8 +2281,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "tag": { "commentStart": 810, @@ -2293,8 +2293,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperNeckWall" }, "to": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "type": "ToPoint", "units": "mm" @@ -2305,8 +2305,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "tag": { "commentStart": 956, @@ -2317,8 +2317,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperRib" }, "to": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "type": "ToPoint", "units": "mm" @@ -2329,8 +2329,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "tag": { "commentStart": 1094, @@ -2341,8 +2341,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "midWall" }, "to": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "type": "ToPoint", "units": "mm" @@ -2353,8 +2353,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "tag": { "commentStart": 1225, @@ -2365,8 +2365,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "taperFlank" }, "to": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "type": "ToPoint", "units": "mm" @@ -2377,8 +2377,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "tag": { "commentStart": 1361, @@ -2389,8 +2389,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerNeckWall" }, "to": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "type": "ToPoint", "units": "mm" @@ -2401,8 +2401,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "tag": { "commentStart": 1506, @@ -2413,8 +2413,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerRib" }, "to": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "type": "ToPoint", "units": "mm" @@ -2425,8 +2425,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "tag": { "commentStart": 1644, @@ -2437,8 +2437,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerBandWall" }, "to": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "type": "ToPoint", "units": "mm" @@ -2449,13 +2449,13 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "tag": null, "to": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "type": "ToPoint", "units": "mm" @@ -2466,8 +2466,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "tag": { "commentStart": 1786, @@ -2478,8 +2478,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topBridge" }, "to": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "type": "ToPoint", "units": "mm" @@ -2490,8 +2490,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "tag": { "commentStart": 1867, @@ -2502,8 +2502,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "innerWall" }, "to": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "type": "ToPoint", "units": "mm" @@ -2514,8 +2514,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "tag": { "commentStart": 1998, @@ -2526,8 +2526,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "bottomBridge" }, "to": [ - -2.7500000000183675, - -8.099999999948306 + -2.7500000000000133, + -8.100000000000113 ], "type": "ToPoint", "units": "mm" @@ -2566,12 +2566,12 @@ description: Variables in memory after executing m4-insert.kcl }, "start": { "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "to": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "units": "mm", "tag": null, @@ -2651,7 +2651,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -3.1100000000316324, + "n": -3.109999999999987, "ty": { "mm": null, "type": "Known", @@ -2659,7 +2659,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -3.132871870667607, + "n": -3.1328718708048613, "ty": { "mm": null, "type": "Known", @@ -2669,7 +2669,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -3.110000000044407, + "n": -3.1099999999999617, "ty": { "mm": null, "type": "Known", @@ -2677,7 +2677,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -5.532871870673323, + "n": -5.532871870804853, "ty": { "mm": null, "type": "Known", @@ -2771,7 +2771,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -3.150000000025, + "n": -3.15, "ty": { "mm": null, "type": "Known", @@ -2779,7 +2779,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": 0.00000000005169368042384991, + "n": -0.00000000000011334396960489123, "ty": { "mm": null, "type": "Known", @@ -2789,7 +2789,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -3.150000000025, + "n": -3.15, "ty": { "mm": null, "type": "Known", @@ -2797,7 +2797,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -2.279999999942562, + "n": -2.280000000000126, "ty": { "mm": null, "type": "Known", @@ -2891,7 +2891,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -3.1100000000510395, + "n": -3.1099999999999515, "ty": { "mm": null, "type": "Known", @@ -2899,7 +2899,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -5.532871870681939, + "n": -5.532871870804841, "ty": { "mm": null, "type": "Known", @@ -2909,7 +2909,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.1499999999653094, + "n": -2.150000000000118, "ty": { "mm": null, "type": "Known", @@ -2917,7 +2917,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -6.087128129162952, + "n": -6.087128129195516, "ty": { "mm": null, "type": "Known", @@ -3011,7 +3011,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -3.150000000025, + "n": -3.15, "ty": { "mm": null, "type": "Known", @@ -3019,7 +3019,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": 0.00000000004594993807505346, + "n": -0.00000000000010075004870403091, "ty": { "mm": null, "type": "Known", @@ -3029,7 +3029,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -1.555000000075, + "n": -1.5550000000000002, "ty": { "mm": null, "type": "Known", @@ -3037,7 +3037,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": 0.00000000004020619577220696, + "n": -0.00000000000008815618544209148, "ty": { "mm": null, "type": "Known", @@ -3131,7 +3131,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -3.150000000025, + "n": -3.15, "ty": { "mm": null, "type": "Known", @@ -3139,7 +3139,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -2.279999999936819, + "n": -2.2800000000001384, "ty": { "mm": null, "type": "Known", @@ -3149,7 +3149,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.550000000018368, + "n": -2.550000000000013, "ty": { "mm": null, "type": "Known", @@ -3157,7 +3157,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -2.279999999931075, + "n": -2.280000000000151, "ty": { "mm": null, "type": "Known", @@ -3251,7 +3251,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -2.550000000018368, + "n": -2.550000000000013, "ty": { "mm": null, "type": "Known", @@ -3259,7 +3259,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -2.279999999925331, + "n": -2.2800000000001637, "ty": { "mm": null, "type": "Known", @@ -3269,7 +3269,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -2.550000000018368, + "n": -2.550000000000013, "ty": { "mm": null, "type": "Known", @@ -3277,7 +3277,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -3.132871870667607, + "n": -3.1328718708048537, "ty": { "mm": null, "type": "Known", @@ -3371,7 +3371,7 @@ description: Variables in memory after executing m4-insert.kcl "line": { "start": [ { - "n": -2.550000000018368, + "n": -2.550000000000013, "ty": { "mm": null, "type": "Known", @@ -3379,7 +3379,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -3.132871870664735, + "n": -3.1328718708048613, "ty": { "mm": null, "type": "Known", @@ -3389,7 +3389,7 @@ description: Variables in memory after executing m4-insert.kcl ], "end": [ { - "n": -3.1100000000316324, + "n": -3.109999999999987, "ty": { "mm": null, "type": "Known", @@ -3397,7 +3397,7 @@ description: Variables in memory after executing m4-insert.kcl } }, { - "n": -3.132871870664735, + "n": -3.1328718708048635, "ty": { "mm": null, "type": "Known", @@ -3721,8 +3721,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "tag": { "commentStart": 579, @@ -3733,8 +3733,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "outerTopWall" }, "to": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "type": "ToPoint", "units": "mm" @@ -3745,8 +3745,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - -2.279999999942562 + -3.15, + -2.280000000000126 ], "tag": { "commentStart": 667, @@ -3757,8 +3757,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topShoulder" }, "to": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "type": "ToPoint", "units": "mm" @@ -3769,8 +3769,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -2.279999999931075 + -2.550000000000013, + -2.280000000000151 ], "tag": { "commentStart": 810, @@ -3781,8 +3781,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperNeckWall" }, "to": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "type": "ToPoint", "units": "mm" @@ -3793,8 +3793,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.550000000018368, - -3.132871870667607 + -2.550000000000013, + -3.1328718708048537 ], "tag": { "commentStart": 956, @@ -3805,8 +3805,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "upperRib" }, "to": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "type": "ToPoint", "units": "mm" @@ -3817,8 +3817,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.1100000000316324, - -3.132871870664735 + -3.109999999999987, + -3.1328718708048635 ], "tag": { "commentStart": 1094, @@ -3829,8 +3829,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "midWall" }, "to": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "type": "ToPoint", "units": "mm" @@ -3841,8 +3841,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.110000000044407, - -5.532871870673323 + -3.1099999999999617, + -5.532871870804853 ], "tag": { "commentStart": 1225, @@ -3853,8 +3853,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "taperFlank" }, "to": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "type": "ToPoint", "units": "mm" @@ -3865,8 +3865,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.1499999999653094, - -6.087128129162952 + -2.150000000000118, + -6.087128129195516 ], "tag": { "commentStart": 1361, @@ -3877,8 +3877,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerNeckWall" }, "to": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "type": "ToPoint", "units": "mm" @@ -3889,8 +3889,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.149999999978574, - -6.939999999919587 + -2.150000000000092, + -6.940000000000176 ], "tag": { "commentStart": 1506, @@ -3901,8 +3901,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerRib" }, "to": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "type": "ToPoint", "units": "mm" @@ -3913,8 +3913,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -2.749999999998471, - -6.939999999931075 + -2.7500000000000524, + -6.940000000000151 ], "tag": { "commentStart": 1644, @@ -3925,8 +3925,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "lowerBandWall" }, "to": [ - -2.7500000000117355, - -8.099999999942563 + -2.750000000000026, + -8.100000000000126 ], "type": "ToPoint", "units": "mm" @@ -3937,8 +3937,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -3.150000000025, - 0.00000000004594993807505346 + -3.15, + -0.00000000000010075004870403091 ], "tag": { "commentStart": 1786, @@ -3949,8 +3949,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "topBridge" }, "to": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "type": "ToPoint", "units": "mm" @@ -3961,8 +3961,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.555000000075, - 0.00000000004020619577220696 + -1.5550000000000002, + -0.00000000000008815618544209148 ], "tag": { "commentStart": 1867, @@ -3973,8 +3973,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "innerWall" }, "to": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "type": "ToPoint", "units": "mm" @@ -3985,8 +3985,8 @@ description: Variables in memory after executing m4-insert.kcl "sourceRange": [] }, "from": [ - -1.55500000008, - -8.099999999959794 + -1.5550000000000002, + -8.100000000000088 ], "tag": { "commentStart": 1998, @@ -3997,8 +3997,8 @@ description: Variables in memory after executing m4-insert.kcl "value": "bottomBridge" }, "to": [ - -2.7500000000183675, - -8.099999999948306 + -2.7500000000000133, + -8.100000000000113 ], "type": "ToPoint", "units": "mm" @@ -4037,12 +4037,12 @@ description: Variables in memory after executing m4-insert.kcl }, "start": { "from": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "to": [ - -3.150000000025, - 0.00000000005169368042384991 + -3.15, + -0.00000000000011334396960489123 ], "units": "mm", "tag": null, diff --git a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_commands.snap index 6b3cab501d4..6872ab68e67 100644 --- a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_commands.snap @@ -156,8 +156,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 115.34590322619881, - "y": 66.19074818599579, + "x": 115.34590297600542, + "y": 66.1907481173565, "z": 0.0 } } @@ -171,17 +171,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": 112.65791573450548, - "y": 75.9887236526364 + "x": 112.65791573450852, + "y": 75.98872365263455 }, - "radius": 10.160000000019254, + "radius": 10.160000000017579, "start": { "unit": "radians", - "value": -1.3030427812994652 + "value": -1.303042806834945 }, "end": { "unit": "radians", - "value": 4.980142525880121 + "value": 4.980142500344641 }, "relative": false } @@ -194,8 +194,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 76.20297032727467, - "y": 102.50017492452574, + "x": 76.20297037705954, + "y": 102.50017492556024, "z": 0.0 } } @@ -209,17 +209,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": 75.98872365264373, - "y": 112.6579157345016 + "x": 75.98872365264447, + "y": 112.65791573450264 }, - "radius": 10.160000000011774, + "radius": 10.160000000028354, "start": { "unit": "radians", - "value": -1.5497074925336563 + "value": -1.5497074876325871 }, "end": { "unit": "radians", - "value": 4.73347781464593 + "value": 4.733477819546999 }, "relative": false } @@ -232,8 +232,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -66.11724957707733, - "y": 110.25383595711216, + "x": -66.11724961616123, + "y": 110.25383579661144, "z": 0.0 } } @@ -247,17 +247,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": -75.98872365263058, - "y": 112.65791573450096 + "x": -75.98872365262976, + "y": 112.65791573450315 }, - "radius": 10.160000000018194, + "radius": 10.16000000002193, "start": { "unit": "radians", - "value": -0.23888766393254873 + "value": -0.23888768019172335 }, "end": { "unit": "radians", - "value": 6.044297643247037 + "value": 6.044297626987863 }, "relative": false } @@ -270,8 +270,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -109.71905003965142, - "y": 66.26305306248888, + "x": -109.71904990363062, + "y": 66.26305310358617, "z": 0.0 } } @@ -285,17 +285,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": -112.65791573449367, - "y": 75.98872365263567 + "x": -112.65791573449577, + "y": 75.98872365263496 }, - "radius": 10.160000000018044, + "radius": 10.16000000002271, "start": { "unit": "radians", - "value": -1.2773442621485338 + "value": -1.2773442481627078 }, "end": { "unit": "radians", - "value": 5.005841045031053 + "value": 5.005841059016879 }, "relative": false } @@ -308,8 +308,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -109.23482524495223, - "y": -85.55470773692953, + "x": -109.23482559113862, + "y": -85.55470786081092, "z": 0.0 } } @@ -323,17 +323,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": -112.6579157344919, - "y": -75.98872365264337 + "x": -112.65791573449113, + "y": -75.98872365264697 }, - "radius": 10.160000000019329, + "radius": 10.160000000017689, "start": { "unit": "radians", - "value": -1.2271543587235647 + "value": -1.2271543949128976 }, "end": { "unit": "radians", - "value": 5.056030948456021 + "value": 5.056030912266689 }, "relative": false } @@ -346,8 +346,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": -66.74217988942823, - "y": -116.8682635153567, + "x": -66.74217974475924, + "y": -116.86826319764936, "z": 0.0 } } @@ -361,17 +361,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": -75.98872365262382, - "y": -112.65791573450744 + "x": -75.98872365262073, + "y": -112.65791573451087 }, - "radius": 10.160000000019377, + "radius": 10.160000000018066, "start": { "unit": "radians", - "value": -0.42728816682888987 + "value": -0.427288132468999 }, "end": { "unit": "radians", - "value": 5.855897140350696 + "value": 5.855897174710587 }, "relative": false } @@ -384,8 +384,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 85.02043020861142, - "y": -117.31128834879816, + "x": 85.02043017122914, + "y": -117.3112884213694, "z": 0.0 } } @@ -399,17 +399,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": 75.98872365265449, - "y": -112.65791573450633 + "x": 75.98872365265586, + "y": -112.65791573450672 }, - "radius": 10.16000000001755, + "radius": 10.160000000023544, "start": { "unit": "radians", - "value": -0.47575430570272675 + "value": -0.4757543137375426 }, "end": { "unit": "radians", - "value": 5.80743100147686 + "value": 5.807430993442043 }, "relative": false } @@ -422,8 +422,8 @@ description: Artifact commands multi-axis-robot.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 116.59137245076384, - "y": -85.35640843928084, + "x": 116.59137250688771, + "y": -85.35640841572491, "z": 0.0 } } @@ -437,17 +437,17 @@ description: Artifact commands multi-axis-robot.kcl "segment": { "type": "arc", "center": { - "x": 112.6579157345182, - "y": -75.98872365264425 + "x": 112.65791573451894, + "y": -75.98872365264583 }, - "radius": 10.160000000017753, + "radius": 10.160000000025482, "start": { "unit": "radians", - "value": -1.173256440295038 + "value": -1.1732564343042153 }, "end": { "unit": "radians", - "value": 5.109928866884548 + "value": 5.109928872875371 }, "relative": false } diff --git a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_graph_flowchart.snap.md index 22e49446d5c..53376debfbd 100644 --- a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/artifact_graph_flowchart.snap.md @@ -668,55 +668,55 @@ flowchart LR %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 30 }, ExpressionStatementExpr] 339["SketchBlockConstraint Horizontal
[2196, 2214, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 31 }, ExpressionStatementExpr] - 340["SketchBlockConstraint Angle
[2217, 2245, 1]"] + 340["SketchBlockConstraint Angle
[2217, 2274, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 32 }, ExpressionStatementExpr] - 341["SketchBlockConstraint Coincident
[2342, 2381, 1]"] + 341["SketchBlockConstraint Coincident
[2371, 2410, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 34 }, ExpressionStatementExpr] - 342["SketchBlockConstraint Vertical
[2384, 2414, 1]"] + 342["SketchBlockConstraint Vertical
[2413, 2443, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 35 }, ExpressionStatementExpr] - 343["SketchBlockConstraint Coincident
[2512, 2552, 1]"] + 343["SketchBlockConstraint Coincident
[2541, 2581, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 37 }, ExpressionStatementExpr] - 344["SketchBlockConstraint Vertical
[2555, 2585, 1]"] + 344["SketchBlockConstraint Vertical
[2584, 2614, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 38 }, ExpressionStatementExpr] - 345["SketchBlockConstraint Vertical
[2588, 2604, 1]"] + 345["SketchBlockConstraint Vertical
[2617, 2633, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 39 }, ExpressionStatementExpr] - 346["SketchBlockConstraint Vertical
[2607, 2623, 1]"] + 346["SketchBlockConstraint Vertical
[2636, 2652, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 40 }, ExpressionStatementExpr] - 347["SketchBlockConstraint Angle
[2626, 2654, 1]"] + 347["SketchBlockConstraint Angle
[2655, 2712, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 41 }, ExpressionStatementExpr] - 348["SketchBlockConstraint Angle
[2657, 2685, 1]"] + 348["SketchBlockConstraint Angle
[2715, 2772, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 42 }, ExpressionStatementExpr] - 349["SketchBlockConstraint Angle
[2688, 2716, 1]"] + 349["SketchBlockConstraint Angle
[2775, 2832, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 43 }, ExpressionStatementExpr] - 350["SketchBlockConstraint Angle
[2719, 2747, 1]"] + 350["SketchBlockConstraint Angle
[2835, 2892, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 44 }, ExpressionStatementExpr] - 351["SketchBlockConstraint Angle
[2750, 2779, 1]"] + 351["SketchBlockConstraint Angle
[2895, 2953, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 45 }, ExpressionStatementExpr] - 352["SketchBlockConstraint Angle
[2782, 2811, 1]"] + 352["SketchBlockConstraint Angle
[2956, 3014, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 46 }, ExpressionStatementExpr] - 353["SketchBlockConstraint Angle
[2814, 2843, 1]"] + 353["SketchBlockConstraint Angle
[3017, 3075, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 47 }, ExpressionStatementExpr] - 354["SketchBlockConstraint Distance
[2846, 2890, 1]"] + 354["SketchBlockConstraint Distance
[3078, 3122, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 48 }, ExpressionStatementExpr] - 355["SketchBlockConstraint Coincident
[2981, 3020, 1]"] + 355["SketchBlockConstraint Coincident
[3213, 3252, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 50 }, ExpressionStatementExpr] - 356["SketchBlockConstraint Coincident
[3108, 3147, 1]"] + 356["SketchBlockConstraint Coincident
[3340, 3379, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 52 }, ExpressionStatementExpr] - 357["SketchBlockConstraint Coincident
[3239, 3278, 1]"] + 357["SketchBlockConstraint Coincident
[3471, 3510, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 54 }, ExpressionStatementExpr] - 358["SketchBlockConstraint Coincident
[3371, 3410, 1]"] + 358["SketchBlockConstraint Coincident
[3603, 3642, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 56 }, ExpressionStatementExpr] - 359["SketchBlockConstraint Coincident
[3504, 3543, 1]"] + 359["SketchBlockConstraint Coincident
[3736, 3775, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 58 }, ExpressionStatementExpr] - 360["SketchBlockConstraint Coincident
[3637, 3677, 1]"] + 360["SketchBlockConstraint Coincident
[3869, 3909, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 60 }, ExpressionStatementExpr] - 361["SketchBlockConstraint Coincident
[3770, 3810, 1]"] + 361["SketchBlockConstraint Coincident
[4002, 4042, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 62 }, ExpressionStatementExpr] - 362["SketchBlockConstraint Coincident
[3903, 3943, 1]"] + 362["SketchBlockConstraint Coincident
[4135, 4175, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 64 }, ExpressionStatementExpr] - 363["SketchBlockConstraint EqualRadius
[3946, 4067, 1]"] + 363["SketchBlockConstraint EqualRadius
[4178, 4299, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 65 }, ExpressionStatementExpr] - 364["SketchBlockConstraint Radius
[4070, 4091, 1]"] + 364["SketchBlockConstraint Radius
[4302, 4323, 1]"] %% [ProgramBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 66 }, ExpressionStatementExpr] 365["StartSketchOnFace
[289, 332, 0]"] %% [ProgramBodyItem { index: 0 }] diff --git a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap index 5c0e4360413..38570900a01 100644 --- a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap @@ -3202,22 +3202,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -3725,22 +3738,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -3772,22 +3798,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -3819,22 +3858,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -3866,22 +3918,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -3913,22 +3978,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -3960,22 +4038,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -4007,22 +4098,35 @@ description: Operations executed multi-axis-robot.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_commands.snap index c85bd018a2e..5f42d343b18 100644 --- a/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_commands.snap @@ -763,8 +763,8 @@ description: Artifact commands wheel-hub.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 38.10000000000015, - "y": -19.049999999999958, + "x": 38.10000000000007, + "y": -19.049999999999198, "z": 0.0 } } @@ -785,8 +785,8 @@ description: Artifact commands wheel-hub.kcl "segment": { "type": "line", "end": { - "x": 75.62117538976531, - "y": -12.434004430889896, + "x": 75.62117538977138, + "y": -12.434004430889582, "z": 0.0 }, "relative": false @@ -802,8 +802,8 @@ description: Artifact commands wheel-hub.kcl "segment": { "type": "line", "end": { - "x": 75.62117538976536, - "y": -126.73400443088988, + "x": 75.62117538977141, + "y": -126.73400443088937, "z": 0.0 }, "relative": false @@ -819,8 +819,8 @@ description: Artifact commands wheel-hub.kcl "segment": { "type": "line", "end": { - "x": 38.10000000000015, - "y": -126.73400443088987, + "x": 38.10000000000007, + "y": -126.73400443088926, "z": 0.0 }, "relative": false @@ -836,8 +836,8 @@ description: Artifact commands wheel-hub.kcl "segment": { "type": "line", "end": { - "x": 38.10000000000015, - "y": -19.049999999999958, + "x": 38.10000000000007, + "y": -19.049999999999198, "z": 0.0 }, "relative": false diff --git a/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_graph_flowchart.snap.md index fa7751f5732..afd472ff82c 100644 --- a/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/wheel-hub/artifact_graph_flowchart.snap.md @@ -57,7 +57,7 @@ flowchart LR %% [ProgramBodyItem { index: 28 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path62 [Path] - 62["Path
[5140, 6490, 0]
Consumed: false"] + 62["Path
[5140, 6554, 0]
Consumed: false"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit] 63["Segment
[5385, 5456, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] @@ -69,85 +69,85 @@ flowchart LR %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path67 [Path] - 67["Path Region
[6505, 6562, 0]
Consumed: true"] + 67["Path Region
[6569, 6626, 0]
Consumed: true"] %% [ProgramBodyItem { index: 34 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 68["Segment
[6505, 6562, 0]"] + 68["Segment
[6569, 6626, 0]"] %% [ProgramBodyItem { index: 34 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 69["Segment
[6505, 6562, 0]"] + 69["Segment
[6569, 6626, 0]"] %% [ProgramBodyItem { index: 34 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 70["Segment
[6505, 6562, 0]"] + 70["Segment
[6569, 6626, 0]"] %% [ProgramBodyItem { index: 34 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 71["Segment
[6505, 6562, 0]"] + 71["Segment
[6569, 6626, 0]"] %% [ProgramBodyItem { index: 34 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path83 [Path] - 83["Path
[6889, 8031, 0]
Consumed: false"] + 83["Path
[6953, 8095, 0]
Consumed: false"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 84["Segment
[7141, 7204, 0]"] + 84["Segment
[7205, 7268, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 85["Segment
[7226, 7291, 0]"] + 85["Segment
[7290, 7355, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path86 [Path] - 86["Path Region
[8056, 8116, 0]
Consumed: true"] + 86["Path Region
[8120, 8180, 0]
Consumed: true"] %% [ProgramBodyItem { index: 42 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 87["Segment
[8056, 8116, 0]"] + 87["Segment
[8120, 8180, 0]"] %% [ProgramBodyItem { index: 42 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path94 [Path] - 94["Path
[8300, 9037, 0]
Consumed: false"] + 94["Path
[8364, 9101, 0]
Consumed: false"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 95["Segment
[8540, 8609, 0]"] + 95["Segment
[8604, 8673, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path96 [Path] - 96["Path Region
[9058, 9104, 0]
Consumed: true"] + 96["Path Region
[9122, 9168, 0]
Consumed: true"] %% [ProgramBodyItem { index: 46 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 97["Segment
[9058, 9104, 0]"] + 97["Segment
[9122, 9168, 0]"] %% [ProgramBodyItem { index: 46 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path108 [Path] - 108["Path
[9843, 11900, 0]
Consumed: false"] + 108["Path
[9907, 11964, 0]
Consumed: false"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 109["Segment
[10125, 10194, 0]"] + 109["Segment
[10189, 10258, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 110["Segment
[10205, 10277, 0]"] + 110["Segment
[10269, 10341, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 111["Segment
[10328, 10397, 0]"] + 111["Segment
[10392, 10461, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 112["Segment
[10448, 10518, 0]"] + 112["Segment
[10512, 10582, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 113["Segment
[10569, 10643, 0]"] + 113["Segment
[10633, 10707, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 114["Segment
[10694, 10764, 0]"] + 114["Segment
[10758, 10828, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path115 [Path] - 115["Path Region
[11919, 11981, 0]
Consumed: true"] + 115["Path Region
[11983, 12045, 0]
Consumed: true"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 116["Segment
[11919, 11981, 0]"] + 116["Segment
[11983, 12045, 0]"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 117["Segment
[11919, 11981, 0]"] + 117["Segment
[11983, 12045, 0]"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 118["Segment
[11919, 11981, 0]"] + 118["Segment
[11983, 12045, 0]"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 119["Segment
[11919, 11981, 0]"] + 119["Segment
[11983, 12045, 0]"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 120["Segment
[11919, 11981, 0]"] + 120["Segment
[11983, 12045, 0]"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 121["Segment
[11919, 11981, 0]"] + 121["Segment
[11983, 12045, 0]"] %% [ProgramBodyItem { index: 54 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path143 [Path] - 143["Path
[12132, 12904, 0]
Consumed: false"] + 143["Path
[12196, 12968, 0]
Consumed: false"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 144["Segment
[12398, 12467, 0]"] + 144["Segment
[12462, 12531, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path145 [Path] - 145["Path Region
[12923, 12967, 0]
Consumed: true"] + 145["Path Region
[12987, 13031, 0]
Consumed: true"] %% [ProgramBodyItem { index: 58 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 146["Segment
[12923, 12967, 0]"] + 146["Segment
[12987, 13031, 0]"] %% [ProgramBodyItem { index: 58 }, VariableDeclarationDeclaration, VariableDeclarationInit] end 1["Plane
[920, 3177, 0]"] @@ -210,9 +210,9 @@ flowchart LR %% [ProgramBodyItem { index: 30 }, VariableDeclarationDeclaration, VariableDeclarationInit] 60["CompositeSolid Subtract
[5009, 5074, 0]
Consumed: true"] %% [ProgramBodyItem { index: 32 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 61["Plane
[5140, 6490, 0]"] + 61["Plane
[5140, 6554, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 72["Sweep Revolve
[6577, 6606, 0]
Consumed: true"] + 72["Sweep Revolve
[6641, 6670, 0]
Consumed: true"] %% [ProgramBodyItem { index: 35 }, VariableDeclarationDeclaration, VariableDeclarationInit] 73[Wall] %% face_code_ref=Missing NodePath @@ -226,11 +226,11 @@ flowchart LR 78["SweepEdge Adjacent"] 79["SweepEdge Adjacent"] 80["SweepEdge Adjacent"] - 81["CompositeSolid Subtract
[6621, 6667, 0]
Consumed: false"] + 81["CompositeSolid Subtract
[6685, 6731, 0]
Consumed: false"] %% [ProgramBodyItem { index: 36 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 82["Plane
[6701, 6745, 0]"] + 82["Plane
[6765, 6809, 0]"] %% [ProgramBodyItem { index: 38 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 88["Sweep Extrusion
[8139, 8250, 0]
Consumed: true"] + 88["Sweep Extrusion
[8203, 8314, 0]
Consumed: true"] %% [ProgramBodyItem { index: 43 }, VariableDeclarationDeclaration, VariableDeclarationInit] 89[Wall] %% face_code_ref=Missing NodePath @@ -240,7 +240,7 @@ flowchart LR %% face_code_ref=Missing NodePath 92["SweepEdge Opposite"] 93["SweepEdge Adjacent"] - 98["Sweep Extrusion
[9124, 9174, 0]
Consumed: true"] + 98["Sweep Extrusion
[9188, 9238, 0]
Consumed: true"] %% [ProgramBodyItem { index: 47 }, VariableDeclarationDeclaration, VariableDeclarationInit] 99[Wall] %% face_code_ref=Missing NodePath @@ -250,15 +250,15 @@ flowchart LR %% face_code_ref=Missing NodePath 102["SweepEdge Opposite"] 103["SweepEdge Adjacent"] - 104["Pattern Circular
[9195, 9297, 0]
Copies: 9
Faces: 27
Edges: 27"] + 104["Pattern Circular
[9259, 9361, 0]
Copies: 9
Faces: 27
Edges: 27"] %% [ProgramBodyItem { index: 48 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 105["EdgeCut Chamfer
[9384, 9543, 0]"] + 105["EdgeCut Chamfer
[9448, 9607, 0]"] %% [ProgramBodyItem { index: 50 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 106["EdgeCut Chamfer
[9557, 9705, 0]"] + 106["EdgeCut Chamfer
[9621, 9769, 0]"] %% [ProgramBodyItem { index: 51 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 107["CompositeSolid Subtract
[9723, 9774, 0]
Consumed: false"] + 107["CompositeSolid Subtract
[9787, 9838, 0]
Consumed: false"] %% [ProgramBodyItem { index: 52 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 122["Sweep Extrusion
[11993, 12055, 0]
Consumed: false"] + 122["Sweep Extrusion
[12057, 12119, 0]
Consumed: false"] %% [ProgramBodyItem { index: 55 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }] 123[Wall] %% face_code_ref=Missing NodePath @@ -288,7 +288,7 @@ flowchart LR 140["SweepEdge Adjacent"] 141["SweepEdge Opposite"] 142["SweepEdge Adjacent"] - 147["Sweep Extrusion
[12979, 13039, 0]
Consumed: false"] + 147["Sweep Extrusion
[13043, 13103, 0]
Consumed: false"] %% [ProgramBodyItem { index: 59 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }] 148[Wall] %% face_code_ref=Missing NodePath @@ -296,7 +296,7 @@ flowchart LR %% face_code_ref=Missing NodePath 150["SweepEdge Opposite"] 151["SweepEdge Adjacent"] - 152["Pattern Circular
[13045, 13114, 0]
Copies: 4
Faces: 40
Edges: 84"] + 152["Pattern Circular
[13109, 13178, 0]
Copies: 4
Faces: 40
Edges: 84"] %% [ProgramBodyItem { index: 59 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }] 153["SketchBlock
[920, 3177, 0]"] %% [ProgramBodyItem { index: 19 }, VariableDeclarationDeclaration, VariableDeclarationInit] @@ -390,7 +390,7 @@ flowchart LR %% [ProgramBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] 198["SketchBlockConstraint Radius
[4695, 4735, 0]"] %% [ProgramBodyItem { index: 27 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] - 199["SketchBlock
[5140, 6490, 0]"] + 199["SketchBlock
[5140, 6554, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit] 200["SketchBlockConstraint Coincident
[5706, 5750, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] @@ -422,129 +422,129 @@ flowchart LR %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 19 }, ExpressionStatementExpr] 214["SketchBlockConstraint Distance
[6335, 6387, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 20 }, ExpressionStatementExpr] - 215["SketchBlockConstraint Angle
[6390, 6431, 0]"] + 215["SketchBlockConstraint Angle
[6390, 6495, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 21 }, ExpressionStatementExpr] - 216["SketchBlockConstraint Distance
[6434, 6488, 0]"] + 216["SketchBlockConstraint Distance
[6498, 6552, 0]"] %% [ProgramBodyItem { index: 33 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 22 }, ExpressionStatementExpr] - 217["SketchBlock
[6889, 8031, 0]"] + 217["SketchBlock
[6953, 8095, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 218["SketchBlockConstraint Coincident
[7295, 7339, 0]"] + 218["SketchBlockConstraint Coincident
[7359, 7403, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 219["SketchBlockConstraint Coincident
[7342, 7410, 0]"] + 219["SketchBlockConstraint Coincident
[7406, 7474, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] - 220["SketchBlockConstraint Coincident
[7413, 7478, 0]"] + 220["SketchBlockConstraint Coincident
[7477, 7542, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] - 221["SketchBlockConstraint Coincident
[7482, 7531, 0]"] + 221["SketchBlockConstraint Coincident
[7546, 7595, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] - 222["SketchBlockConstraint Coincident
[7534, 7612, 0]"] + 222["SketchBlockConstraint Coincident
[7598, 7676, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 8 }, ExpressionStatementExpr] - 223["SketchBlockConstraint Coincident
[7615, 7690, 0]"] + 223["SketchBlockConstraint Coincident
[7679, 7754, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, ExpressionStatementExpr] - 224["SketchBlockConstraint Horizontal
[7694, 7722, 0]"] + 224["SketchBlockConstraint Horizontal
[7758, 7786, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] - 225["SketchBlockConstraint Horizontal
[7725, 7758, 0]"] + 225["SketchBlockConstraint Horizontal
[7789, 7822, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] - 226["SketchBlockConstraint Distance
[7761, 7844, 0]"] + 226["SketchBlockConstraint Distance
[7825, 7908, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 12 }, ExpressionStatementExpr] - 227["SketchBlockConstraint Distance
[7847, 7939, 0]"] + 227["SketchBlockConstraint Distance
[7911, 8003, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 13 }, ExpressionStatementExpr] - 228["SketchBlockConstraint Radius
[7942, 7982, 0]"] + 228["SketchBlockConstraint Radius
[8006, 8046, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 14 }, ExpressionStatementExpr] - 229["SketchBlockConstraint Radius
[7985, 8029, 0]"] + 229["SketchBlockConstraint Radius
[8049, 8093, 0]"] %% [ProgramBodyItem { index: 41 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 15 }, ExpressionStatementExpr] - 230["SketchBlock
[8300, 9037, 0]"] + 230["SketchBlock
[8364, 9101, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 231["SketchBlockConstraint Coincident
[8613, 8652, 0]"] + 231["SketchBlockConstraint Coincident
[8677, 8716, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 232["SketchBlockConstraint Coincident
[8655, 8700, 0]"] + 232["SketchBlockConstraint Coincident
[8719, 8764, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 233["SketchBlockConstraint Coincident
[8703, 8750, 0]"] + 233["SketchBlockConstraint Coincident
[8767, 8814, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] - 234["SketchBlockConstraint Coincident
[8753, 8797, 0]"] + 234["SketchBlockConstraint Coincident
[8817, 8861, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] - 235["SketchBlockConstraint Horizontal
[8801, 8824, 0]"] + 235["SketchBlockConstraint Horizontal
[8865, 8888, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] - 236["SketchBlockConstraint Horizontal
[8827, 8850, 0]"] + 236["SketchBlockConstraint Horizontal
[8891, 8914, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 8 }, ExpressionStatementExpr] - 237["SketchBlockConstraint Distance
[8853, 8918, 0]"] + 237["SketchBlockConstraint Distance
[8917, 8982, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, ExpressionStatementExpr] - 238["SketchBlockConstraint Distance
[8921, 8992, 0]"] + 238["SketchBlockConstraint Distance
[8985, 9056, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] - 239["SketchBlockConstraint Radius
[8995, 9035, 0]"] + 239["SketchBlockConstraint Radius
[9059, 9099, 0]"] %% [ProgramBodyItem { index: 45 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] - 240["StartSketchOnFace
[9855, 9898, 0]"] + 240["StartSketchOnFace
[9919, 9962, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockArgs] - 241["SketchBlock
[9843, 11900, 0]"] + 241["SketchBlock
[9907, 11964, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 242["SketchBlockConstraint Coincident
[10280, 10316, 0]"] + 242["SketchBlockConstraint Coincident
[10344, 10380, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 243["SketchBlockConstraint Coincident
[10400, 10436, 0]"] + 243["SketchBlockConstraint Coincident
[10464, 10500, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] - 244["SketchBlockConstraint Coincident
[10521, 10557, 0]"] + 244["SketchBlockConstraint Coincident
[10585, 10621, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 8 }, ExpressionStatementExpr] - 245["SketchBlockConstraint Coincident
[10646, 10682, 0]"] + 245["SketchBlockConstraint Coincident
[10710, 10746, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] - 246["SketchBlockConstraint Coincident
[10767, 10803, 0]"] + 246["SketchBlockConstraint Coincident
[10831, 10867, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 12 }, ExpressionStatementExpr] - 247["SketchBlockConstraint Coincident
[10806, 10842, 0]"] + 247["SketchBlockConstraint Coincident
[10870, 10906, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 13 }, ExpressionStatementExpr] - 248["SketchBlockConstraint Coincident
[10846, 10885, 0]"] + 248["SketchBlockConstraint Coincident
[10910, 10949, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 14 }, ExpressionStatementExpr] - 249["SketchBlockConstraint Coincident
[10888, 10940, 0]"] + 249["SketchBlockConstraint Coincident
[10952, 11004, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 15 }, ExpressionStatementExpr] - 250["SketchBlockConstraint Coincident
[10944, 10985, 0]"] + 250["SketchBlockConstraint Coincident
[11008, 11049, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 16 }, ExpressionStatementExpr] - 251["SketchBlockConstraint Coincident
[10988, 11029, 0]"] + 251["SketchBlockConstraint Coincident
[11052, 11093, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 17 }, ExpressionStatementExpr] - 252["SketchBlockConstraint Coincident
[11032, 11073, 0]"] + 252["SketchBlockConstraint Coincident
[11096, 11137, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 18 }, ExpressionStatementExpr] - 253["SketchBlockConstraint Coincident
[11076, 11117, 0]"] + 253["SketchBlockConstraint Coincident
[11140, 11181, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 19 }, ExpressionStatementExpr] - 254["SketchBlockConstraint Coincident
[11120, 11161, 0]"] + 254["SketchBlockConstraint Coincident
[11184, 11225, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 20 }, ExpressionStatementExpr] - 255["SketchBlockConstraint Coincident
[11164, 11205, 0]"] + 255["SketchBlockConstraint Coincident
[11228, 11269, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 21 }, ExpressionStatementExpr] - 256["SketchBlockConstraint Horizontal
[11209, 11232, 0]"] + 256["SketchBlockConstraint Horizontal
[11273, 11296, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 22 }, ExpressionStatementExpr] - 257["SketchBlockConstraint Horizontal
[11235, 11252, 0]"] + 257["SketchBlockConstraint Horizontal
[11299, 11316, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 23 }, ExpressionStatementExpr] - 258["SketchBlockConstraint Horizontal
[11255, 11272, 0]"] + 258["SketchBlockConstraint Horizontal
[11319, 11336, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 24 }, ExpressionStatementExpr] - 259["SketchBlockConstraint LinesEqualLength
[11276, 11359, 0]"] + 259["SketchBlockConstraint LinesEqualLength
[11340, 11423, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 25 }, ExpressionStatementExpr] - 260["SketchBlockConstraint Coincident
[11475, 11549, 0]"] + 260["SketchBlockConstraint Coincident
[11539, 11613, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 27 }, ExpressionStatementExpr] - 261["SketchBlockConstraint Coincident
[11552, 11602, 0]"] + 261["SketchBlockConstraint Coincident
[11616, 11666, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 28 }, ExpressionStatementExpr] - 262["SketchBlockConstraint Coincident
[11605, 11676, 0]"] + 262["SketchBlockConstraint Coincident
[11669, 11740, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 29 }, ExpressionStatementExpr] - 263["SketchBlockConstraint Horizontal
[11680, 11711, 0]"] + 263["SketchBlockConstraint Horizontal
[11744, 11775, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 30 }, ExpressionStatementExpr] - 264["SketchBlockConstraint HorizontalDistance
[11714, 11789, 0]"] + 264["SketchBlockConstraint HorizontalDistance
[11778, 11853, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 31 }, ExpressionStatementExpr] - 265["SketchBlockConstraint HorizontalDistance
[11792, 11898, 0]"] + 265["SketchBlockConstraint HorizontalDistance
[11856, 11962, 0]"] %% [ProgramBodyItem { index: 53 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 32 }, ExpressionStatementExpr] - 266["StartSketchOnFace
[12144, 12181, 0]"] + 266["StartSketchOnFace
[12208, 12245, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockArgs] - 267["SketchBlock
[12132, 12904, 0]"] + 267["SketchBlock
[12196, 12968, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 268["SketchBlockConstraint Coincident
[12471, 12510, 0]"] + 268["SketchBlockConstraint Coincident
[12535, 12574, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 3 }, ExpressionStatementExpr] - 269["SketchBlockConstraint Coincident
[12513, 12558, 0]"] + 269["SketchBlockConstraint Coincident
[12577, 12622, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] - 270["SketchBlockConstraint Coincident
[12561, 12608, 0]"] + 270["SketchBlockConstraint Coincident
[12625, 12672, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 5 }, ExpressionStatementExpr] - 271["SketchBlockConstraint Coincident
[12611, 12655, 0]"] + 271["SketchBlockConstraint Coincident
[12675, 12719, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 6 }, ExpressionStatementExpr] - 272["SketchBlockConstraint Horizontal
[12659, 12682, 0]"] + 272["SketchBlockConstraint Horizontal
[12723, 12746, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 7 }, ExpressionStatementExpr] - 273["SketchBlockConstraint Horizontal
[12685, 12708, 0]"] + 273["SketchBlockConstraint Horizontal
[12749, 12772, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 8 }, ExpressionStatementExpr] - 274["SketchBlockConstraint HorizontalDistance
[12711, 12785, 0]"] + 274["SketchBlockConstraint HorizontalDistance
[12775, 12849, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 9 }, ExpressionStatementExpr] - 275["SketchBlockConstraint Distance
[12788, 12859, 0]"] + 275["SketchBlockConstraint Distance
[12852, 12923, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 10 }, ExpressionStatementExpr] - 276["SketchBlockConstraint Radius
[12862, 12902, 0]"] + 276["SketchBlockConstraint Radius
[12926, 12966, 0]"] %% [ProgramBodyItem { index: 57 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 11 }, ExpressionStatementExpr] 1 --- 2 1 <--x 9 diff --git a/rust/kcl-lib/tests/kcl_samples/wheel-hub/ast.snap b/rust/kcl-lib/tests/kcl_samples/wheel-hub/ast.snap index 0efad6625ea..d1750c86ba6 100644 --- a/rust/kcl-lib/tests/kcl_samples/wheel-hub/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/wheel-hub/ast.snap @@ -13167,7 +13167,145 @@ description: Result of parsing wheel-hub.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "startOffsetGuide", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "line1", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2.17in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.17, + "suffix": "Inch" + } + }, + { + "argument": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0.69in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.69, + "suffix": "Inch" + } + }, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "operator": "-", + "start": 0, + "type": "UnaryExpression", + "type": "UnaryExpression" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -13177,7 +13315,7 @@ description: Result of parsing wheel-hub.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -13191,52 +13329,7 @@ description: Result of parsing wheel-hub.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "startOffsetGuide", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "line1", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", diff --git a/rust/kcl-lib/tests/kcl_samples/wheel-hub/ops.snap b/rust/kcl-lib/tests/kcl_samples/wheel-hub/ops.snap index b7fa3aa738e..a230e1b0141 100644 --- a/rust/kcl-lib/tests/kcl_samples/wheel-hub/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/wheel-hub/ops.snap @@ -5718,22 +5718,61 @@ description: Operations executed wheel-hub.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 2.17, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": -0.69, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/wheel-hub/program_memory.snap b/rust/kcl-lib/tests/kcl_samples/wheel-hub/program_memory.snap index 59f972637d5..5e74c2f5130 100644 --- a/rust/kcl-lib/tests/kcl_samples/wheel-hub/program_memory.snap +++ b/rust/kcl-lib/tests/kcl_samples/wheel-hub/program_memory.snap @@ -285,10 +285,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 10117, - "end": 10122, + "commentStart": 10181, + "end": 10186, "moduleId": 0, - "start": 10117, + "start": 10181, "type": "TagDeclarator", "value": "line1" }, @@ -299,10 +299,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 10197, - "end": 10202, + "commentStart": 10261, + "end": 10266, "moduleId": 0, - "start": 10197, + "start": 10261, "type": "TagDeclarator", "value": "line2" }, @@ -313,10 +313,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 10320, - "end": 10325, + "commentStart": 10384, + "end": 10389, "moduleId": 0, - "start": 10320, + "start": 10384, "type": "TagDeclarator", "value": "line3" }, @@ -327,10 +327,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 10440, - "end": 10445, + "commentStart": 10504, + "end": 10509, "moduleId": 0, - "start": 10440, + "start": 10504, "type": "TagDeclarator", "value": "line4" }, @@ -341,10 +341,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 10561, - "end": 10566, + "commentStart": 10625, + "end": 10630, "moduleId": 0, - "start": 10561, + "start": 10625, "type": "TagDeclarator", "value": "line5" }, @@ -355,10 +355,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 10686, - "end": 10691, + "commentStart": 10750, + "end": 10755, "moduleId": 0, - "start": 10686, + "start": 10750, "type": "TagDeclarator", "value": "line6" }, @@ -380,10 +380,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.00000000000005416211904739693 ], "tag": { - "commentStart": 10117, - "end": 10122, + "commentStart": 10181, + "end": 10186, "moduleId": 0, - "start": 10117, + "start": 10181, "type": "TagDeclarator", "value": "line1" }, @@ -404,10 +404,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.37407621519391915 ], "tag": { - "commentStart": 10197, - "end": 10202, + "commentStart": 10261, + "end": 10266, "moduleId": 0, - "start": 10197, + "start": 10261, "type": "TagDeclarator", "value": "line2" }, @@ -428,10 +428,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.3740762151939048 ], "tag": { - "commentStart": 10320, - "end": 10325, + "commentStart": 10384, + "end": 10389, "moduleId": 0, - "start": 10320, + "start": 10384, "type": "TagDeclarator", "value": "line3" }, @@ -452,10 +452,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.0000000000000250277270112892 ], "tag": { - "commentStart": 10440, - "end": 10445, + "commentStart": 10504, + "end": 10509, "moduleId": 0, - "start": 10440, + "start": 10504, "type": "TagDeclarator", "value": "line4" }, @@ -476,10 +476,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.3740762151939279 ], "tag": { - "commentStart": 10561, - "end": 10566, + "commentStart": 10625, + "end": 10630, "moduleId": 0, - "start": 10561, + "start": 10625, "type": "TagDeclarator", "value": "line5" }, @@ -500,10 +500,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.37407621519389656 ], "tag": { - "commentStart": 10686, - "end": 10691, + "commentStart": 10750, + "end": 10755, "moduleId": 0, - "start": 10686, + "start": 10750, "type": "TagDeclarator", "value": "line6" }, @@ -1684,10 +1684,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.00000000000005416211904739693 ], "tag": { - "commentStart": 10117, - "end": 10122, + "commentStart": 10181, + "end": 10186, "moduleId": 0, - "start": 10117, + "start": 10181, "type": "TagDeclarator", "value": "line1" }, @@ -1708,10 +1708,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.37407621519391915 ], "tag": { - "commentStart": 10197, - "end": 10202, + "commentStart": 10261, + "end": 10266, "moduleId": 0, - "start": 10197, + "start": 10261, "type": "TagDeclarator", "value": "line2" }, @@ -1732,10 +1732,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.3740762151939048 ], "tag": { - "commentStart": 10320, - "end": 10325, + "commentStart": 10384, + "end": 10389, "moduleId": 0, - "start": 10320, + "start": 10384, "type": "TagDeclarator", "value": "line3" }, @@ -1756,10 +1756,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.0000000000000250277270112892 ], "tag": { - "commentStart": 10440, - "end": 10445, + "commentStart": 10504, + "end": 10509, "moduleId": 0, - "start": 10440, + "start": 10504, "type": "TagDeclarator", "value": "line4" }, @@ -1780,10 +1780,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.3740762151939279 ], "tag": { - "commentStart": 10561, - "end": 10566, + "commentStart": 10625, + "end": 10630, "moduleId": 0, - "start": 10561, + "start": 10625, "type": "TagDeclarator", "value": "line5" }, @@ -1804,10 +1804,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.37407621519389656 ], "tag": { - "commentStart": 10686, - "end": 10691, + "commentStart": 10750, + "end": 10755, "moduleId": 0, - "start": 10686, + "start": 10750, "type": "TagDeclarator", "value": "line6" }, @@ -1918,10 +1918,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.00000000000005416211904739693 ], "tag": { - "commentStart": 10117, - "end": 10122, + "commentStart": 10181, + "end": 10186, "moduleId": 0, - "start": 10117, + "start": 10181, "type": "TagDeclarator", "value": "line1" }, @@ -1942,10 +1942,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.37407621519391915 ], "tag": { - "commentStart": 10197, - "end": 10202, + "commentStart": 10261, + "end": 10266, "moduleId": 0, - "start": 10197, + "start": 10261, "type": "TagDeclarator", "value": "line2" }, @@ -1966,10 +1966,10 @@ description: Variables in memory after executing wheel-hub.kcl 0.3740762151939048 ], "tag": { - "commentStart": 10320, - "end": 10325, + "commentStart": 10384, + "end": 10389, "moduleId": 0, - "start": 10320, + "start": 10384, "type": "TagDeclarator", "value": "line3" }, @@ -1990,10 +1990,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.0000000000000250277270112892 ], "tag": { - "commentStart": 10440, - "end": 10445, + "commentStart": 10504, + "end": 10509, "moduleId": 0, - "start": 10440, + "start": 10504, "type": "TagDeclarator", "value": "line4" }, @@ -2014,10 +2014,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.3740762151939279 ], "tag": { - "commentStart": 10561, - "end": 10566, + "commentStart": 10625, + "end": 10630, "moduleId": 0, - "start": 10561, + "start": 10625, "type": "TagDeclarator", "value": "line5" }, @@ -2038,10 +2038,10 @@ description: Variables in memory after executing wheel-hub.kcl -0.37407621519389656 ], "tag": { - "commentStart": 10686, - "end": 10691, + "commentStart": 10750, + "end": 10755, "moduleId": 0, - "start": 10686, + "start": 10750, "type": "TagDeclarator", "value": "line6" }, @@ -2145,10 +2145,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2176,10 +2176,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2261,10 +2261,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2292,10 +2292,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2377,10 +2377,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2408,10 +2408,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2493,10 +2493,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2524,10 +2524,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2609,10 +2609,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2640,10 +2640,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -2972,10 +2972,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -3183,10 +3183,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 12388, - "end": 12395, + "commentStart": 12452, + "end": 12459, "moduleId": 0, - "start": 12388, + "start": 12452, "type": "TagDeclarator", "value": "circle1" }, @@ -3278,10 +3278,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -3292,10 +3292,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8212, - "end": 8224, + "commentStart": 8276, + "end": 8288, "moduleId": 0, - "start": 8212, + "start": 8276, "type": "TagDeclarator", "value": "capStart001" }, @@ -3306,10 +3306,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8237, - "end": 8247, + "commentStart": 8301, + "end": 8311, "moduleId": 0, - "start": 8237, + "start": 8301, "type": "TagDeclarator", "value": "capEnd001" }, @@ -3347,10 +3347,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 3.0, "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -3466,10 +3466,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -3480,10 +3480,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8212, - "end": 8224, + "commentStart": 8276, + "end": 8288, "moduleId": 0, - "start": 8212, + "start": 8276, "type": "TagDeclarator", "value": "capStart001" }, @@ -3494,10 +3494,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8237, - "end": 8247, + "commentStart": 8301, + "end": 8311, "moduleId": 0, - "start": 8237, + "start": 8301, "type": "TagDeclarator", "value": "capEnd001" }, @@ -3535,10 +3535,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 3.0, "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -3682,10 +3682,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -3713,10 +3713,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -3807,10 +3807,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -3838,10 +3838,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -3929,10 +3929,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -3960,10 +3960,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4051,10 +4051,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4082,10 +4082,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4173,10 +4173,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4204,10 +4204,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4295,10 +4295,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4326,10 +4326,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4417,10 +4417,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4448,10 +4448,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4539,10 +4539,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4570,10 +4570,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4661,10 +4661,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4692,10 +4692,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4783,10 +4783,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4814,10 +4814,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4905,10 +4905,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -4936,10 +4936,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -5286,10 +5286,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -5509,10 +5509,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 0.26996625421831055, "tag": { - "commentStart": 8530, - "end": 8537, + "commentStart": 8594, + "end": 8601, "moduleId": 0, - "start": 8530, + "start": 8594, "type": "TagDeclarator", "value": "circle1" }, @@ -7407,10 +7407,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -7421,10 +7421,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8212, - "end": 8224, + "commentStart": 8276, + "end": 8288, "moduleId": 0, - "start": 8212, + "start": 8276, "type": "TagDeclarator", "value": "capStart001" }, @@ -7435,10 +7435,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8237, - "end": 8247, + "commentStart": 8301, + "end": 8311, "moduleId": 0, - "start": 8237, + "start": 8301, "type": "TagDeclarator", "value": "capEnd001" }, @@ -7476,10 +7476,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 3.0, "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -7609,10 +7609,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -7623,10 +7623,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8212, - "end": 8224, + "commentStart": 8276, + "end": 8288, "moduleId": 0, - "start": 8212, + "start": 8276, "type": "TagDeclarator", "value": "capStart001" }, @@ -7637,10 +7637,10 @@ description: Variables in memory after executing wheel-hub.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8237, - "end": 8247, + "commentStart": 8301, + "end": 8311, "moduleId": 0, - "start": 8237, + "start": 8301, "type": "TagDeclarator", "value": "capEnd001" }, @@ -7678,10 +7678,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 3.0, "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -8038,10 +8038,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 3.0, "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -8085,10 +8085,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 1.5, "tag": { - "commentStart": 7207, - "end": 7223, + "commentStart": 7271, + "end": 7287, "moduleId": 0, - "start": 7207, + "start": 7271, "type": "TagDeclarator", "value": "centerBoreCircle" }, @@ -8432,10 +8432,10 @@ description: Variables in memory after executing wheel-hub.kcl ], "radius": 3.0, "tag": { - "commentStart": 7127, - "end": 7138, + "commentStart": 7191, + "end": 7202, "moduleId": 0, - "start": 7127, + "start": 7191, "type": "TagDeclarator", "value": "outerCircle" }, @@ -10963,8 +10963,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "tag": { "commentStart": 5377, @@ -10975,8 +10975,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line1" }, "to": [ - 2.9772116295183193, - -0.4895277334996022 + 2.9772116295185587, + -0.48952773349958983 ], "type": "ToPoint", "units": "in" @@ -10987,8 +10987,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 2.9772116295183193, - -0.4895277334996022 + 2.9772116295185587, + -0.48952773349958983 ], "tag": { "commentStart": 5459, @@ -10999,8 +10999,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line2" }, "to": [ - 2.977211629518321, - -4.989527733499602 + 2.9772116295185596, + -4.989527733499582 ], "type": "ToPoint", "units": "in" @@ -11011,8 +11011,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 2.977211629518321, - -4.989527733499602 + 2.9772116295185596, + -4.989527733499582 ], "tag": { "commentStart": 5542, @@ -11023,8 +11023,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line3" }, "to": [ - 1.500000000000006, - -4.989527733499601 + 1.5000000000000029, + -4.989527733499577 ], "type": "ToPoint", "units": "in" @@ -11035,8 +11035,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 1.500000000000006, - -4.989527733499601 + 1.5000000000000029, + -4.989527733499577 ], "tag": { "commentStart": 5624, @@ -11047,8 +11047,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line4" }, "to": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "type": "ToPoint", "units": "in" @@ -11087,12 +11087,12 @@ description: Variables in memory after executing wheel-hub.kcl }, "start": { "from": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "to": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "units": "in", "tag": null, @@ -11168,7 +11168,7 @@ description: Variables in memory after executing wheel-hub.kcl "line": { "start": [ { - "n": 1.500000000000006, + "n": 1.5000000000000029, "ty": { "in": null, "type": "Known", @@ -11176,7 +11176,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.7499999999999983, + "n": -0.7499999999999685, "ty": { "in": null, "type": "Known", @@ -11186,7 +11186,7 @@ description: Variables in memory after executing wheel-hub.kcl ], "end": [ { - "n": 2.9772116295183193, + "n": 2.9772116295185587, "ty": { "in": null, "type": "Known", @@ -11194,7 +11194,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.4895277334996022, + "n": -0.48952773349958983, "ty": { "in": null, "type": "Known", @@ -11288,7 +11288,7 @@ description: Variables in memory after executing wheel-hub.kcl "line": { "start": [ { - "n": 2.97721162951832, + "n": 2.977211629518559, "ty": { "in": null, "type": "Known", @@ -11296,7 +11296,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.48952773349960194, + "n": -0.48952773349958545, "ty": { "in": null, "type": "Known", @@ -11306,7 +11306,7 @@ description: Variables in memory after executing wheel-hub.kcl ], "end": [ { - "n": 2.977211629518321, + "n": 2.9772116295185596, "ty": { "in": null, "type": "Known", @@ -11314,7 +11314,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -4.989527733499602, + "n": -4.989527733499582, "ty": { "in": null, "type": "Known", @@ -11408,7 +11408,7 @@ description: Variables in memory after executing wheel-hub.kcl "line": { "start": [ { - "n": 2.977211629518321, + "n": 2.9772116295185596, "ty": { "in": null, "type": "Known", @@ -11416,7 +11416,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -4.989527733499601, + "n": -4.989527733499579, "ty": { "in": null, "type": "Known", @@ -11426,7 +11426,7 @@ description: Variables in memory after executing wheel-hub.kcl ], "end": [ { - "n": 1.500000000000006, + "n": 1.5000000000000029, "ty": { "in": null, "type": "Known", @@ -11434,7 +11434,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -4.989527733499601, + "n": -4.989527733499577, "ty": { "in": null, "type": "Known", @@ -11528,7 +11528,7 @@ description: Variables in memory after executing wheel-hub.kcl "line": { "start": [ { - "n": 1.500000000000006, + "n": 1.5000000000000029, "ty": { "in": null, "type": "Known", @@ -11536,7 +11536,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -4.989527733499601, + "n": -4.9895277334995765, "ty": { "in": null, "type": "Known", @@ -11546,7 +11546,7 @@ description: Variables in memory after executing wheel-hub.kcl ], "end": [ { - "n": 1.500000000000006, + "n": 1.5000000000000029, "ty": { "in": null, "type": "Known", @@ -11554,7 +11554,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.7499999999999983, + "n": -0.7499999999999685, "ty": { "in": null, "type": "Known", @@ -11651,8 +11651,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "tag": { "commentStart": 5377, @@ -11663,8 +11663,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line1" }, "to": [ - 2.9772116295183193, - -0.4895277334996022 + 2.9772116295185587, + -0.48952773349958983 ], "type": "ToPoint", "units": "in" @@ -11675,8 +11675,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 2.9772116295183193, - -0.4895277334996022 + 2.9772116295185587, + -0.48952773349958983 ], "tag": { "commentStart": 5459, @@ -11687,8 +11687,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line2" }, "to": [ - 2.977211629518321, - -4.989527733499602 + 2.9772116295185596, + -4.989527733499582 ], "type": "ToPoint", "units": "in" @@ -11699,8 +11699,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 2.977211629518321, - -4.989527733499602 + 2.9772116295185596, + -4.989527733499582 ], "tag": { "commentStart": 5542, @@ -11711,8 +11711,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line3" }, "to": [ - 1.500000000000006, - -4.989527733499601 + 1.5000000000000029, + -4.989527733499577 ], "type": "ToPoint", "units": "in" @@ -11723,8 +11723,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 1.500000000000006, - -4.989527733499601 + 1.5000000000000029, + -4.989527733499577 ], "tag": { "commentStart": 5624, @@ -11735,8 +11735,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line4" }, "to": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "type": "ToPoint", "units": "in" @@ -11775,12 +11775,12 @@ description: Variables in memory after executing wheel-hub.kcl }, "start": { "from": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "to": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "units": "in", "tag": null, @@ -11828,7 +11828,7 @@ description: Variables in memory after executing wheel-hub.kcl "line": { "start": [ { - "n": 0.0000000000000011797270560770102, + "n": 0.000000000000000597186770944707, "ty": { "in": null, "type": "Known", @@ -11836,7 +11836,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": 0.0000000000000003115995891563336, + "n": 0.000000000000005274899195679176, "ty": { "in": null, "type": "Known", @@ -11846,7 +11846,7 @@ description: Variables in memory after executing wheel-hub.kcl ], "end": [ { - "n": 0.0000000000000023594429610291178, + "n": 0.0000000000000011943623895980575, "ty": { "in": null, "type": "Known", @@ -11854,7 +11854,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.7499999999999994, + "n": -0.7499999999999895, "ty": { "in": null, "type": "Known", @@ -11949,7 +11949,7 @@ description: Variables in memory after executing wheel-hub.kcl "line": { "start": [ { - "n": 0.0000000000000035391365637330357, + "n": 0.000000000000001791515703671926, "ty": { "in": null, "type": "Known", @@ -11957,7 +11957,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.7499999999999991, + "n": -0.7499999999999841, "ty": { "in": null, "type": "Known", @@ -11967,7 +11967,7 @@ description: Variables in memory after executing wheel-hub.kcl ], "end": [ { - "n": 1.5000000000000049, + "n": 1.5000000000000022, "ty": { "in": null, "type": "Known", @@ -11975,7 +11975,7 @@ description: Variables in memory after executing wheel-hub.kcl } }, { - "n": -0.7499999999999987, + "n": -0.7499999999999738, "ty": { "in": null, "type": "Known", @@ -12073,8 +12073,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "tag": { "commentStart": 5377, @@ -12085,8 +12085,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line1" }, "to": [ - 2.9772116295183193, - -0.4895277334996022 + 2.9772116295185587, + -0.48952773349958983 ], "type": "ToPoint", "units": "in" @@ -12097,8 +12097,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 2.9772116295183193, - -0.4895277334996022 + 2.9772116295185587, + -0.48952773349958983 ], "tag": { "commentStart": 5459, @@ -12109,8 +12109,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line2" }, "to": [ - 2.977211629518321, - -4.989527733499602 + 2.9772116295185596, + -4.989527733499582 ], "type": "ToPoint", "units": "in" @@ -12121,8 +12121,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 2.977211629518321, - -4.989527733499602 + 2.9772116295185596, + -4.989527733499582 ], "tag": { "commentStart": 5542, @@ -12133,8 +12133,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line3" }, "to": [ - 1.500000000000006, - -4.989527733499601 + 1.5000000000000029, + -4.989527733499577 ], "type": "ToPoint", "units": "in" @@ -12145,8 +12145,8 @@ description: Variables in memory after executing wheel-hub.kcl "sourceRange": [] }, "from": [ - 1.500000000000006, - -4.989527733499601 + 1.5000000000000029, + -4.989527733499577 ], "tag": { "commentStart": 5624, @@ -12157,8 +12157,8 @@ description: Variables in memory after executing wheel-hub.kcl "value": "line4" }, "to": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "type": "ToPoint", "units": "in" @@ -12197,12 +12197,12 @@ description: Variables in memory after executing wheel-hub.kcl }, "start": { "from": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "to": [ - 1.500000000000006, - -0.7499999999999983 + 1.5000000000000029, + -0.7499999999999685 ], "units": "in", "tag": null, diff --git a/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_commands.snap b/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_commands.snap index 259a66c9f00..2d4e795572b 100644 --- a/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_commands.snap +++ b/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_commands.snap @@ -68,8 +68,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 0.6350000000354321, - "y": 0.6349999999857875, + "x": 0.635000000034589, + "y": 0.634999999987585, "z": 0.0 } } @@ -90,8 +90,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 0.6350000000494767, - "y": 4.191000081321146, + "x": 0.6350000000486336, + "y": 4.191000081322944, "z": 0.0 }, "relative": false @@ -107,8 +107,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 14.535228349241837, - "y": 19.303999999983247, + "x": 14.535228349240993, + "y": 19.303999999985038, "z": 0.0 }, "relative": false @@ -124,8 +124,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 0.6350000001011795, - "y": 19.303999999987678, + "x": 0.6350000001003364, + "y": 19.303999999989472, "z": 0.0 }, "relative": false @@ -141,8 +141,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 0.6350000001184138, - "y": 24.764999999993535, + "x": 0.6350000001175706, + "y": 24.76499999999533, "z": 0.0 }, "relative": false @@ -158,8 +158,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 15.875000000145844, - "y": 24.764999999998636, + "x": 15.875000000144999, + "y": 24.76500000000043, "z": 0.0 }, "relative": false @@ -175,8 +175,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 15.875000000180313, - "y": 20.760664377378166, + "x": 15.875000000179467, + "y": 20.760664377379957, "z": 0.0 }, "relative": false @@ -192,8 +192,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 19.55799999985375, - "y": 24.76500000006094, + "x": 19.55799999985291, + "y": 24.765000000062734, "z": 0.0 }, "relative": false @@ -209,8 +209,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 23.113999999885095, - "y": 24.76500000004688, + "x": 23.113999999884253, + "y": 24.76500000004867, "z": 0.0 }, "relative": false @@ -226,8 +226,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 23.113999999916437, - "y": 21.209000000047578, + "x": 23.113999999915595, + "y": 21.20900000004937, "z": 0.0 }, "relative": false @@ -243,8 +243,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 9.213771607806196, - "y": 6.095999999960672, + "x": 9.213771607805354, + "y": 6.095999999962471, "z": 0.0 }, "relative": false @@ -260,8 +260,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 23.113999999980265, - "y": 6.095999999959661, + "x": 23.113999999979423, + "y": 6.095999999961459, "z": 0.0 }, "relative": false @@ -277,8 +277,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 23.113999999996317, - "y": 0.6349999999554393, + "x": 23.113999999995475, + "y": 0.6349999999572371, "z": 0.0 }, "relative": false @@ -294,8 +294,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 7.874000000009209, - "y": 0.6349999999527153, + "x": 7.874000000008366, + "y": 0.634999999954513, "z": 0.0 }, "relative": false @@ -311,8 +311,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 7.8740000000232815, - "y": 4.639335622564266, + "x": 7.8740000000224395, + "y": 4.639335622566066, "z": 0.0 }, "relative": false @@ -328,8 +328,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 4.191000003981789, - "y": 0.634999999985507, + "x": 4.191000003980944, + "y": 0.6349999999873047, "z": 0.0 }, "relative": false @@ -345,8 +345,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 0.6350000000213875, - "y": 0.6349999999857875, + "x": 0.6350000000205444, + "y": 0.634999999987585, "z": 0.0 }, "relative": false @@ -360,8 +360,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 44.46834441715509, - "y": 22.807772169166427, + "x": 44.46834442196898, + "y": 22.80777217774533, "z": 0.0 } } @@ -375,17 +375,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 36.779200000109064, - "y": 12.699999999906591 + "x": 36.77920000010646, + "y": 12.699999999909966 }, - "radius": 12.70000000361629, + "radius": 12.700000013357565, "start": { "unit": "degrees", - "value": 52.73916962151668 + "value": 52.73916962764604 }, "end": { "unit": "degrees", - "value": 221.26083055016414 + "value": 221.26083054811593 }, "relative": false } @@ -398,8 +398,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 40.44662815247449, - "y": 18.49500948539818, + "x": 40.44662816288228, + "y": 18.495009487551666, "z": 0.0 } } @@ -413,17 +413,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 36.77920000206833, - "y": 12.700000002007757 + "x": 36.77920000207094, + "y": 12.700000002016786 }, - "radius": 6.858000011007326, + "radius": 6.858000018383735, "start": { "unit": "degrees", - "value": 57.67192766159749 + "value": 57.671927597721655 }, "end": { "unit": "degrees", - "value": 216.32807261894507 + "value": 216.32807268059847 }, "relative": false } @@ -436,8 +436,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 29.090055915966776, - "y": 2.5922275429710444, + "x": 29.09005590710058, + "y": 2.592227529229856, "z": 0.0 } } @@ -451,17 +451,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 36.779200000780826, - "y": 12.700000000626266 + "x": 36.779200000776314, + "y": 12.700000000627622 }, - "radius": 12.700000031998599, + "radius": 12.700000048301373, "start": { "unit": "degrees", - "value": -127.26082839782381 + "value": -127.26082839210574 }, "end": { "unit": "degrees", - "value": 41.260828430859696 + "value": 41.26082839708283 }, "relative": false } @@ -474,8 +474,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 33.11177218911826, - "y": 6.9049902671388885, + "x": 33.11177217397298, + "y": 6.904990264267679, "z": 0.0 } } @@ -489,17 +489,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 36.77919999814787, - "y": 12.69999999780358 + "x": 36.77919999814004, + "y": 12.69999999780129 }, - "radius": 6.858000037397355, + "radius": 6.858000047916596, "start": { "unit": "degrees", - "value": -122.3280688236503 + "value": -122.32806891769751 }, "end": { "unit": "degrees", - "value": 36.32806915973179 + "value": 36.328069177418946 }, "relative": false } @@ -512,8 +512,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 27.23241748756816, - "y": 4.324503384918471, + "x": 27.232417487678482, + "y": 4.324503385625123, "z": 0.0 } } @@ -527,8 +527,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 31.254133767782637, - "y": 8.637266084416654, + "x": 31.254133774334424, + "y": 8.637266080080567, "z": 0.0 }, "relative": false @@ -542,8 +542,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 40.446628153256455, - "y": 18.49500948663209, + "x": 40.44662816366668, + "y": 18.495009488788785, "z": 0.0 } } @@ -557,8 +557,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 44.46834441685701, - "y": 22.807772168773674, + "x": 44.4683444216719, + "y": 22.80777217735356, "z": 0.0 }, "relative": false @@ -572,8 +572,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 29.090055915965344, - "y": 2.592227542972357, + "x": 29.090055907098876, + "y": 2.5922275292314536, "z": 0.0 } } @@ -587,8 +587,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 33.111772188335785, - "y": 6.904990265903376, + "x": 33.111772173188335, + "y": 6.904990263028899, "z": 0.0 }, "relative": false @@ -602,8 +602,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 42.304266584692165, - "y": 16.762733660487143, + "x": 42.30426656755469, + "y": 16.762733650516296, "z": 0.0 } } @@ -617,8 +617,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 46.32598285787484, - "y": 21.075496292967998, + "x": 46.32598285274018, + "y": 21.075496278508, "z": 0.0 }, "relative": false @@ -632,8 +632,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 71.18914430041069, - "y": 22.807772288510442, + "x": 71.18914437370873, + "y": 22.80777225740901, "z": 0.0 } } @@ -647,17 +647,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 63.50000000170948, - "y": 12.70000000181106 + "x": 63.50000000169832, + "y": 12.700000001806291 }, - "radius": 12.700000025433754, + "radius": 12.700000045068952, "start": { "unit": "degrees", - "value": 52.73917036722932 + "value": 52.73917001906413 }, "end": { "unit": "degrees", - "value": 221.2608293088481 + "value": 221.2608289435621 }, "relative": false } @@ -670,8 +670,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 55.810855686922665, - "y": 2.5922277270601035, + "x": 55.81085561309877, + "y": 2.5922277586607, "z": 0.0 } } @@ -685,17 +685,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 63.50000000185824, - "y": 12.700000001970036 + "x": 63.5000000018486, + "y": 12.700000001966911 }, - "radius": 12.700000025879683, + "radius": 12.700000045417108, "start": { "unit": "degrees", - "value": -127.26082972326456 + "value": -127.26083007462823 }, "end": { "unit": "degrees", - "value": 41.2608293989906 + "value": 41.26082903662816 }, "relative": false } @@ -708,8 +708,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 67.16742803659287, - "y": 18.495009602343114, + "x": 67.16742809556791, + "y": 18.49500958270679, "z": 0.0 } } @@ -723,17 +723,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 63.50000000339558, - "y": 12.700000003621428 + "x": 63.5000000033744, + "y": 12.700000003606004 }, - "radius": 6.858000045782867, + "radius": 6.858000060752406, "start": { "unit": "degrees", - "value": 57.67192900432028 + "value": 57.67192850016751 }, "end": { "unit": "degrees", - "value": 216.3280705229788 + "value": 216.328070161891 }, "relative": false } @@ -746,8 +746,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 59.832571940226536, - "y": 6.904990398060244, + "x": 59.83257188225481, + "y": 6.904990416947131, "z": 0.0 } } @@ -761,17 +761,17 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "arc", "center": { - "x": 63.50000000002184, - "y": 12.700000000000143 + "x": 63.50000000002072, + "y": 12.700000000006023 }, - "radius": 6.858000062725987, + "radius": 6.858000077772265, "start": { "unit": "degrees", - "value": -122.32807116907371 + "value": -122.32807166268023 }, "end": { "unit": "degrees", - "value": 36.32807063329834 + "value": 36.32807026212587 }, "relative": false } @@ -784,8 +784,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 53.953217298267354, - "y": 4.324503585367348, + "x": 53.953217249163586, + "y": 4.324503650004626, "z": 0.0 } } @@ -799,8 +799,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 57.974933609155336, - "y": 8.637266279810309, + "x": 57.974933589384776, + "y": 8.637266318920101, "z": 0.0 }, "relative": false @@ -814,8 +814,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 67.1674280372681, - "y": 18.49500960340906, + "x": 67.16742809623926, + "y": 18.495009583766386, "z": 0.0 } } @@ -829,8 +829,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 71.18914430034548, - "y": 22.807772288423347, + "x": 71.18914437364303, + "y": 22.80777225732085, "z": 0.0 }, "relative": false @@ -844,8 +844,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 55.81085568698723, - "y": 2.592227727146336, + "x": 55.8108556131638, + "y": 2.5922277587479954, "z": 0.0 } } @@ -859,8 +859,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 59.832571939553645, - "y": 6.904990396998012, + "x": 59.83257188158579, + "y": 6.904990415891235, "z": 0.0 }, "relative": false @@ -874,8 +874,8 @@ description: Artifact commands zoo-logo.kcl "type": "move_path_pen", "path": "[uuid]", "to": { - "x": 69.02506636764373, - "y": 16.762733720629306, + "x": 69.02506638842057, + "y": 16.76273368076763, "z": 0.0 } } @@ -889,8 +889,8 @@ description: Artifact commands zoo-logo.kcl "segment": { "type": "line", "end": { - "x": 73.04678269131756, - "y": 21.075496432728006, + "x": 73.04678273993022, + "y": 21.075496368531635, "z": 0.0 }, "relative": false @@ -904,8 +904,8 @@ description: Artifact commands zoo-logo.kcl "type": "create_region_from_query_point", "object_id": "[uuid]", "query_point": { - "x": 19.557999999869423, - "y": 21.209000000047578 + "x": 19.55799999986858, + "y": 21.20900000004937 } } }, @@ -916,8 +916,8 @@ description: Artifact commands zoo-logo.kcl "type": "create_region_from_query_point", "object_id": "[uuid]", "query_point": { - "x": 40.4466281524741, - "y": 22.807772168375674 + "x": 40.446628162881446, + "y": 22.807772176957805 } } }, @@ -928,8 +928,8 @@ description: Artifact commands zoo-logo.kcl "type": "create_region_from_query_point", "object_id": "[uuid]", "query_point": { - "x": 46.32598285823988, - "y": 16.76273366134223 + "x": 46.32598285310261, + "y": 16.762733651374578 } } }, @@ -940,8 +940,8 @@ description: Artifact commands zoo-logo.kcl "type": "create_region_from_query_point", "object_id": "[uuid]", "query_point": { - "x": 67.1674280386111, - "y": 22.80777228833509 + "x": 67.16742809757393, + "y": 22.807772257232646 } } }, @@ -952,8 +952,8 @@ description: Artifact commands zoo-logo.kcl "type": "create_region_from_query_point", "object_id": "[uuid]", "query_point": { - "x": 73.04678269123809, - "y": 16.762733721372385 + "x": 73.04678273984837, + "y": 16.762733681507473 } } }, diff --git a/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_graph_flowchart.snap.md b/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_graph_flowchart.snap.md index 9f87c633d6a..238eb26f31c 100644 --- a/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_graph_flowchart.snap.md +++ b/rust/kcl-lib/tests/kcl_samples/zoo-logo/artifact_graph_flowchart.snap.md @@ -1,7 +1,7 @@ ```mermaid flowchart LR subgraph path2 [Path] - 2["Path
[150, 15243, 0]
Consumed: false"] + 2["Path
[150, 15368, 0]
Consumed: false"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] 3["Segment
[1084, 1154, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 15 }, VariableDeclarationDeclaration, VariableDeclarationInit] @@ -51,110 +51,110 @@ flowchart LR %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 103 }, VariableDeclarationDeclaration, VariableDeclarationInit] 26["Segment
[6168, 6238, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 104 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 27["Segment
[8958, 9058, 0]"] + 27["Segment
[9021, 9121, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 150 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 28["Segment
[9071, 9171, 0]"] + 28["Segment
[9134, 9234, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 151 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 29["Segment
[9184, 9286, 0]"] + 29["Segment
[9247, 9349, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 152 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 30["Segment
[9299, 9401, 0]"] + 30["Segment
[9362, 9464, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 153 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 31["Segment
[9415, 9485, 0]"] + 31["Segment
[9478, 9548, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 154 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 32["Segment
[9499, 9567, 0]"] + 32["Segment
[9562, 9630, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 155 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 33["Segment
[9581, 9649, 0]"] + 33["Segment
[9644, 9712, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 156 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 34["Segment
[9663, 9733, 0]"] + 34["Segment
[9726, 9796, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 157 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path35 [Path] - 35["Path Region
[15255, 15306, 0]
Consumed: true"] + 35["Path Region
[15380, 15431, 0]
Consumed: true"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 36["Segment
[15255, 15306, 0]"] + 36["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 37["Segment
[15255, 15306, 0]"] + 37["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 38["Segment
[15255, 15306, 0]"] + 38["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 39["Segment
[15255, 15306, 0]"] + 39["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 40["Segment
[15255, 15306, 0]"] + 40["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 41["Segment
[15255, 15306, 0]"] + 41["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 42["Segment
[15255, 15306, 0]"] + 42["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 43["Segment
[15255, 15306, 0]"] + 43["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 44["Segment
[15255, 15306, 0]"] + 44["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 45["Segment
[15255, 15306, 0]"] + 45["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 46["Segment
[15255, 15306, 0]"] + 46["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 47["Segment
[15255, 15306, 0]"] + 47["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 48["Segment
[15255, 15306, 0]"] + 48["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 49["Segment
[15255, 15306, 0]"] + 49["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 50["Segment
[15255, 15306, 0]"] + 50["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 51["Segment
[15255, 15306, 0]"] + 51["Segment
[15380, 15431, 0]"] %% [ProgramBodyItem { index: 3 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path52 [Path] - 52["Path Region
[15319, 15372, 0]
Consumed: true"] + 52["Path Region
[15444, 15497, 0]
Consumed: true"] %% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 53["Segment
[15319, 15372, 0]"] + 53["Segment
[15444, 15497, 0]"] %% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 54["Segment
[15319, 15372, 0]"] + 54["Segment
[15444, 15497, 0]"] %% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 55["Segment
[15319, 15372, 0]"] + 55["Segment
[15444, 15497, 0]"] %% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 56["Segment
[15319, 15372, 0]"] + 56["Segment
[15444, 15497, 0]"] %% [ProgramBodyItem { index: 4 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path57 [Path] - 57["Path Region
[15385, 15438, 0]
Consumed: true"] + 57["Path Region
[15510, 15563, 0]
Consumed: true"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 58["Segment
[15385, 15438, 0]"] + 58["Segment
[15510, 15563, 0]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 59["Segment
[15385, 15438, 0]"] + 59["Segment
[15510, 15563, 0]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 60["Segment
[15385, 15438, 0]"] + 60["Segment
[15510, 15563, 0]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 61["Segment
[15385, 15438, 0]"] + 61["Segment
[15510, 15563, 0]"] %% [ProgramBodyItem { index: 5 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path62 [Path] - 62["Path Region
[15451, 15504, 0]
Consumed: true"] + 62["Path Region
[15576, 15629, 0]
Consumed: true"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 63["Segment
[15451, 15504, 0]"] + 63["Segment
[15576, 15629, 0]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 64["Segment
[15451, 15504, 0]"] + 64["Segment
[15576, 15629, 0]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 65["Segment
[15451, 15504, 0]"] + 65["Segment
[15576, 15629, 0]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 66["Segment
[15451, 15504, 0]"] + 66["Segment
[15576, 15629, 0]"] %% [ProgramBodyItem { index: 6 }, VariableDeclarationDeclaration, VariableDeclarationInit] end subgraph path67 [Path] - 67["Path Region
[15517, 15570, 0]
Consumed: true"] + 67["Path Region
[15642, 15695, 0]
Consumed: true"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 68["Segment
[15517, 15570, 0]"] + 68["Segment
[15642, 15695, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 69["Segment
[15517, 15570, 0]"] + 69["Segment
[15642, 15695, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 70["Segment
[15517, 15570, 0]"] + 70["Segment
[15642, 15695, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 71["Segment
[15517, 15570, 0]"] + 71["Segment
[15642, 15695, 0]"] %% [ProgramBodyItem { index: 7 }, VariableDeclarationDeclaration, VariableDeclarationInit] end - 1["Plane
[150, 15243, 0]"] + 1["Plane
[150, 15368, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] - 72["Sweep Extrusion
[15601, 15714, 0]
Consumed: false"] + 72["Sweep Extrusion
[15726, 15839, 0]
Consumed: false"] %% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] 73[Wall] %% face_code_ref=Missing NodePath @@ -224,7 +224,7 @@ flowchart LR 120["SweepEdge Adjacent"] 121["SweepEdge Opposite"] 122["SweepEdge Adjacent"] - 123["Sweep Extrusion
[15601, 15714, 0]
Consumed: false"] + 123["Sweep Extrusion
[15726, 15839, 0]
Consumed: false"] %% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] 124[Wall] %% face_code_ref=Missing NodePath @@ -246,7 +246,7 @@ flowchart LR 135["SweepEdge Adjacent"] 136["SweepEdge Opposite"] 137["SweepEdge Adjacent"] - 138["Sweep Extrusion
[15601, 15714, 0]
Consumed: false"] + 138["Sweep Extrusion
[15726, 15839, 0]
Consumed: false"] %% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] 139[Wall] %% face_code_ref=Missing NodePath @@ -268,7 +268,7 @@ flowchart LR 150["SweepEdge Adjacent"] 151["SweepEdge Opposite"] 152["SweepEdge Adjacent"] - 153["Sweep Extrusion
[15601, 15714, 0]
Consumed: false"] + 153["Sweep Extrusion
[15726, 15839, 0]
Consumed: false"] %% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] 154[Wall] %% face_code_ref=Missing NodePath @@ -290,7 +290,7 @@ flowchart LR 165["SweepEdge Adjacent"] 166["SweepEdge Opposite"] 167["SweepEdge Adjacent"] - 168["Sweep Extrusion
[15601, 15714, 0]
Consumed: false"] + 168["Sweep Extrusion
[15726, 15839, 0]
Consumed: false"] %% [ProgramBodyItem { index: 9 }, VariableDeclarationDeclaration, VariableDeclarationInit] 169[Wall] %% face_code_ref=Missing NodePath @@ -312,7 +312,7 @@ flowchart LR 180["SweepEdge Adjacent"] 181["SweepEdge Opposite"] 182["SweepEdge Adjacent"] - 183["SketchBlock
[150, 15243, 0]"] + 183["SketchBlock
[150, 15368, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit] 184["SketchBlockConstraint Coincident
[560, 607, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 4 }, ExpressionStatementExpr] @@ -522,145 +522,145 @@ flowchart LR %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 142 }, ExpressionStatementExpr] 287["SketchBlockConstraint LinesEqualLength
[8552, 8587, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 143 }, ExpressionStatementExpr] - 288["SketchBlockConstraint Angle
[8591, 8630, 0]"] + 288["SketchBlockConstraint Angle
[8591, 8693, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 144 }, ExpressionStatementExpr] - 289["SketchBlockConstraint HorizontalDistance
[8633, 8711, 0]"] + 289["SketchBlockConstraint HorizontalDistance
[8696, 8774, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 145 }, ExpressionStatementExpr] - 290["SketchBlockConstraint VerticalDistance
[8714, 8788, 0]"] + 290["SketchBlockConstraint VerticalDistance
[8777, 8851, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 146 }, ExpressionStatementExpr] - 291["SketchBlockConstraint Radius
[8791, 8826, 0]"] + 291["SketchBlockConstraint Radius
[8854, 8889, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 147 }, ExpressionStatementExpr] - 292["SketchBlockConstraint Radius
[8829, 8865, 0]"] + 292["SketchBlockConstraint Radius
[8892, 8928, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 148 }, ExpressionStatementExpr] - 293["SketchBlockConstraint Distance
[8868, 8936, 0]"] + 293["SketchBlockConstraint Distance
[8931, 8999, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 149 }, ExpressionStatementExpr] - 294["SketchBlockConstraint Coincident
[10593, 10637, 0]"] + 294["SketchBlockConstraint Coincident
[10656, 10700, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 164 }, ExpressionStatementExpr] - 295["SketchBlockConstraint Coincident
[10640, 10684, 0]"] + 295["SketchBlockConstraint Coincident
[10703, 10747, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 165 }, ExpressionStatementExpr] - 296["SketchBlockConstraint Coincident
[10687, 10731, 0]"] + 296["SketchBlockConstraint Coincident
[10750, 10794, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 166 }, ExpressionStatementExpr] - 297["SketchBlockConstraint Coincident
[10734, 10783, 0]"] + 297["SketchBlockConstraint Coincident
[10797, 10846, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 167 }, ExpressionStatementExpr] - 298["SketchBlockConstraint Coincident
[10786, 10835, 0]"] + 298["SketchBlockConstraint Coincident
[10849, 10898, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 168 }, ExpressionStatementExpr] - 299["SketchBlockConstraint Coincident
[10838, 10887, 0]"] + 299["SketchBlockConstraint Coincident
[10901, 10950, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 169 }, ExpressionStatementExpr] - 300["SketchBlockConstraint Coincident
[10890, 10939, 0]"] + 300["SketchBlockConstraint Coincident
[10953, 11002, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 170 }, ExpressionStatementExpr] - 301["SketchBlockConstraint Coincident
[10943, 10984, 0]"] + 301["SketchBlockConstraint Coincident
[11006, 11047, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 171 }, ExpressionStatementExpr] - 302["SketchBlockConstraint Coincident
[10987, 11026, 0]"] + 302["SketchBlockConstraint Coincident
[11050, 11089, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 172 }, ExpressionStatementExpr] - 303["SketchBlockConstraint Coincident
[11029, 11072, 0]"] + 303["SketchBlockConstraint Coincident
[11092, 11135, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 173 }, ExpressionStatementExpr] - 304["SketchBlockConstraint Coincident
[11075, 11116, 0]"] + 304["SketchBlockConstraint Coincident
[11138, 11179, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 174 }, ExpressionStatementExpr] - 305["SketchBlockConstraint Coincident
[11119, 11162, 0]"] + 305["SketchBlockConstraint Coincident
[11182, 11225, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 175 }, ExpressionStatementExpr] - 306["SketchBlockConstraint Coincident
[11165, 11206, 0]"] + 306["SketchBlockConstraint Coincident
[11228, 11269, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 176 }, ExpressionStatementExpr] - 307["SketchBlockConstraint Coincident
[11209, 11250, 0]"] + 307["SketchBlockConstraint Coincident
[11272, 11313, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 177 }, ExpressionStatementExpr] - 308["SketchBlockConstraint Coincident
[11253, 11292, 0]"] + 308["SketchBlockConstraint Coincident
[11316, 11355, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 178 }, ExpressionStatementExpr] - 309["SketchBlockConstraint Coincident
[11295, 11338, 0]"] + 309["SketchBlockConstraint Coincident
[11358, 11401, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 179 }, ExpressionStatementExpr] - 310["SketchBlockConstraint Coincident
[11341, 11384, 0]"] + 310["SketchBlockConstraint Coincident
[11404, 11447, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 180 }, ExpressionStatementExpr] - 311["SketchBlockConstraint Coincident
[11387, 11430, 0]"] + 311["SketchBlockConstraint Coincident
[11450, 11493, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 181 }, ExpressionStatementExpr] - 312["SketchBlockConstraint Coincident
[11433, 11476, 0]"] + 312["SketchBlockConstraint Coincident
[11496, 11539, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 182 }, ExpressionStatementExpr] - 313["SketchBlockConstraint Coincident
[11479, 11527, 0]"] + 313["SketchBlockConstraint Coincident
[11542, 11590, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 183 }, ExpressionStatementExpr] - 314["SketchBlockConstraint Coincident
[11530, 11576, 0]"] + 314["SketchBlockConstraint Coincident
[11593, 11639, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 184 }, ExpressionStatementExpr] - 315["SketchBlockConstraint Coincident
[11579, 11628, 0]"] + 315["SketchBlockConstraint Coincident
[11642, 11691, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 185 }, ExpressionStatementExpr] - 316["SketchBlockConstraint Coincident
[11631, 11678, 0]"] + 316["SketchBlockConstraint Coincident
[11694, 11741, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 186 }, ExpressionStatementExpr] - 317["SketchBlockConstraint Coincident
[11681, 11728, 0]"] + 317["SketchBlockConstraint Coincident
[11744, 11791, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 187 }, ExpressionStatementExpr] - 318["SketchBlockConstraint Coincident
[11731, 11776, 0]"] + 318["SketchBlockConstraint Coincident
[11794, 11839, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 188 }, ExpressionStatementExpr] - 319["SketchBlockConstraint Coincident
[11779, 11825, 0]"] + 319["SketchBlockConstraint Coincident
[11842, 11888, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 189 }, ExpressionStatementExpr] - 320["SketchBlockConstraint Coincident
[11828, 11872, 0]"] + 320["SketchBlockConstraint Coincident
[11891, 11935, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 190 }, ExpressionStatementExpr] - 321["SketchBlockConstraint Parallel
[11876, 11907, 0]"] + 321["SketchBlockConstraint Parallel
[11939, 11970, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 191 }, ExpressionStatementExpr] - 322["SketchBlockConstraint Parallel
[11910, 11941, 0]"] + 322["SketchBlockConstraint Parallel
[11973, 12004, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 192 }, ExpressionStatementExpr] - 323["SketchBlockConstraint Parallel
[11944, 11975, 0]"] + 323["SketchBlockConstraint Parallel
[12007, 12038, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 193 }, ExpressionStatementExpr] - 324["SketchBlockConstraint Parallel
[11978, 12009, 0]"] + 324["SketchBlockConstraint Parallel
[12041, 12072, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 194 }, ExpressionStatementExpr] - 325["SketchBlockConstraint Parallel
[12012, 12044, 0]"] + 325["SketchBlockConstraint Parallel
[12075, 12107, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 195 }, ExpressionStatementExpr] - 326["SketchBlockConstraint LinesEqualLength
[12047, 12082, 0]"] + 326["SketchBlockConstraint LinesEqualLength
[12110, 12145, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 196 }, ExpressionStatementExpr] - 327["SketchBlockConstraint HorizontalDistance
[12086, 12160, 0]"] + 327["SketchBlockConstraint HorizontalDistance
[12149, 12223, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 197 }, ExpressionStatementExpr] - 328["SketchBlockConstraint VerticalDistance
[12163, 12235, 0]"] + 328["SketchBlockConstraint VerticalDistance
[12226, 12298, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 198 }, ExpressionStatementExpr] - 329["SketchBlockConstraint Distance
[12238, 12306, 0]"] + 329["SketchBlockConstraint Distance
[12301, 12369, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 199 }, ExpressionStatementExpr] - 330["SketchBlockConstraint Angle
[12309, 12348, 0]"] + 330["SketchBlockConstraint Angle
[12372, 12473, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 200 }, ExpressionStatementExpr] - 331["SketchBlockConstraint Radius
[12351, 12386, 0]"] + 331["SketchBlockConstraint Radius
[12476, 12511, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 201 }, ExpressionStatementExpr] - 332["SketchBlockConstraint Radius
[12389, 12425, 0]"] + 332["SketchBlockConstraint Radius
[12514, 12550, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 202 }, ExpressionStatementExpr] - 333["SketchBlockConstraint Coincident
[12692, 12758, 0]"] + 333["SketchBlockConstraint Coincident
[12817, 12883, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 205 }, ExpressionStatementExpr] - 334["SketchBlockConstraint Coincident
[12761, 12828, 0]"] + 334["SketchBlockConstraint Coincident
[12886, 12953, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 206 }, ExpressionStatementExpr] - 335["SketchBlockConstraint Coincident
[12831, 12909, 0]"] + 335["SketchBlockConstraint Coincident
[12956, 13034, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 207 }, ExpressionStatementExpr] - 336["SketchBlockConstraint Vertical
[12913, 12943, 0]"] + 336["SketchBlockConstraint Vertical
[13038, 13068, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 208 }, ExpressionStatementExpr] - 337["SketchBlockConstraint Horizontal
[12946, 12980, 0]"] + 337["SketchBlockConstraint Horizontal
[13071, 13105, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 209 }, ExpressionStatementExpr] - 338["SketchBlockConstraint Coincident
[13239, 13308, 0]"] + 338["SketchBlockConstraint Coincident
[13364, 13433, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 212 }, ExpressionStatementExpr] - 339["SketchBlockConstraint Coincident
[13311, 13385, 0]"] + 339["SketchBlockConstraint Coincident
[13436, 13510, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 213 }, ExpressionStatementExpr] - 340["SketchBlockConstraint Coincident
[13388, 13470, 0]"] + 340["SketchBlockConstraint Coincident
[13513, 13595, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 214 }, ExpressionStatementExpr] - 341["SketchBlockConstraint Vertical
[13474, 13506, 0]"] + 341["SketchBlockConstraint Vertical
[13599, 13631, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 215 }, ExpressionStatementExpr] - 342["SketchBlockConstraint Horizontal
[13509, 13545, 0]"] + 342["SketchBlockConstraint Horizontal
[13634, 13670, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 216 }, ExpressionStatementExpr] - 343["SketchBlockConstraint Coincident
[13807, 13881, 0]"] + 343["SketchBlockConstraint Coincident
[13932, 14006, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 219 }, ExpressionStatementExpr] - 344["SketchBlockConstraint Coincident
[13884, 13953, 0]"] + 344["SketchBlockConstraint Coincident
[14009, 14078, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 220 }, ExpressionStatementExpr] - 345["SketchBlockConstraint Coincident
[13956, 14038, 0]"] + 345["SketchBlockConstraint Coincident
[14081, 14163, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 221 }, ExpressionStatementExpr] - 346["SketchBlockConstraint Vertical
[14042, 14074, 0]"] + 346["SketchBlockConstraint Vertical
[14167, 14199, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 222 }, ExpressionStatementExpr] - 347["SketchBlockConstraint Horizontal
[14077, 14113, 0]"] + 347["SketchBlockConstraint Horizontal
[14202, 14238, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 223 }, ExpressionStatementExpr] - 348["SketchBlockConstraint Coincident
[14371, 14443, 0]"] + 348["SketchBlockConstraint Coincident
[14496, 14568, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 226 }, ExpressionStatementExpr] - 349["SketchBlockConstraint Coincident
[14446, 14520, 0]"] + 349["SketchBlockConstraint Coincident
[14571, 14645, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 227 }, ExpressionStatementExpr] - 350["SketchBlockConstraint Coincident
[14523, 14605, 0]"] + 350["SketchBlockConstraint Coincident
[14648, 14730, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 228 }, ExpressionStatementExpr] - 351["SketchBlockConstraint Vertical
[14609, 14641, 0]"] + 351["SketchBlockConstraint Vertical
[14734, 14766, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 229 }, ExpressionStatementExpr] - 352["SketchBlockConstraint Horizontal
[14644, 14680, 0]"] + 352["SketchBlockConstraint Horizontal
[14769, 14805, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 230 }, ExpressionStatementExpr] - 353["SketchBlockConstraint Coincident
[14942, 15009, 0]"] + 353["SketchBlockConstraint Coincident
[15067, 15134, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 233 }, ExpressionStatementExpr] - 354["SketchBlockConstraint Coincident
[15012, 15081, 0]"] + 354["SketchBlockConstraint Coincident
[15137, 15206, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 234 }, ExpressionStatementExpr] - 355["SketchBlockConstraint Coincident
[15084, 15166, 0]"] + 355["SketchBlockConstraint Coincident
[15209, 15291, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 235 }, ExpressionStatementExpr] - 356["SketchBlockConstraint Vertical
[15170, 15202, 0]"] + 356["SketchBlockConstraint Vertical
[15295, 15327, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 236 }, ExpressionStatementExpr] - 357["SketchBlockConstraint Horizontal
[15205, 15241, 0]"] + 357["SketchBlockConstraint Horizontal
[15330, 15366, 0]"] %% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, SketchBlockBody, SketchBlockBodyItem { index: 237 }, ExpressionStatementExpr] 1 --- 2 1 <--x 35 diff --git a/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap b/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap index ebd550fee19..5935c830b80 100644 --- a/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap +++ b/rust/kcl-lib/tests/kcl_samples/zoo-logo/ast.snap @@ -19641,7 +19641,136 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "frameBottom", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "o1Line01", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1.06in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.06, + "suffix": "Inch" + } + }, + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0.06in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.06, + "suffix": "Inch" + } + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -19651,7 +19780,7 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -19665,52 +19794,7 @@ description: Result of parsing zoo-logo.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "frameBottom", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "o1Line01", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", @@ -28050,7 +28134,136 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "left": { - "arguments": [], + "arguments": [ + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "lines", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "frameBottom", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + }, + { + "abs_path": false, + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "o2Line03", + "start": 0, + "type": "Identifier" + }, + "path": [], + "start": 0, + "type": "Name", + "type": "Name" + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "sector", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "1", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 1.0, + "suffix": "None" + } + } + }, + { + "type": "LabeledArg", + "label": { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "name": "labelPosition", + "start": 0, + "type": "Identifier" + }, + "arg": { + "commentStart": 0, + "elements": [ + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "2.2in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 2.2, + "suffix": "Inch" + } + }, + { + "commentStart": 0, + "end": 0, + "moduleId": 0, + "raw": "0.04in", + "start": 0, + "type": "Literal", + "type": "Literal", + "value": { + "value": 0.04, + "suffix": "Inch" + } + } + ], + "end": 0, + "moduleId": 0, + "start": 0, + "type": "ArrayExpression", + "type": "ArrayExpression" + } + } + ], "callee": { "abs_path": false, "commentStart": 0, @@ -28060,7 +28273,7 @@ description: Result of parsing zoo-logo.kcl "commentStart": 0, "end": 0, "moduleId": 0, - "name": "angle", + "name": "angleDimension", "start": 0, "type": "Identifier" }, @@ -28074,52 +28287,7 @@ description: Result of parsing zoo-logo.kcl "start": 0, "type": "CallExpressionKw", "type": "CallExpressionKw", - "unlabeled": { - "commentStart": 0, - "elements": [ - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "frameBottom", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - }, - { - "abs_path": false, - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": { - "commentStart": 0, - "end": 0, - "moduleId": 0, - "name": "o2Line03", - "start": 0, - "type": "Identifier" - }, - "path": [], - "start": 0, - "type": "Name", - "type": "Name" - } - ], - "end": 0, - "moduleId": 0, - "start": 0, - "type": "ArrayExpression", - "type": "ArrayExpression" - } + "unlabeled": null }, "moduleId": 0, "operator": "==", diff --git a/rust/kcl-lib/tests/kcl_samples/zoo-logo/ops.snap b/rust/kcl-lib/tests/kcl_samples/zoo-logo/ops.snap index 8f598f69843..78d933bd3ca 100644 --- a/rust/kcl-lib/tests/kcl_samples/zoo-logo/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/zoo-logo/ops.snap @@ -8376,22 +8376,61 @@ description: Operations executed zoo-logo.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 1.06, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 0.06, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { @@ -11703,22 +11742,61 @@ description: Operations executed zoo-logo.kcl }, { "type": "StdLibCall", - "name": "angle", - "unlabeledArg": { - "value": { - "type": "Array", - "value": [ - { - "type": "KclNone" - }, - { - "type": "KclNone" - } - ] + "name": "angleDimension", + "unlabeledArg": null, + "labeledArgs": { + "labelPosition": { + "value": { + "type": "Array", + "value": [ + { + "type": "Number", + "value": 2.2, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + }, + { + "type": "Number", + "value": 0.04, + "ty": { + "in": null, + "type": "Known", + "type": "Length" + } + } + ] + }, + "sourceRange": [] }, - "sourceRange": [] + "lines": { + "value": { + "type": "Array", + "value": [ + { + "type": "KclNone" + }, + { + "type": "KclNone" + } + ] + }, + "sourceRange": [] + }, + "sector": { + "value": { + "type": "Number", + "value": 1.0, + "ty": { + "type": "Known", + "type": "Count" + } + }, + "sourceRange": [] + } }, - "labeledArgs": {}, "nodePath": { "steps": [ { diff --git a/rust/kcl-lib/tests/kcl_samples/zoo-logo/program_memory.snap b/rust/kcl-lib/tests/kcl_samples/zoo-logo/program_memory.snap index 5bfd334d879..494805a6291 100644 --- a/rust/kcl-lib/tests/kcl_samples/zoo-logo/program_memory.snap +++ b/rust/kcl-lib/tests/kcl_samples/zoo-logo/program_memory.snap @@ -281,8 +281,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "tag": { "commentStart": 1074, @@ -293,8 +293,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine01" }, "to": [ - 0.0250000000019479, - 0.16500000320161995 + 0.02500000000191471, + 0.16500000320169073 ], "type": "ToPoint", "units": "in" @@ -305,8 +305,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.0250000000019479, - 0.16500000320161995 + 0.02500000000191471, + 0.16500000320169073 ], "tag": { "commentStart": 1157, @@ -317,8 +317,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine02" }, "to": [ - 0.5722530846158204, - 0.7599999999993404 + 0.5722530846157872, + 0.759999999999411 ], "type": "ToPoint", "units": "in" @@ -329,8 +329,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.5722530846158204, - 0.7599999999993404 + 0.5722530846157872, + 0.759999999999411 ], "tag": { "commentStart": 1240, @@ -341,8 +341,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine03" }, "to": [ - 0.025000000003983447, - 0.759999999999515 + 0.025000000003950255, + 0.7599999999995856 ], "type": "ToPoint", "units": "in" @@ -353,8 +353,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000003983447, - 0.759999999999515 + 0.025000000003950255, + 0.7599999999995856 ], "tag": { "commentStart": 1323, @@ -365,8 +365,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine04" }, "to": [ - 0.025000000004661963, - 0.9749999999997455 + 0.025000000004628768, + 0.9749999999998161 ], "type": "ToPoint", "units": "in" @@ -377,8 +377,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000004661963, - 0.9749999999997455 + 0.025000000004628768, + 0.9749999999998161 ], "tag": { "commentStart": 1406, @@ -389,8 +389,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine05" }, "to": [ - 0.625000000005742, - 0.9749999999999464 + 0.6250000000057087, + 0.975000000000017 ], "type": "ToPoint", "units": "in" @@ -401,8 +401,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.625000000005742, - 0.9749999999999464 + 0.6250000000057087, + 0.975000000000017 ], "tag": { "commentStart": 1489, @@ -413,8 +413,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine06" }, "to": [ - 0.625000000007099, - 0.8173489912353609 + 0.6250000000070657, + 0.8173489912354314 ], "type": "ToPoint", "units": "in" @@ -425,8 +425,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.625000000007099, - 0.8173489912353609 + 0.6250000000070657, + 0.8173489912354314 ], "tag": { "commentStart": 1572, @@ -437,8 +437,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine07" }, "to": [ - 0.7699999999942422, - 0.9750000000023993 + 0.7699999999942091, + 0.9750000000024699 ], "type": "ToPoint", "units": "in" @@ -449,8 +449,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.7699999999942422, - 0.9750000000023993 + 0.7699999999942091, + 0.9750000000024699 ], "tag": { "commentStart": 1655, @@ -461,8 +461,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine08" }, "to": [ - 0.9099999999954762, - 0.9750000000018456 + 0.9099999999954431, + 0.9750000000019162 ], "type": "ToPoint", "units": "in" @@ -473,8 +473,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999954762, - 0.9750000000018456 + 0.9099999999954431, + 0.9750000000019162 ], "tag": { "commentStart": 1738, @@ -485,8 +485,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine09" }, "to": [ - 0.9099999999967102, - 0.8350000000018732 + 0.909999999996677, + 0.8350000000019439 ], "type": "ToPoint", "units": "in" @@ -497,8 +497,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999967102, - 0.8350000000018732 + 0.909999999996677, + 0.8350000000019439 ], "tag": { "commentStart": 1821, @@ -509,8 +509,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine10" }, "to": [ - 0.36274691369315737, - 0.23999999999845167 + 0.3627469136931242, + 0.23999999999852248 ], "type": "ToPoint", "units": "in" @@ -521,8 +521,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.36274691369315737, - 0.23999999999845167 + 0.3627469136931242, + 0.23999999999852248 ], "tag": { "commentStart": 1904, @@ -533,8 +533,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine11" }, "to": [ - 0.9099999999992231, - 0.23999999999841187 + 0.90999999999919, + 0.23999999999848265 ], "type": "ToPoint", "units": "in" @@ -545,8 +545,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999992231, - 0.23999999999841187 + 0.90999999999919, + 0.23999999999848265 ], "tag": { "commentStart": 1987, @@ -557,8 +557,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine12" }, "to": [ - 0.909999999999855, - 0.024999999998245644 + 0.909999999999822, + 0.02499999999831642 ], "type": "ToPoint", "units": "in" @@ -569,8 +569,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.909999999999855, - 0.024999999998245644 + 0.909999999999822, + 0.02499999999831642 ], "tag": { "commentStart": 2070, @@ -581,8 +581,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine13" }, "to": [ - 0.3100000000003626, - 0.024999999998138397 + 0.3100000000003294, + 0.024999999998209173 ], "type": "ToPoint", "units": "in" @@ -593,8 +593,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.3100000000003626, - 0.024999999998138397 + 0.3100000000003294, + 0.024999999998209173 ], "tag": { "commentStart": 2153, @@ -605,8 +605,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine14" }, "to": [ - 0.3100000000009166, - 0.1826510087623727 + 0.31000000000088346, + 0.18265100876244356 ], "type": "ToPoint", "units": "in" @@ -617,8 +617,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.3100000000009166, - 0.1826510087623727 + 0.31000000000088346, + 0.18265100876244356 ], "tag": { "commentStart": 2236, @@ -629,8 +629,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine15" }, "to": [ - 0.16500000015676336, - 0.024999999999429413 + 0.1650000001567301, + 0.02499999999950019 ], "type": "ToPoint", "units": "in" @@ -641,8 +641,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.16500000015676336, - 0.024999999999429413 + 0.1650000001567301, + 0.02499999999950019 ], "tag": { "commentStart": 2319, @@ -653,8 +653,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine16" }, "to": [ - 0.025000000000842026, - 0.024999999999440452 + 0.025000000000808834, + 0.024999999999511226 ], "type": "ToPoint", "units": "in" @@ -693,12 +693,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -924,14 +924,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000042939, - 0.4999999999963225 + 1.4480000000041913, + 0.4999999999964554 ], "from": [ - 1.7507222211478382, - 0.8979437861876547 + 1.7507222213373614, + 0.8979437865254067 ], - "radius": 0.5000000001423737, + "radius": 0.5000000005258884, "tag": { "commentStart": 5447, "end": 5454, @@ -941,8 +941,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc01" }, "to": [ - 1.0721424205345453, - 0.1702560385694067 + 1.072142420234361, + 0.17025603833005248 ], "type": "Arc", "units": "in" @@ -954,14 +954,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000814304, - 0.5000000000790455 + 1.448000000081533, + 0.500000000079401 ], "from": [ - 1.592386935136791, - 0.7281499797400859 + 1.5923869355465465, + 0.7281499798248687 ], - "radius": 0.2700000004333593, + "radius": 0.2700000007237691, "tag": { "commentStart": 5562, "end": 5569, @@ -971,8 +971,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc02" }, "to": [ - 1.230477706531429, - 0.34004984520959547 + 1.2304777064696815, + 0.34004984480384404 ], "type": "Arc", "units": "in" @@ -984,14 +984,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000307414, - 0.5000000000246562 + 1.4480000000305635, + 0.5000000000247096 ], "from": [ - 1.145277791967196, - 0.10205620247917498 + 1.1452777916181331, + 0.10205620193818332 ], - "radius": 0.5000000012597874, + "radius": 0.5000000019016289, "tag": { "commentStart": 5678, "end": 5685, @@ -1001,8 +1001,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc03" }, "to": [ - 1.8238575925373133, - 0.8297439482859565 + 1.8238575932140073, + 0.8297439484877219 ], "type": "Arc", "units": "in" @@ -1014,14 +1014,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4479999999270814, - 0.49999999991352684 + 1.4479999999267732, + 0.49999999991343663 ], "from": [ - 1.3036130783117428, - 0.2718500105172791 + 1.3036130777154717, + 0.27185001040423934 ], - "radius": 0.2700000014723368, + "radius": 0.27000000188648016, "tag": { "commentStart": 5793, "end": 5800, @@ -1031,8 +1031,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc04" }, "to": [ - 1.6655223039710587, - 0.6599501422656404 + 1.6655223042550238, + 0.6599501425780409 ], "type": "Arc", "units": "in" @@ -1071,12 +1071,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -1301,8 +1301,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.0721424207704, - 0.1702560387763178 + 1.0721424207747434, + 0.1702560388041387 ], "tag": { "commentStart": 5908, @@ -1313,8 +1313,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line01" }, "to": [ - 1.2304777073930173, - 0.3400498458431754 + 1.2304777076509616, + 0.34004984567246327 ], "type": "ToPoint", "units": "in" @@ -1325,8 +1325,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.592386935167577, - 0.728149979788665 + 1.5923869355774285, + 0.7281499798735742 ], "tag": { "commentStart": 5992, @@ -1337,8 +1337,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line02" }, "to": [ - 1.7507222211361029, - 0.897943786172192 + 1.7507222213256655, + 0.8979437865099826 ], "type": "ToPoint", "units": "in" @@ -1349,8 +1349,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.1452777919671395, - 0.10205620247922666 + 1.145277791618066, + 0.1020562019382462 ], "tag": { "commentStart": 6075, @@ -1361,8 +1361,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line03" }, "to": [ - 1.3036130782809365, - 0.2718500104686369 + 1.3036130776845802, + 0.27185001035546846 ], "type": "ToPoint", "units": "in" @@ -1373,8 +1373,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.6655223064839437, - 0.6599501441136671 + 1.6655223058092399, + 0.659950143721114 ], "tag": { "commentStart": 6157, @@ -1385,8 +1385,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line04" }, "to": [ - 1.8238575928297183, - 0.8297439485420472 + 1.8238575926275662, + 0.8297439479727559 ], "type": "ToPoint", "units": "in" @@ -1425,12 +1425,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -1592,10 +1592,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 8948, - "end": 8955, + "commentStart": 9011, + "end": 9018, "moduleId": 0, - "start": 8948, + "start": 9011, "type": "TagDeclarator", "value": "o2Arc01" }, @@ -1606,10 +1606,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9061, - "end": 9068, + "commentStart": 9124, + "end": 9131, "moduleId": 0, - "start": 9061, + "start": 9124, "type": "TagDeclarator", "value": "o2Arc02" }, @@ -1620,10 +1620,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9174, - "end": 9181, + "commentStart": 9237, + "end": 9244, "moduleId": 0, - "start": 9174, + "start": 9237, "type": "TagDeclarator", "value": "o2Arc03" }, @@ -1634,10 +1634,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9570, - "end": 9578, + "commentStart": 9633, + "end": 9641, "moduleId": 0, - "start": 9570, + "start": 9633, "type": "TagDeclarator", "value": "o2Line03" }, @@ -1656,25 +1656,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.5000000000673026, - 0.5000000000713016 + 2.500000000066863, + 0.5000000000711139 ], "from": [ - 2.802722216551602, - 0.897943790886238 + 2.8027222194373516, + 0.897943789661772 ], - "radius": 0.5000000010013289, + "radius": 0.5000000017743682, "tag": { - "commentStart": 8948, - "end": 8955, + "commentStart": 9011, + "end": 9018, "moduleId": 0, - "start": 8948, + "start": 9011, "type": "TagDeclarator", "value": "o2Arc01" }, "to": [ - 2.1241424128079442, - 0.17025604622088947 + 2.1241424101241355, + 0.17025604810715045 ], "type": "Arc", "units": "in" @@ -1686,25 +1686,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.5000000000731593, - 0.5000000000775605 + 2.5000000000727796, + 0.5000000000774375 ], "from": [ - 2.1972777829497114, - 0.10205620972677573 + 2.1972777800432586, + 0.1020562109708937 ], - "radius": 0.5000000010188852, + "radius": 0.5000000017880751, "tag": { - "commentStart": 9061, - "end": 9068, + "commentStart": 9124, + "end": 9131, "moduleId": 0, - "start": 9061, + "start": 9124, "type": "TagDeclarator", "value": "o2Arc02" }, "to": [ - 2.875857586826934, - 0.8297439545308815 + 2.8758575894902045, + 0.8297439526609495 ], "type": "Arc", "units": "in" @@ -1716,25 +1716,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.500000000133684, - 0.500000000142576 + 2.5000000001328506, + 0.5000000001419687 ], "from": [ - 2.6443869305745222, - 0.7281499843442172 + 2.6443869328963747, + 0.7281499835711335 ], - "radius": 0.2700000018024751, + "radius": 0.27000000239182703, "tag": { - "commentStart": 9174, - "end": 9181, + "commentStart": 9237, + "end": 9244, "moduleId": 0, - "start": 9174, + "start": 9237, "type": "TagDeclarator", "value": "o2Arc03" }, "to": [ - 2.2824776996294527, - 0.3400498524193454 + 2.2824776981457813, + 0.34004985344046407 ], "type": "Arc", "units": "in" @@ -1745,20 +1745,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1972777829522534, - 0.10205620973017071 + 2.197277780045819, + 0.10205621097433053 ], "tag": { - "commentStart": 9570, - "end": 9578, + "commentStart": 9633, + "end": 9641, "moduleId": 0, - "start": 9570, + "start": 9633, "type": "TagDeclarator", "value": "o2Line03" }, "to": [ - 2.355613068486364, - 0.271850015629843 + 2.355613066204165, + 0.2718500163736707 ], "type": "ToPoint", "units": "in" @@ -1797,12 +1797,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -1964,10 +1964,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9289, - "end": 9296, + "commentStart": 9352, + "end": 9359, "moduleId": 0, - "start": 9289, + "start": 9352, "type": "TagDeclarator", "value": "o2Arc04" }, @@ -1978,10 +1978,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9404, - "end": 9412, + "commentStart": 9467, + "end": 9475, "moduleId": 0, - "start": 9404, + "start": 9467, "type": "TagDeclarator", "value": "o2Line01" }, @@ -1992,10 +1992,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9488, - "end": 9496, + "commentStart": 9551, + "end": 9559, "moduleId": 0, - "start": 9488, + "start": 9551, "type": "TagDeclarator", "value": "o2Line02" }, @@ -2006,10 +2006,10 @@ description: Variables in memory after executing zoo-logo.kcl "id": "[uuid]", "sourceRange": [], "tag": { - "commentStart": 9652, - "end": 9660, + "commentStart": 9715, + "end": 9723, "moduleId": 0, - "start": 9652, + "start": 9715, "type": "TagDeclarator", "value": "o2Line04" }, @@ -2028,25 +2028,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.50000000000086, - 0.5000000000000057 + 2.500000000000816, + 0.5000000000002371 ], "from": [ - 2.355613068512856, - 0.27185001567166317 + 2.3556130662305046, + 0.27185001641524137 ], - "radius": 0.27000000246952705, + "radius": 0.2700000030619002, "tag": { - "commentStart": 9289, - "end": 9296, + "commentStart": 9352, + "end": 9359, "moduleId": 0, - "start": 9289, + "start": 9352, "type": "TagDeclarator", "value": "o2Arc04" }, "to": [ - 2.71752230073452, - 0.6599501485372291 + 2.7175223022479003, + 0.6599501474792382 ], "type": "Arc", "units": "in" @@ -2057,20 +2057,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1241424133176126, - 0.17025604666800587 + 2.124142411384393, + 0.17025604921278056 ], "tag": { - "commentStart": 9404, - "end": 9412, + "commentStart": 9467, + "end": 9475, "moduleId": 0, - "start": 9404, + "start": 9467, "type": "TagDeclarator", "value": "o2Line01" }, "to": [ - 2.282477701147848, - 0.34004985353583894 + 2.2824777003694794, + 0.34004985507559454 ], "type": "ToPoint", "units": "in" @@ -2081,20 +2081,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.6443869306011063, - 0.7281499843861835 + 2.644386932922806, + 0.7281499836128499 ], "tag": { - "commentStart": 9488, - "end": 9496, + "commentStart": 9551, + "end": 9559, "moduleId": 0, - "start": 9488, + "start": 9551, "type": "TagDeclarator", "value": "o2Line02" }, "to": [ - 2.802722216549035, - 0.8979437908828091 + 2.802722219434765, + 0.8979437896583012 ], "type": "ToPoint", "units": "in" @@ -2105,20 +2105,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.7175222979387295, - 0.6599501464814688 + 2.7175222987567156, + 0.6599501449121116 ], "tag": { - "commentStart": 9652, - "end": 9660, + "commentStart": 9715, + "end": 9723, "moduleId": 0, - "start": 9652, + "start": 9715, "type": "TagDeclarator", "value": "o2Line04" }, "to": [ - 2.8758575862723452, - 0.8297439540444097 + 2.8758575881862294, + 0.8297439515169935 ], "type": "ToPoint", "units": "in" @@ -2157,12 +2157,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -2347,7 +2347,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.0000000000006440519118786756, + "n": 0.0000000000006108599792405233, "ty": { "in": null, "type": "Known", @@ -2355,7 +2355,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": -0.00000000000027413177987219153, + "n": -0.00000000000015999475270707247, "ty": { "in": null, "type": "Known", @@ -2365,7 +2365,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 3.0000000000008167, + "n": 3.000000000000775, "ty": { "in": null, "type": "Known", @@ -2373,7 +2373,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": -0.00000000000016834437184936211, + "n": 0.00000000000006454610653354578, "ty": { "in": null, "type": "Known", @@ -2468,7 +2468,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.0000000000006520020892822867, + "n": 0.0000000000005770087115273643, "ty": { "in": null, "type": "Known", @@ -2476,7 +2476,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9999999999997217, + "n": 0.9999999999997923, "ty": { "in": null, "type": "Known", @@ -2486,7 +2486,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.0000000000006440518471737259, + "n": 0.0000000000006108613311521401, "ty": { "in": null, "type": "Known", @@ -2494,7 +2494,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": -0.00000000000036115068442778974, + "n": -0.0000000000002903759863256353, "ty": { "in": null, "type": "Known", @@ -2589,7 +2589,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 3.0000000000008167, + "n": 3.000000000000775, "ty": { "in": null, "type": "Known", @@ -2597,7 +2597,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": -0.00000000000008132583320762857, + "n": 0.00000000000015088455794429679, "ty": { "in": null, "type": "Known", @@ -2607,7 +2607,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 3.0000000000007816, + "n": 3.0000000000007, "ty": { "in": null, "type": "Known", @@ -2615,7 +2615,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9999999999998169, + "n": 0.9999999999999942, "ty": { "in": null, "type": "Known", @@ -2710,7 +2710,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 3.0000000000007385, + "n": 3.000000000000659, "ty": { "in": null, "type": "Known", @@ -2718,7 +2718,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9999999999998169, + "n": 0.9999999999999942, "ty": { "in": null, "type": "Known", @@ -2728,7 +2728,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.0000000000006952147184818856, + "n": 0.0000000000006179825860300944, "ty": { "in": null, "type": "Known", @@ -2736,7 +2736,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9999999999997217, + "n": 0.9999999999997922, "ty": { "in": null, "type": "Known", @@ -2834,8 +2834,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "tag": { "commentStart": 1074, @@ -2846,8 +2846,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine01" }, "to": [ - 0.0250000000019479, - 0.16500000320161995 + 0.02500000000191471, + 0.16500000320169073 ], "type": "ToPoint", "units": "in" @@ -2858,8 +2858,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.0250000000019479, - 0.16500000320161995 + 0.02500000000191471, + 0.16500000320169073 ], "tag": { "commentStart": 1157, @@ -2870,8 +2870,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine02" }, "to": [ - 0.5722530846158204, - 0.7599999999993404 + 0.5722530846157872, + 0.759999999999411 ], "type": "ToPoint", "units": "in" @@ -2882,8 +2882,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.5722530846158204, - 0.7599999999993404 + 0.5722530846157872, + 0.759999999999411 ], "tag": { "commentStart": 1240, @@ -2894,8 +2894,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine03" }, "to": [ - 0.025000000003983447, - 0.759999999999515 + 0.025000000003950255, + 0.7599999999995856 ], "type": "ToPoint", "units": "in" @@ -2906,8 +2906,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000003983447, - 0.759999999999515 + 0.025000000003950255, + 0.7599999999995856 ], "tag": { "commentStart": 1323, @@ -2918,8 +2918,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine04" }, "to": [ - 0.025000000004661963, - 0.9749999999997455 + 0.025000000004628768, + 0.9749999999998161 ], "type": "ToPoint", "units": "in" @@ -2930,8 +2930,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000004661963, - 0.9749999999997455 + 0.025000000004628768, + 0.9749999999998161 ], "tag": { "commentStart": 1406, @@ -2942,8 +2942,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine05" }, "to": [ - 0.625000000005742, - 0.9749999999999464 + 0.6250000000057087, + 0.975000000000017 ], "type": "ToPoint", "units": "in" @@ -2954,8 +2954,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.625000000005742, - 0.9749999999999464 + 0.6250000000057087, + 0.975000000000017 ], "tag": { "commentStart": 1489, @@ -2966,8 +2966,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine06" }, "to": [ - 0.625000000007099, - 0.8173489912353609 + 0.6250000000070657, + 0.8173489912354314 ], "type": "ToPoint", "units": "in" @@ -2978,8 +2978,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.625000000007099, - 0.8173489912353609 + 0.6250000000070657, + 0.8173489912354314 ], "tag": { "commentStart": 1572, @@ -2990,8 +2990,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine07" }, "to": [ - 0.7699999999942422, - 0.9750000000023993 + 0.7699999999942091, + 0.9750000000024699 ], "type": "ToPoint", "units": "in" @@ -3002,8 +3002,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.7699999999942422, - 0.9750000000023993 + 0.7699999999942091, + 0.9750000000024699 ], "tag": { "commentStart": 1655, @@ -3014,8 +3014,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine08" }, "to": [ - 0.9099999999954762, - 0.9750000000018456 + 0.9099999999954431, + 0.9750000000019162 ], "type": "ToPoint", "units": "in" @@ -3026,8 +3026,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999954762, - 0.9750000000018456 + 0.9099999999954431, + 0.9750000000019162 ], "tag": { "commentStart": 1738, @@ -3038,8 +3038,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine09" }, "to": [ - 0.9099999999967102, - 0.8350000000018732 + 0.909999999996677, + 0.8350000000019439 ], "type": "ToPoint", "units": "in" @@ -3050,8 +3050,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999967102, - 0.8350000000018732 + 0.909999999996677, + 0.8350000000019439 ], "tag": { "commentStart": 1821, @@ -3062,8 +3062,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine10" }, "to": [ - 0.36274691369315737, - 0.23999999999845167 + 0.3627469136931242, + 0.23999999999852248 ], "type": "ToPoint", "units": "in" @@ -3074,8 +3074,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.36274691369315737, - 0.23999999999845167 + 0.3627469136931242, + 0.23999999999852248 ], "tag": { "commentStart": 1904, @@ -3086,8 +3086,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine11" }, "to": [ - 0.9099999999992231, - 0.23999999999841187 + 0.90999999999919, + 0.23999999999848265 ], "type": "ToPoint", "units": "in" @@ -3098,8 +3098,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999992231, - 0.23999999999841187 + 0.90999999999919, + 0.23999999999848265 ], "tag": { "commentStart": 1987, @@ -3110,8 +3110,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine12" }, "to": [ - 0.909999999999855, - 0.024999999998245644 + 0.909999999999822, + 0.02499999999831642 ], "type": "ToPoint", "units": "in" @@ -3122,8 +3122,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.909999999999855, - 0.024999999998245644 + 0.909999999999822, + 0.02499999999831642 ], "tag": { "commentStart": 2070, @@ -3134,8 +3134,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine13" }, "to": [ - 0.3100000000003626, - 0.024999999998138397 + 0.3100000000003294, + 0.024999999998209173 ], "type": "ToPoint", "units": "in" @@ -3146,8 +3146,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.3100000000003626, - 0.024999999998138397 + 0.3100000000003294, + 0.024999999998209173 ], "tag": { "commentStart": 2153, @@ -3158,8 +3158,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine14" }, "to": [ - 0.3100000000009166, - 0.1826510087623727 + 0.31000000000088346, + 0.18265100876244356 ], "type": "ToPoint", "units": "in" @@ -3170,8 +3170,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.3100000000009166, - 0.1826510087623727 + 0.31000000000088346, + 0.18265100876244356 ], "tag": { "commentStart": 2236, @@ -3182,8 +3182,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine15" }, "to": [ - 0.16500000015676336, - 0.024999999999429413 + 0.1650000001567301, + 0.02499999999950019 ], "type": "ToPoint", "units": "in" @@ -3194,8 +3194,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.16500000015676336, - 0.024999999999429413 + 0.1650000001567301, + 0.02499999999950019 ], "tag": { "commentStart": 2319, @@ -3206,8 +3206,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine16" }, "to": [ - 0.025000000000842026, - 0.024999999999440452 + 0.025000000000808834, + 0.024999999999511226 ], "type": "ToPoint", "units": "in" @@ -3218,13 +3218,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000000842026, - 0.024999999999440452 + 0.025000000000808834, + 0.024999999999511226 ], "tag": null, "to": [ - 1.7507222211478382, - 0.8979437861876547 + 1.7507222213373614, + 0.8979437865254067 ], "type": "ToPoint", "units": "in" @@ -3236,14 +3236,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000042939, - 0.4999999999963225 + 1.4480000000041913, + 0.4999999999964554 ], "from": [ - 1.7507222211478382, - 0.8979437861876547 + 1.7507222213373614, + 0.8979437865254067 ], - "radius": 0.5000000001423737, + "radius": 0.5000000005258884, "tag": { "commentStart": 5447, "end": 5454, @@ -3253,8 +3253,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc01" }, "to": [ - 1.0721424205345453, - 0.1702560385694067 + 1.072142420234361, + 0.17025603833005248 ], "type": "Arc", "units": "in" @@ -3265,13 +3265,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.0721424205345453, - 0.1702560385694067 + 1.072142420234361, + 0.17025603833005248 ], "tag": null, "to": [ - 1.592386935136791, - 0.7281499797400859 + 1.5923869355465465, + 0.7281499798248687 ], "type": "ToPoint", "units": "in" @@ -3283,14 +3283,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000814304, - 0.5000000000790455 + 1.448000000081533, + 0.500000000079401 ], "from": [ - 1.592386935136791, - 0.7281499797400859 + 1.5923869355465465, + 0.7281499798248687 ], - "radius": 0.2700000004333593, + "radius": 0.2700000007237691, "tag": { "commentStart": 5562, "end": 5569, @@ -3300,8 +3300,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc02" }, "to": [ - 1.230477706531429, - 0.34004984520959547 + 1.2304777064696815, + 0.34004984480384404 ], "type": "Arc", "units": "in" @@ -3312,13 +3312,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.230477706531429, - 0.34004984520959547 + 1.2304777064696815, + 0.34004984480384404 ], "tag": null, "to": [ - 1.145277791967196, - 0.10205620247917498 + 1.1452777916181331, + 0.10205620193818332 ], "type": "ToPoint", "units": "in" @@ -3330,14 +3330,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000307414, - 0.5000000000246562 + 1.4480000000305635, + 0.5000000000247096 ], "from": [ - 1.145277791967196, - 0.10205620247917498 + 1.1452777916181331, + 0.10205620193818332 ], - "radius": 0.5000000012597874, + "radius": 0.5000000019016289, "tag": { "commentStart": 5678, "end": 5685, @@ -3347,8 +3347,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc03" }, "to": [ - 1.8238575925373133, - 0.8297439482859565 + 1.8238575932140073, + 0.8297439484877219 ], "type": "Arc", "units": "in" @@ -3359,13 +3359,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.8238575925373133, - 0.8297439482859565 + 1.8238575932140073, + 0.8297439484877219 ], "tag": null, "to": [ - 1.3036130783117428, - 0.2718500105172791 + 1.3036130777154717, + 0.27185001040423934 ], "type": "ToPoint", "units": "in" @@ -3377,14 +3377,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4479999999270814, - 0.49999999991352684 + 1.4479999999267732, + 0.49999999991343663 ], "from": [ - 1.3036130783117428, - 0.2718500105172791 + 1.3036130777154717, + 0.27185001040423934 ], - "radius": 0.2700000014723368, + "radius": 0.27000000188648016, "tag": { "commentStart": 5793, "end": 5800, @@ -3394,8 +3394,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc04" }, "to": [ - 1.6655223039710587, - 0.6599501422656404 + 1.6655223042550238, + 0.6599501425780409 ], "type": "Arc", "units": "in" @@ -3406,13 +3406,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.6655223039710587, - 0.6599501422656404 + 1.6655223042550238, + 0.6599501425780409 ], "tag": null, "to": [ - 1.0721424207704, - 0.1702560387763178 + 1.0721424207747434, + 0.1702560388041387 ], "type": "ToPoint", "units": "in" @@ -3423,8 +3423,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.0721424207704, - 0.1702560387763178 + 1.0721424207747434, + 0.1702560388041387 ], "tag": { "commentStart": 5908, @@ -3435,8 +3435,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line01" }, "to": [ - 1.2304777073930173, - 0.3400498458431754 + 1.2304777076509616, + 0.34004984567246327 ], "type": "ToPoint", "units": "in" @@ -3447,13 +3447,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.2304777073930173, - 0.3400498458431754 + 1.2304777076509616, + 0.34004984567246327 ], "tag": null, "to": [ - 1.592386935167577, - 0.728149979788665 + 1.5923869355774285, + 0.7281499798735742 ], "type": "ToPoint", "units": "in" @@ -3464,8 +3464,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.592386935167577, - 0.728149979788665 + 1.5923869355774285, + 0.7281499798735742 ], "tag": { "commentStart": 5992, @@ -3476,8 +3476,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line02" }, "to": [ - 1.7507222211361029, - 0.897943786172192 + 1.7507222213256655, + 0.8979437865099826 ], "type": "ToPoint", "units": "in" @@ -3488,13 +3488,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.7507222211361029, - 0.897943786172192 + 1.7507222213256655, + 0.8979437865099826 ], "tag": null, "to": [ - 1.1452777919671395, - 0.10205620247922666 + 1.145277791618066, + 0.1020562019382462 ], "type": "ToPoint", "units": "in" @@ -3505,8 +3505,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.1452777919671395, - 0.10205620247922666 + 1.145277791618066, + 0.1020562019382462 ], "tag": { "commentStart": 6075, @@ -3517,8 +3517,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line03" }, "to": [ - 1.3036130782809365, - 0.2718500104686369 + 1.3036130776845802, + 0.27185001035546846 ], "type": "ToPoint", "units": "in" @@ -3529,13 +3529,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.3036130782809365, - 0.2718500104686369 + 1.3036130776845802, + 0.27185001035546846 ], "tag": null, "to": [ - 1.6655223064839437, - 0.6599501441136671 + 1.6655223058092399, + 0.659950143721114 ], "type": "ToPoint", "units": "in" @@ -3546,8 +3546,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.6655223064839437, - 0.6599501441136671 + 1.6655223058092399, + 0.659950143721114 ], "tag": { "commentStart": 6157, @@ -3558,8 +3558,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line04" }, "to": [ - 1.8238575928297183, - 0.8297439485420472 + 1.8238575926275662, + 0.8297439479727559 ], "type": "ToPoint", "units": "in" @@ -3570,13 +3570,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.8238575928297183, - 0.8297439485420472 + 1.8238575926275662, + 0.8297439479727559 ], "tag": null, "to": [ - 2.802722216551602, - 0.897943790886238 + 2.8027222194373516, + 0.897943789661772 ], "type": "ToPoint", "units": "in" @@ -3588,25 +3588,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.5000000000673026, - 0.5000000000713016 + 2.500000000066863, + 0.5000000000711139 ], "from": [ - 2.802722216551602, - 0.897943790886238 + 2.8027222194373516, + 0.897943789661772 ], - "radius": 0.5000000010013289, + "radius": 0.5000000017743682, "tag": { - "commentStart": 8948, - "end": 8955, + "commentStart": 9011, + "end": 9018, "moduleId": 0, - "start": 8948, + "start": 9011, "type": "TagDeclarator", "value": "o2Arc01" }, "to": [ - 2.1241424128079442, - 0.17025604622088947 + 2.1241424101241355, + 0.17025604810715045 ], "type": "Arc", "units": "in" @@ -3617,13 +3617,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1241424128079442, - 0.17025604622088947 + 2.1241424101241355, + 0.17025604810715045 ], "tag": null, "to": [ - 2.1972777829497114, - 0.10205620972677573 + 2.1972777800432586, + 0.1020562109708937 ], "type": "ToPoint", "units": "in" @@ -3635,25 +3635,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.5000000000731593, - 0.5000000000775605 + 2.5000000000727796, + 0.5000000000774375 ], "from": [ - 2.1972777829497114, - 0.10205620972677573 + 2.1972777800432586, + 0.1020562109708937 ], - "radius": 0.5000000010188852, + "radius": 0.5000000017880751, "tag": { - "commentStart": 9061, - "end": 9068, + "commentStart": 9124, + "end": 9131, "moduleId": 0, - "start": 9061, + "start": 9124, "type": "TagDeclarator", "value": "o2Arc02" }, "to": [ - 2.875857586826934, - 0.8297439545308815 + 2.8758575894902045, + 0.8297439526609495 ], "type": "Arc", "units": "in" @@ -3664,13 +3664,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.875857586826934, - 0.8297439545308815 + 2.8758575894902045, + 0.8297439526609495 ], "tag": null, "to": [ - 2.6443869305745222, - 0.7281499843442172 + 2.6443869328963747, + 0.7281499835711335 ], "type": "ToPoint", "units": "in" @@ -3682,25 +3682,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.500000000133684, - 0.500000000142576 + 2.5000000001328506, + 0.5000000001419687 ], "from": [ - 2.6443869305745222, - 0.7281499843442172 + 2.6443869328963747, + 0.7281499835711335 ], - "radius": 0.2700000018024751, + "radius": 0.27000000239182703, "tag": { - "commentStart": 9174, - "end": 9181, + "commentStart": 9237, + "end": 9244, "moduleId": 0, - "start": 9174, + "start": 9237, "type": "TagDeclarator", "value": "o2Arc03" }, "to": [ - 2.2824776996294527, - 0.3400498524193454 + 2.2824776981457813, + 0.34004985344046407 ], "type": "Arc", "units": "in" @@ -3711,13 +3711,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.2824776996294527, - 0.3400498524193454 + 2.2824776981457813, + 0.34004985344046407 ], "tag": null, "to": [ - 2.355613068512856, - 0.27185001567166317 + 2.3556130662305046, + 0.27185001641524137 ], "type": "ToPoint", "units": "in" @@ -3729,25 +3729,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.50000000000086, - 0.5000000000000057 + 2.500000000000816, + 0.5000000000002371 ], "from": [ - 2.355613068512856, - 0.27185001567166317 + 2.3556130662305046, + 0.27185001641524137 ], - "radius": 0.27000000246952705, + "radius": 0.2700000030619002, "tag": { - "commentStart": 9289, - "end": 9296, + "commentStart": 9352, + "end": 9359, "moduleId": 0, - "start": 9289, + "start": 9352, "type": "TagDeclarator", "value": "o2Arc04" }, "to": [ - 2.71752230073452, - 0.6599501485372291 + 2.7175223022479003, + 0.6599501474792382 ], "type": "Arc", "units": "in" @@ -3758,13 +3758,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.71752230073452, - 0.6599501485372291 + 2.7175223022479003, + 0.6599501474792382 ], "tag": null, "to": [ - 2.1241424133176126, - 0.17025604666800587 + 2.124142411384393, + 0.17025604921278056 ], "type": "ToPoint", "units": "in" @@ -3775,20 +3775,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1241424133176126, - 0.17025604666800587 + 2.124142411384393, + 0.17025604921278056 ], "tag": { - "commentStart": 9404, - "end": 9412, + "commentStart": 9467, + "end": 9475, "moduleId": 0, - "start": 9404, + "start": 9467, "type": "TagDeclarator", "value": "o2Line01" }, "to": [ - 2.282477701147848, - 0.34004985353583894 + 2.2824777003694794, + 0.34004985507559454 ], "type": "ToPoint", "units": "in" @@ -3799,13 +3799,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.282477701147848, - 0.34004985353583894 + 2.2824777003694794, + 0.34004985507559454 ], "tag": null, "to": [ - 2.6443869306011063, - 0.7281499843861835 + 2.644386932922806, + 0.7281499836128499 ], "type": "ToPoint", "units": "in" @@ -3816,20 +3816,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.6443869306011063, - 0.7281499843861835 + 2.644386932922806, + 0.7281499836128499 ], "tag": { - "commentStart": 9488, - "end": 9496, + "commentStart": 9551, + "end": 9559, "moduleId": 0, - "start": 9488, + "start": 9551, "type": "TagDeclarator", "value": "o2Line02" }, "to": [ - 2.802722216549035, - 0.8979437908828091 + 2.802722219434765, + 0.8979437896583012 ], "type": "ToPoint", "units": "in" @@ -3840,13 +3840,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.802722216549035, - 0.8979437908828091 + 2.802722219434765, + 0.8979437896583012 ], "tag": null, "to": [ - 2.1972777829522534, - 0.10205620973017071 + 2.197277780045819, + 0.10205621097433053 ], "type": "ToPoint", "units": "in" @@ -3857,20 +3857,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1972777829522534, - 0.10205620973017071 + 2.197277780045819, + 0.10205621097433053 ], "tag": { - "commentStart": 9570, - "end": 9578, + "commentStart": 9633, + "end": 9641, "moduleId": 0, - "start": 9570, + "start": 9633, "type": "TagDeclarator", "value": "o2Line03" }, "to": [ - 2.355613068486364, - 0.271850015629843 + 2.355613066204165, + 0.2718500163736707 ], "type": "ToPoint", "units": "in" @@ -3881,13 +3881,13 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.355613068486364, - 0.271850015629843 + 2.355613066204165, + 0.2718500163736707 ], "tag": null, "to": [ - 2.7175222979387295, - 0.6599501464814688 + 2.7175222987567156, + 0.6599501449121116 ], "type": "ToPoint", "units": "in" @@ -3898,20 +3898,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.7175222979387295, - 0.6599501464814688 + 2.7175222987567156, + 0.6599501449121116 ], "tag": { - "commentStart": 9652, - "end": 9660, + "commentStart": 9715, + "end": 9723, "moduleId": 0, - "start": 9652, + "start": 9715, "type": "TagDeclarator", "value": "o2Line04" }, "to": [ - 2.8758575862723452, - 0.8297439540444097 + 2.8758575881862294, + 0.8297439515169935 ], "type": "ToPoint", "units": "in" @@ -3950,12 +3950,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -4115,7 +4115,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.7507222211478382, + "n": 1.7507222213373614, "ty": { "in": null, "type": "Known", @@ -4123,7 +4123,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437861876547, + "n": 0.8979437865254067, "ty": { "in": null, "type": "Known", @@ -4133,7 +4133,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.072142420784981, + "n": 1.072142420789288, "ty": { "in": null, "type": "Known", @@ -4141,7 +4141,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.1702560387891165, + "n": 0.17025603881689574, "ty": { "in": null, "type": "Known", @@ -4151,7 +4151,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.4480000000042939, + "n": 1.4480000000041913, "ty": { "in": null, "type": "Known", @@ -4159,7 +4159,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.4999999999963225, + "n": 0.4999999999964554, "ty": { "in": null, "type": "Known", @@ -4267,7 +4267,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.592386935136791, + "n": 1.5923869355465465, "ty": { "in": null, "type": "Known", @@ -4275,7 +4275,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499797400859, + "n": 0.7281499798248687, "ty": { "in": null, "type": "Known", @@ -4285,7 +4285,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.2304777073930229, + "n": 1.2304777076509446, "ty": { "in": null, "type": "Known", @@ -4293,7 +4293,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.34004984584314923, + "n": 0.34004984567245955, "ty": { "in": null, "type": "Known", @@ -4303,7 +4303,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.4480000000814304, + "n": 1.448000000081533, "ty": { "in": null, "type": "Known", @@ -4311,7 +4311,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000790455, + "n": 0.500000000079401, "ty": { "in": null, "type": "Known", @@ -4419,7 +4419,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.145277791967196, + "n": 1.1452777916181331, "ty": { "in": null, "type": "Known", @@ -4427,7 +4427,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.10205620247917498, + "n": 0.10205620193818332, "ty": { "in": null, "type": "Known", @@ -4437,7 +4437,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.8238575928294605, + "n": 1.823857592627288, "ty": { "in": null, "type": "Known", @@ -4445,7 +4445,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439485422603, + "n": 0.8297439479729868, "ty": { "in": null, "type": "Known", @@ -4455,7 +4455,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.4480000000307414, + "n": 1.4480000000305635, "ty": { "in": null, "type": "Known", @@ -4463,7 +4463,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000246562, + "n": 0.5000000000247096, "ty": { "in": null, "type": "Known", @@ -4571,7 +4571,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.3036130783117428, + "n": 1.3036130777154717, "ty": { "in": null, "type": "Known", @@ -4579,7 +4579,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.2718500105172791, + "n": 0.27185001040423934, "ty": { "in": null, "type": "Known", @@ -4589,7 +4589,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.6655223065304074, + "n": 1.6655223058558224, "ty": { "in": null, "type": "Known", @@ -4597,7 +4597,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501441476, + "n": 0.6599501437551524, "ty": { "in": null, "type": "Known", @@ -4607,7 +4607,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.4479999999270814, + "n": 1.4479999999267732, "ty": { "in": null, "type": "Known", @@ -4615,7 +4615,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.49999999991352684, + "n": 0.49999999991343674, "ty": { "in": null, "type": "Known", @@ -4723,7 +4723,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.230477707439384, + "n": 1.2304777076974038, "ty": { "in": null, "type": "Known", @@ -4731,7 +4731,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.34004984587719633, + "n": 0.34004984570662444, "ty": { "in": null, "type": "Known", @@ -4741,7 +4741,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.592386935166972, + "n": 1.592386935576899, "ty": { "in": null, "type": "Known", @@ -4749,7 +4749,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499797883131, + "n": 0.7281499798732277, "ty": { "in": null, "type": "Known", @@ -4844,7 +4844,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.3036130782500444, + "n": 1.3036130776535821, "ty": { "in": null, "type": "Known", @@ -4852,7 +4852,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.27185001042011436, + "n": 0.2718500103068354, "ty": { "in": null, "type": "Known", @@ -4862,7 +4862,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.665522306484501, + "n": 1.6655223058097939, "ty": { "in": null, "type": "Known", @@ -4870,7 +4870,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.659950144114069, + "n": 0.6599501437214434, "ty": { "in": null, "type": "Known", @@ -4965,7 +4965,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.2304777074851363, + "n": 1.2304777077433309, "ty": { "in": null, "type": "Known", @@ -4973,7 +4973,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.34004984591084797, + "n": 0.3400498457404005, "ty": { "in": null, "type": "Known", @@ -4983,7 +4983,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.3036130782196804, + "n": 1.3036130776231079, "ty": { "in": null, "type": "Known", @@ -4991,7 +4991,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.2718500103720809, + "n": 0.2718500102586179, "ty": { "in": null, "type": "Known", @@ -5001,7 +5001,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.447999999988914, + "n": 1.4479999999887532, "ty": { "in": null, "type": "Known", @@ -5009,7 +5009,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.500000000010678, + "n": 0.5000000000108649, "ty": { "in": null, "type": "Known", @@ -5118,7 +5118,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.0721424207558177, + "n": 1.072142420760209, "ty": { "in": null, "type": "Known", @@ -5126,7 +5126,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.17025603876353174, + "n": 0.17025603879138423, "ty": { "in": null, "type": "Known", @@ -5136,7 +5136,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.145277791978959, + "n": 1.1452777916298675, "ty": { "in": null, "type": "Known", @@ -5144,7 +5144,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.10205620249457759, + "n": 0.10205620195353608, "ty": { "in": null, "type": "Known", @@ -5154,7 +5154,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.448000000007131, + "n": 1.44800000000702, "ty": { "in": null, "type": "Known", @@ -5162,7 +5162,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.49999999999367745, + "n": 0.4999999999938181, "ty": { "in": null, "type": "Known", @@ -5271,7 +5271,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.6655223064371096, + "n": 1.6655223057623185, "ty": { "in": null, "type": "Known", @@ -5279,7 +5279,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501440791777, + "n": 0.6599501436865645, "ty": { "in": null, "type": "Known", @@ -5289,7 +5289,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.5923869351986755, + "n": 1.5923869356085794, "ty": { "in": null, "type": "Known", @@ -5297,7 +5297,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499798378437, + "n": 0.7281499799228451, "ty": { "in": null, "type": "Known", @@ -5307,7 +5307,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.4480000000200541, + "n": 1.4480000000199804, "ty": { "in": null, "type": "Known", @@ -5315,7 +5315,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.49999999998161593, + "n": 0.49999999998172223, "ty": { "in": null, "type": "Known", @@ -5424,7 +5424,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 1.8238575928438718, + "n": 1.8238575926416423, "ty": { "in": null, "type": "Known", @@ -5432,7 +5432,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439485553916, + "n": 0.8297439479860943, "ty": { "in": null, "type": "Known", @@ -5442,7 +5442,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.7507222211246785, + "n": 1.7507222213142581, "ty": { "in": null, "type": "Known", @@ -5450,7 +5450,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437861564394, + "n": 0.897943786494291, "ty": { "in": null, "type": "Known", @@ -5460,7 +5460,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 1.448000000001047, + "n": 1.4480000000009827, "ty": { "in": null, "type": "Known", @@ -5468,7 +5468,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.4999999999993062, + "n": 0.49999999999940453, "ty": { "in": null, "type": "Known", @@ -5577,7 +5577,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.0721424207704, + "n": 1.0721424207747434, "ty": { "in": null, "type": "Known", @@ -5585,7 +5585,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.1702560387763178, + "n": 0.1702560388041387, "ty": { "in": null, "type": "Known", @@ -5595,7 +5595,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.2304777073930173, + "n": 1.2304777076509616, "ty": { "in": null, "type": "Known", @@ -5603,7 +5603,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.3400498458431754, + "n": 0.34004984567246327, "ty": { "in": null, "type": "Known", @@ -5697,7 +5697,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.592386935167577, + "n": 1.5923869355774285, "ty": { "in": null, "type": "Known", @@ -5705,7 +5705,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.728149979788665, + "n": 0.7281499798735742, "ty": { "in": null, "type": "Known", @@ -5715,7 +5715,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.7507222211361029, + "n": 1.7507222213256655, "ty": { "in": null, "type": "Known", @@ -5723,7 +5723,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.897943786172192, + "n": 0.8979437865099826, "ty": { "in": null, "type": "Known", @@ -5817,7 +5817,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.1452777919671395, + "n": 1.145277791618066, "ty": { "in": null, "type": "Known", @@ -5825,7 +5825,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.10205620247922666, + "n": 0.1020562019382462, "ty": { "in": null, "type": "Known", @@ -5835,7 +5835,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.3036130782809365, + "n": 1.3036130776845802, "ty": { "in": null, "type": "Known", @@ -5843,7 +5843,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.2718500104686369, + "n": 0.27185001035546846, "ty": { "in": null, "type": "Known", @@ -5937,7 +5937,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.6655223064839437, + "n": 1.6655223058092399, "ty": { "in": null, "type": "Known", @@ -5945,7 +5945,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501441136671, + "n": 0.659950143721114, "ty": { "in": null, "type": "Known", @@ -5955,7 +5955,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.8238575928297183, + "n": 1.8238575926275662, "ty": { "in": null, "type": "Known", @@ -5963,7 +5963,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439485420472, + "n": 0.8297439479727559, "ty": { "in": null, "type": "Known", @@ -6057,7 +6057,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.7507222211246625, + "n": 1.7507222213142362, "ty": { "in": null, "type": "Known", @@ -6065,7 +6065,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437861564811, + "n": 0.8979437864943464, "ty": { "in": null, "type": "Known", @@ -6075,7 +6075,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.5923869351367725, + "n": 1.592386935546507, "ty": { "in": null, "type": "Known", @@ -6083,7 +6083,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437861565088, + "n": 0.8979437864943833, "ty": { "in": null, "type": "Known", @@ -6178,7 +6178,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.5923869351367816, + "n": 1.5923869355465268, "ty": { "in": null, "type": "Known", @@ -6186,7 +6186,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499797401131, + "n": 0.728149979824898, "ty": { "in": null, "type": "Known", @@ -6196,7 +6196,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.5923869351367756, + "n": 1.5923869355465137, "ty": { "in": null, "type": "Known", @@ -6204,7 +6204,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437861565227, + "n": 0.8979437864944019, "ty": { "in": null, "type": "Known", @@ -6299,7 +6299,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.6655223065304352, + "n": 1.6655223058558477, "ty": { "in": null, "type": "Known", @@ -6307,7 +6307,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.659950144147466, + "n": 0.6599501437550286, "ty": { "in": null, "type": "Known", @@ -6317,7 +6317,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.8238575928441336, + "n": 1.8238575926418739, "ty": { "in": null, "type": "Known", @@ -6325,7 +6325,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501441473766, + "n": 0.659950143754946, "ty": { "in": null, "type": "Known", @@ -6420,7 +6420,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 1.8238575928440026, + "n": 1.8238575926417582, "ty": { "in": null, "type": "Known", @@ -6428,7 +6428,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439485553788, + "n": 0.8297439479860872, "ty": { "in": null, "type": "Known", @@ -6438,7 +6438,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 1.82385759284409, + "n": 1.8238575926418352, "ty": { "in": null, "type": "Known", @@ -6446,7 +6446,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.659950144147332, + "n": 0.6599501437549047, "ty": { "in": null, "type": "Known", @@ -6541,7 +6541,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.802722216551602, + "n": 2.8027222194373516, "ty": { "in": null, "type": "Known", @@ -6549,7 +6549,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.897943790886238, + "n": 0.897943789661772, "ty": { "in": null, "type": "Known", @@ -6559,7 +6559,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.1241424133208087, + "n": 2.1241424113876297, "ty": { "in": null, "type": "Known", @@ -6567,7 +6567,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.170256046670831, + "n": 0.17025604921562745, "ty": { "in": null, "type": "Known", @@ -6577,7 +6577,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.5000000000673026, + "n": 2.500000000066863, "ty": { "in": null, "type": "Known", @@ -6585,7 +6585,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000713016, + "n": 0.5000000000711139, "ty": { "in": null, "type": "Known", @@ -6693,7 +6693,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.1972777829497114, + "n": 2.1972777800432586, "ty": { "in": null, "type": "Known", @@ -6701,7 +6701,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.10205620972677573, + "n": 0.1020562109708937, "ty": { "in": null, "type": "Known", @@ -6711,7 +6711,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.875857586269125, + "n": 2.875857588182949, "ty": { "in": null, "type": "Known", @@ -6719,7 +6719,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439540415096, + "n": 0.8297439515140798, "ty": { "in": null, "type": "Known", @@ -6729,7 +6729,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.5000000000731593, + "n": 2.5000000000727796, "ty": { "in": null, "type": "Known", @@ -6737,7 +6737,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000775605, + "n": 0.5000000000774375, "ty": { "in": null, "type": "Known", @@ -6845,7 +6845,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.6443869305745222, + "n": 2.6443869328963747, "ty": { "in": null, "type": "Known", @@ -6853,7 +6853,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499843442172, + "n": 0.7281499835711335, "ty": { "in": null, "type": "Known", @@ -6863,7 +6863,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.2824777011080344, + "n": 2.2824777003299057, "ty": { "in": null, "type": "Known", @@ -6871,7 +6871,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.34004985350658745, + "n": 0.34004985504651086, "ty": { "in": null, "type": "Known", @@ -6881,7 +6881,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.500000000133684, + "n": 2.5000000001328506, "ty": { "in": null, "type": "Known", @@ -6889,7 +6889,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.500000000142576, + "n": 0.5000000001419687, "ty": { "in": null, "type": "Known", @@ -6997,7 +6997,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.355613068512856, + "n": 2.3556130662305046, "ty": { "in": null, "type": "Known", @@ -7005,7 +7005,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.27185001567166317, + "n": 0.27185001641524137, "ty": { "in": null, "type": "Known", @@ -7015,7 +7015,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.7175222979786704, + "n": 2.717522298796414, "ty": { "in": null, "type": "Known", @@ -7023,7 +7023,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501465107768, + "n": 0.6599501449412652, "ty": { "in": null, "type": "Known", @@ -7033,7 +7033,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.50000000000086, + "n": 2.500000000000816, "ty": { "in": null, "type": "Known", @@ -7041,7 +7041,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000000057, + "n": 0.5000000000002373, "ty": { "in": null, "type": "Known", @@ -7149,7 +7149,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.282477701187711, + "n": 2.282477700409077, "ty": { "in": null, "type": "Known", @@ -7157,7 +7157,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.34004985356504736, + "n": 0.3400498551046612, "ty": { "in": null, "type": "Known", @@ -7167,7 +7167,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.644386930627515, + "n": 2.644386932949081, "ty": { "in": null, "type": "Known", @@ -7175,7 +7175,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499844282676, + "n": 0.728149983654668, "ty": { "in": null, "type": "Known", @@ -7270,7 +7270,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.355613068459799, + "n": 2.355613066177681, "ty": { "in": null, "type": "Known", @@ -7278,7 +7278,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.2718500155881344, + "n": 0.27185001633227673, "ty": { "in": null, "type": "Known", @@ -7288,7 +7288,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.7175222978990003, + "n": 2.717522298717291, "ty": { "in": null, "type": "Known", @@ -7296,7 +7296,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501464519572, + "n": 0.6599501448826954, "ty": { "in": null, "type": "Known", @@ -7391,7 +7391,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.124142413314401, + "n": 2.1241424113811576, "ty": { "in": null, "type": "Known", @@ -7399,7 +7399,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.17025604666520974, + "n": 0.17025604920994916, "ty": { "in": null, "type": "Known", @@ -7409,7 +7409,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.197277782954845, + "n": 2.197277780048444, "ty": { "in": null, "type": "Known", @@ -7417,7 +7417,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.10205620973352485, + "n": 0.10205621097771148, "ty": { "in": null, "type": "Known", @@ -7427,7 +7427,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.500000000067924, + "n": 2.5000000000674905, "ty": { "in": null, "type": "Known", @@ -7435,7 +7435,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000707221, + "n": 0.5000000000705287, "ty": { "in": null, "type": "Known", @@ -7544,7 +7544,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.2824777012275255, + "n": 2.282477700448665, "ty": { "in": null, "type": "Known", @@ -7552,7 +7552,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.3400498535943408, + "n": 0.34004985513378255, "ty": { "in": null, "type": "Known", @@ -7562,7 +7562,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.3556130684333665, + "n": 2.3556130661514056, "ty": { "in": null, "type": "Known", @@ -7570,7 +7570,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.27185001554630894, + "n": 0.27185001629068795, "ty": { "in": null, "type": "Known", @@ -7580,7 +7580,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.500000000053909, + "n": 2.500000000053546, "ty": { "in": null, "type": "Known", @@ -7588,7 +7588,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000837983, + "n": 0.5000000000835383, "ty": { "in": null, "type": "Known", @@ -7697,7 +7697,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.717522297859121, + "n": 2.717522298677638, "ty": { "in": null, "type": "Known", @@ -7705,7 +7705,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501464226163, + "n": 0.6599501448535265, "ty": { "in": null, "type": "Known", @@ -7715,7 +7715,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.6443869306539884, + "n": 2.6443869329753826, "ty": { "in": null, "type": "Known", @@ -7723,7 +7723,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499844702103, + "n": 0.7281499836963766, "ty": { "in": null, "type": "Known", @@ -7733,7 +7733,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.500000000080718, + "n": 2.5000000000802016, "ty": { "in": null, "type": "Known", @@ -7741,7 +7741,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.500000000058784, + "n": 0.5000000000586683, "ty": { "in": null, "type": "Known", @@ -7850,7 +7850,7 @@ description: Variables in memory after executing zoo-logo.kcl "arc": { "start": [ { - "n": 2.8758575862753193, + "n": 2.8758575881892123, "ty": { "in": null, "type": "Known", @@ -7858,7 +7858,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439540475273, + "n": 0.8297439515201714, "ty": { "in": null, "type": "Known", @@ -7868,7 +7868,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.8027222165466665, + "n": 2.802722219432372, "ty": { "in": null, "type": "Known", @@ -7876,7 +7876,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437908791917, + "n": 0.8979437896546492, "ty": { "in": null, "type": "Known", @@ -7886,7 +7886,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "center": [ { - "n": 2.5000000000666702, + "n": 2.500000000066223, "ty": { "in": null, "type": "Known", @@ -7894,7 +7894,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.5000000000718912, + "n": 0.5000000000717101, "ty": { "in": null, "type": "Known", @@ -8003,7 +8003,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.1241424133176126, + "n": 2.124142411384393, "ty": { "in": null, "type": "Known", @@ -8011,7 +8011,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.17025604666800587, + "n": 0.17025604921278056, "ty": { "in": null, "type": "Known", @@ -8021,7 +8021,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.282477701147848, + "n": 2.2824777003694794, "ty": { "in": null, "type": "Known", @@ -8029,7 +8029,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.34004985353583894, + "n": 0.34004985507559454, "ty": { "in": null, "type": "Known", @@ -8123,7 +8123,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.6443869306011063, + "n": 2.644386932922806, "ty": { "in": null, "type": "Known", @@ -8131,7 +8131,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499843861835, + "n": 0.7281499836128499, "ty": { "in": null, "type": "Known", @@ -8141,7 +8141,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.802722216549035, + "n": 2.802722219434765, "ty": { "in": null, "type": "Known", @@ -8149,7 +8149,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437908828091, + "n": 0.8979437896583012, "ty": { "in": null, "type": "Known", @@ -8243,7 +8243,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.1972777829522534, + "n": 2.197277780045819, "ty": { "in": null, "type": "Known", @@ -8251,7 +8251,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.10205620973017071, + "n": 0.10205621097433053, "ty": { "in": null, "type": "Known", @@ -8261,7 +8261,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.355613068486364, + "n": 2.355613066204165, "ty": { "in": null, "type": "Known", @@ -8269,7 +8269,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.271850015629843, + "n": 0.2718500163736707, "ty": { "in": null, "type": "Known", @@ -8363,7 +8363,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.7175222979387295, + "n": 2.7175222987567156, "ty": { "in": null, "type": "Known", @@ -8371,7 +8371,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501464814688, + "n": 0.6599501449121116, "ty": { "in": null, "type": "Known", @@ -8381,7 +8381,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.8758575862723452, + "n": 2.8758575881862294, "ty": { "in": null, "type": "Known", @@ -8389,7 +8389,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439540444097, + "n": 0.8297439515169935, "ty": { "in": null, "type": "Known", @@ -8483,7 +8483,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.802722216546644, + "n": 2.8027222194323413, "ty": { "in": null, "type": "Known", @@ -8491,7 +8491,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.897943790879263, + "n": 0.8979437896547389, "ty": { "in": null, "type": "Known", @@ -8501,7 +8501,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.6443869306539796, + "n": 2.6443869329753453, "ty": { "in": null, "type": "Known", @@ -8509,7 +8509,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437908793105, + "n": 0.8979437896547987, "ty": { "in": null, "type": "Known", @@ -8604,7 +8604,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.644386930653984, + "n": 2.644386932975364, "ty": { "in": null, "type": "Known", @@ -8612,7 +8612,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7281499844702567, + "n": 0.7281499836964259, "ty": { "in": null, "type": "Known", @@ -8622,7 +8622,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.644386930653981, + "n": 2.6443869329753515, "ty": { "in": null, "type": "Known", @@ -8630,7 +8630,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8979437908793343, + "n": 0.8979437896548286, "ty": { "in": null, "type": "Known", @@ -8725,7 +8725,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.717522297978686, + "n": 2.717522298796426, "ty": { "in": null, "type": "Known", @@ -8733,7 +8733,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501465107503, + "n": 0.6599501449412521, "ty": { "in": null, "type": "Known", @@ -8743,7 +8743,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.875857586269235, + "n": 2.8758575881830177, "ty": { "in": null, "type": "Known", @@ -8751,7 +8751,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501465107326, + "n": 0.6599501449412435, "ty": { "in": null, "type": "Known", @@ -8846,7 +8846,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 2.8758575862691798, + "n": 2.8758575881829835, "ty": { "in": null, "type": "Known", @@ -8854,7 +8854,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8297439540415041, + "n": 0.8297439515140821, "ty": { "in": null, "type": "Known", @@ -8864,7 +8864,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 2.8758575862692166, + "n": 2.8758575881830066, "ty": { "in": null, "type": "Known", @@ -8872,7 +8872,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.6599501465107238, + "n": 0.6599501449412392, "ty": { "in": null, "type": "Known", @@ -8967,7 +8967,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.5722530846156333, + "n": 0.5722530846156001, "ty": { "in": null, "type": "Known", @@ -8975,7 +8975,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7599999999995126, + "n": 0.7599999999995832, "ty": { "in": null, "type": "Known", @@ -8985,7 +8985,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.625000000007839, + "n": 0.6250000000078058, "ty": { "in": null, "type": "Known", @@ -8993,7 +8993,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8173489912348649, + "n": 0.8173489912349354, "ty": { "in": null, "type": "Known", @@ -9088,7 +9088,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.31000000000126693, + "n": 0.31000000000123373, "ty": { "in": null, "type": "Known", @@ -9096,7 +9096,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.1826510087618659, + "n": 0.18265100876193677, "ty": { "in": null, "type": "Known", @@ -9106,7 +9106,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.3627469136930691, + "n": 0.36274691369303586, "ty": { "in": null, "type": "Known", @@ -9114,7 +9114,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.2399999999985329, + "n": 0.2399999999986037, "ty": { "in": null, "type": "Known", @@ -9209,7 +9209,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.16500000015696709, + "n": 0.1650000001569338, "ty": { "in": null, "type": "Known", @@ -9217,7 +9217,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999998856295, + "n": 0.024999999998927068, "ty": { "in": null, "type": "Known", @@ -9227,7 +9227,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.3100000000006396, + "n": 0.3100000000006064, "ty": { "in": null, "type": "Known", @@ -9235,7 +9235,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999998470534, + "n": 0.02499999999854131, "ty": { "in": null, "type": "Known", @@ -9330,7 +9330,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.025000000002626418, + "n": 0.025000000002593226, "ty": { "in": null, "type": "Known", @@ -9338,7 +9338,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.16500000320158142, + "n": 0.1650000032016522, "ty": { "in": null, "type": "Known", @@ -9348,7 +9348,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.025000000003304934, + "n": 0.02500000000327174, "ty": { "in": null, "type": "Known", @@ -9356,7 +9356,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.759999999999574, + "n": 0.7599999999996445, "ty": { "in": null, "type": "Known", @@ -9451,7 +9451,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.6250000000064204, + "n": 0.6250000000063872, "ty": { "in": null, "type": "Known", @@ -9459,7 +9459,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000006694, + "n": 0.97500000000074, "ty": { "in": null, "type": "Known", @@ -9469,7 +9469,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.7699999999948592, + "n": 0.769999999994826, "ty": { "in": null, "type": "Known", @@ -9477,7 +9477,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000012506, + "n": 0.9750000000013213, "ty": { "in": null, "type": "Known", @@ -9572,7 +9572,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.9099999999979591, + "n": 0.909999999997926, "ty": { "in": null, "type": "Known", @@ -9580,7 +9580,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.835000000001887, + "n": 0.8350000000019576, "ty": { "in": null, "type": "Known", @@ -9590,7 +9590,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.9099999999985912, + "n": 0.909999999998558, "ty": { "in": null, "type": "Known", @@ -9598,7 +9598,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.23999999999835825, + "n": 0.23999999999842903, "ty": { "in": null, "type": "Known", @@ -9693,7 +9693,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.025000000001394965, + "n": 0.025000000001361773, "ty": { "in": null, "type": "Known", @@ -9701,7 +9701,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999999440452, + "n": 0.024999999999511226, "ty": { "in": null, "type": "Known", @@ -9711,7 +9711,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.0250000000019479, + "n": 0.02500000000191471, "ty": { "in": null, "type": "Known", @@ -9719,7 +9719,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.16500000320161995, + "n": 0.16500000320169073, "ty": { "in": null, "type": "Known", @@ -9813,7 +9813,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.025000000001822325, + "n": 0.02500000000178913, "ty": { "in": null, "type": "Known", @@ -9821,7 +9821,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.165000003201697, + "n": 0.16500000320176778, "ty": { "in": null, "type": "Known", @@ -9831,7 +9831,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.5722530846158204, + "n": 0.5722530846157872, "ty": { "in": null, "type": "Known", @@ -9839,7 +9839,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.7599999999993404, + "n": 0.759999999999411, "ty": { "in": null, "type": "Known", @@ -9933,7 +9933,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.5722530846157162, + "n": 0.572253084615683, "ty": { "in": null, "type": "Known", @@ -9941,7 +9941,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.759999999999456, + "n": 0.7599999999995266, "ty": { "in": null, "type": "Known", @@ -9951,7 +9951,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.025000000003983447, + "n": 0.025000000003950255, "ty": { "in": null, "type": "Known", @@ -9959,7 +9959,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.759999999999515, + "n": 0.7599999999995856, "ty": { "in": null, "type": "Known", @@ -10053,7 +10053,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.025000000003983447, + "n": 0.025000000003950255, "ty": { "in": null, "type": "Known", @@ -10061,7 +10061,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.759999999999574, + "n": 0.7599999999996445, "ty": { "in": null, "type": "Known", @@ -10071,7 +10071,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.025000000004661963, + "n": 0.025000000004628768, "ty": { "in": null, "type": "Known", @@ -10079,7 +10079,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9749999999997455, + "n": 0.9749999999998161, "ty": { "in": null, "type": "Known", @@ -10173,7 +10173,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.025000000005340476, + "n": 0.025000000005307284, "ty": { "in": null, "type": "Known", @@ -10181,7 +10181,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9749999999998046, + "n": 0.9749999999998751, "ty": { "in": null, "type": "Known", @@ -10191,7 +10191,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.625000000005742, + "n": 0.6250000000057087, "ty": { "in": null, "type": "Known", @@ -10199,7 +10199,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9749999999999464, + "n": 0.975000000000017, "ty": { "in": null, "type": "Known", @@ -10293,7 +10293,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.6250000000064204, + "n": 0.6250000000063872, "ty": { "in": null, "type": "Known", @@ -10301,7 +10301,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000000882, + "n": 0.9750000000001589, "ty": { "in": null, "type": "Known", @@ -10311,7 +10311,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.625000000007099, + "n": 0.6250000000070657, "ty": { "in": null, "type": "Known", @@ -10319,7 +10319,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8173489912353609, + "n": 0.8173489912354314, "ty": { "in": null, "type": "Known", @@ -10413,7 +10413,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.6250000000077774, + "n": 0.6250000000077442, "ty": { "in": null, "type": "Known", @@ -10421,7 +10421,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8173489912348599, + "n": 0.8173489912349305, "ty": { "in": null, "type": "Known", @@ -10431,7 +10431,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.7699999999942422, + "n": 0.7699999999942091, "ty": { "in": null, "type": "Known", @@ -10439,7 +10439,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000023993, + "n": 0.9750000000024699, "ty": { "in": null, "type": "Known", @@ -10533,7 +10533,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.7699999999948592, + "n": 0.769999999994826, "ty": { "in": null, "type": "Known", @@ -10541,7 +10541,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000018318, + "n": 0.9750000000019025, "ty": { "in": null, "type": "Known", @@ -10551,7 +10551,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.9099999999954762, + "n": 0.9099999999954431, "ty": { "in": null, "type": "Known", @@ -10559,7 +10559,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000018456, + "n": 0.9750000000019162, "ty": { "in": null, "type": "Known", @@ -10653,7 +10653,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.9099999999960932, + "n": 0.9099999999960601, "ty": { "in": null, "type": "Known", @@ -10661,7 +10661,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000018595, + "n": 0.9750000000019301, "ty": { "in": null, "type": "Known", @@ -10671,7 +10671,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.9099999999967102, + "n": 0.909999999996677, "ty": { "in": null, "type": "Known", @@ -10679,7 +10679,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8350000000018732, + "n": 0.8350000000019439, "ty": { "in": null, "type": "Known", @@ -10773,7 +10773,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.9099999999973272, + "n": 0.9099999999972941, "ty": { "in": null, "type": "Known", @@ -10781,7 +10781,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.835000000001887, + "n": 0.8350000000019576, "ty": { "in": null, "type": "Known", @@ -10791,7 +10791,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.36274691369315737, + "n": 0.3627469136931242, "ty": { "in": null, "type": "Known", @@ -10799,7 +10799,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.23999999999845167, + "n": 0.23999999999852248, "ty": { "in": null, "type": "Known", @@ -10893,7 +10893,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.36274691369312295, + "n": 0.3627469136930897, "ty": { "in": null, "type": "Known", @@ -10901,7 +10901,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.23999999999846547, + "n": 0.23999999999853627, "ty": { "in": null, "type": "Known", @@ -10911,7 +10911,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.9099999999992231, + "n": 0.90999999999919, "ty": { "in": null, "type": "Known", @@ -10919,7 +10919,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.23999999999841187, + "n": 0.23999999999848265, "ty": { "in": null, "type": "Known", @@ -11013,7 +11013,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.9099999999992231, + "n": 0.90999999999919, "ty": { "in": null, "type": "Known", @@ -11021,7 +11021,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.23999999999835825, + "n": 0.23999999999842903, "ty": { "in": null, "type": "Known", @@ -11031,7 +11031,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.909999999999855, + "n": 0.909999999999822, "ty": { "in": null, "type": "Known", @@ -11039,7 +11039,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999998245644, + "n": 0.02499999999831642, "ty": { "in": null, "type": "Known", @@ -11133,7 +11133,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.9100000000004871, + "n": 0.9100000000004539, "ty": { "in": null, "type": "Known", @@ -11141,7 +11141,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.02499999999819202, + "n": 0.024999999998262797, "ty": { "in": null, "type": "Known", @@ -11151,7 +11151,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.3100000000003626, + "n": 0.3100000000003294, "ty": { "in": null, "type": "Known", @@ -11159,7 +11159,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999998138397, + "n": 0.024999999998209173, "ty": { "in": null, "type": "Known", @@ -11253,7 +11253,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.3100000000006396, + "n": 0.3100000000006064, "ty": { "in": null, "type": "Known", @@ -11261,7 +11261,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999998084773, + "n": 0.02499999999815555, "ty": { "in": null, "type": "Known", @@ -11271,7 +11271,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.3100000000009166, + "n": 0.31000000000088346, "ty": { "in": null, "type": "Known", @@ -11279,7 +11279,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.1826510087623727, + "n": 0.18265100876244356, "ty": { "in": null, "type": "Known", @@ -11373,7 +11373,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.31000000000119365, + "n": 0.31000000000116046, "ty": { "in": null, "type": "Known", @@ -11381,7 +11381,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.18265100876199486, + "n": 0.18265100876206572, "ty": { "in": null, "type": "Known", @@ -11391,7 +11391,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.16500000015676336, + "n": 0.1650000001567301, "ty": { "in": null, "type": "Known", @@ -11399,7 +11399,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999999429413, + "n": 0.02499999999950019, "ty": { "in": null, "type": "Known", @@ -11493,7 +11493,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.16500000015689917, + "n": 0.16500000015686592, "ty": { "in": null, "type": "Known", @@ -11501,7 +11501,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999999242052, + "n": 0.02499999999931283, "ty": { "in": null, "type": "Known", @@ -11511,7 +11511,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.025000000000842026, + "n": 0.025000000000808834, "ty": { "in": null, "type": "Known", @@ -11519,7 +11519,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.024999999999440452, + "n": 0.024999999999511226, "ty": { "in": null, "type": "Known", @@ -11613,7 +11613,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.9099999999967102, + "n": 0.909999999996677, "ty": { "in": null, "type": "Known", @@ -11621,7 +11621,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8350000000018732, + "n": 0.8350000000019439, "ty": { "in": null, "type": "Known", @@ -11631,7 +11631,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.7699999999948592, + "n": 0.769999999994826, "ty": { "in": null, "type": "Known", @@ -11639,7 +11639,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8350000000018732, + "n": 0.8350000000019439, "ty": { "in": null, "type": "Known", @@ -11734,7 +11734,7 @@ description: Variables in memory after executing zoo-logo.kcl "line": { "start": [ { - "n": 0.7699999999948592, + "n": 0.769999999994826, "ty": { "in": null, "type": "Known", @@ -11742,7 +11742,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.9750000000012506, + "n": 0.9750000000013213, "ty": { "in": null, "type": "Known", @@ -11752,7 +11752,7 @@ description: Variables in memory after executing zoo-logo.kcl ], "end": [ { - "n": 0.7699999999948592, + "n": 0.769999999994826, "ty": { "in": null, "type": "Known", @@ -11760,7 +11760,7 @@ description: Variables in memory after executing zoo-logo.kcl } }, { - "n": 0.8350000000018732, + "n": 0.8350000000019439, "ty": { "in": null, "type": "Known", @@ -11899,14 +11899,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000042939, - 0.4999999999963225 + 1.4480000000041913, + 0.4999999999964554 ], "from": [ - 1.7507222211478382, - 0.8979437861876547 + 1.7507222213373614, + 0.8979437865254067 ], - "radius": 0.5000000001423737, + "radius": 0.5000000005258884, "tag": { "commentStart": 5447, "end": 5454, @@ -11916,8 +11916,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc01" }, "to": [ - 1.0721424205345453, - 0.1702560385694067 + 1.072142420234361, + 0.17025603833005248 ], "type": "Arc", "units": "in" @@ -11929,14 +11929,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000814304, - 0.5000000000790455 + 1.448000000081533, + 0.500000000079401 ], "from": [ - 1.592386935136791, - 0.7281499797400859 + 1.5923869355465465, + 0.7281499798248687 ], - "radius": 0.2700000004333593, + "radius": 0.2700000007237691, "tag": { "commentStart": 5562, "end": 5569, @@ -11946,8 +11946,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc02" }, "to": [ - 1.230477706531429, - 0.34004984520959547 + 1.2304777064696815, + 0.34004984480384404 ], "type": "Arc", "units": "in" @@ -11959,14 +11959,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4480000000307414, - 0.5000000000246562 + 1.4480000000305635, + 0.5000000000247096 ], "from": [ - 1.145277791967196, - 0.10205620247917498 + 1.1452777916181331, + 0.10205620193818332 ], - "radius": 0.5000000012597874, + "radius": 0.5000000019016289, "tag": { "commentStart": 5678, "end": 5685, @@ -11976,8 +11976,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc03" }, "to": [ - 1.8238575925373133, - 0.8297439482859565 + 1.8238575932140073, + 0.8297439484877219 ], "type": "Arc", "units": "in" @@ -11989,14 +11989,14 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 1.4479999999270814, - 0.49999999991352684 + 1.4479999999267732, + 0.49999999991343663 ], "from": [ - 1.3036130783117428, - 0.2718500105172791 + 1.3036130777154717, + 0.27185001040423934 ], - "radius": 0.2700000014723368, + "radius": 0.27000000188648016, "tag": { "commentStart": 5793, "end": 5800, @@ -12006,8 +12006,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Arc04" }, "to": [ - 1.6655223039710587, - 0.6599501422656404 + 1.6655223042550238, + 0.6599501425780409 ], "type": "Arc", "units": "in" @@ -12046,12 +12046,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -12208,8 +12208,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.0721424207704, - 0.1702560387763178 + 1.0721424207747434, + 0.1702560388041387 ], "tag": { "commentStart": 5908, @@ -12220,8 +12220,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line01" }, "to": [ - 1.2304777073930173, - 0.3400498458431754 + 1.2304777076509616, + 0.34004984567246327 ], "type": "ToPoint", "units": "in" @@ -12232,8 +12232,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.592386935167577, - 0.728149979788665 + 1.5923869355774285, + 0.7281499798735742 ], "tag": { "commentStart": 5992, @@ -12244,8 +12244,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line02" }, "to": [ - 1.7507222211361029, - 0.897943786172192 + 1.7507222213256655, + 0.8979437865099826 ], "type": "ToPoint", "units": "in" @@ -12256,8 +12256,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.1452777919671395, - 0.10205620247922666 + 1.145277791618066, + 0.1020562019382462 ], "tag": { "commentStart": 6075, @@ -12268,8 +12268,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line03" }, "to": [ - 1.3036130782809365, - 0.2718500104686369 + 1.3036130776845802, + 0.27185001035546846 ], "type": "ToPoint", "units": "in" @@ -12280,8 +12280,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 1.6655223064839437, - 0.6599501441136671 + 1.6655223058092399, + 0.659950143721114 ], "tag": { "commentStart": 6157, @@ -12292,8 +12292,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "o1Line04" }, "to": [ - 1.8238575928297183, - 0.8297439485420472 + 1.8238575926275662, + 0.8297439479727559 ], "type": "ToPoint", "units": "in" @@ -12332,12 +12332,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -12535,25 +12535,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.5000000000673026, - 0.5000000000713016 + 2.500000000066863, + 0.5000000000711139 ], "from": [ - 2.802722216551602, - 0.897943790886238 + 2.8027222194373516, + 0.897943789661772 ], - "radius": 0.5000000010013289, + "radius": 0.5000000017743682, "tag": { - "commentStart": 8948, - "end": 8955, + "commentStart": 9011, + "end": 9018, "moduleId": 0, - "start": 8948, + "start": 9011, "type": "TagDeclarator", "value": "o2Arc01" }, "to": [ - 2.1241424128079442, - 0.17025604622088947 + 2.1241424101241355, + 0.17025604810715045 ], "type": "Arc", "units": "in" @@ -12565,25 +12565,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.5000000000731593, - 0.5000000000775605 + 2.5000000000727796, + 0.5000000000774375 ], "from": [ - 2.1972777829497114, - 0.10205620972677573 + 2.1972777800432586, + 0.1020562109708937 ], - "radius": 0.5000000010188852, + "radius": 0.5000000017880751, "tag": { - "commentStart": 9061, - "end": 9068, + "commentStart": 9124, + "end": 9131, "moduleId": 0, - "start": 9061, + "start": 9124, "type": "TagDeclarator", "value": "o2Arc02" }, "to": [ - 2.875857586826934, - 0.8297439545308815 + 2.8758575894902045, + 0.8297439526609495 ], "type": "Arc", "units": "in" @@ -12595,25 +12595,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.500000000133684, - 0.500000000142576 + 2.5000000001328506, + 0.5000000001419687 ], "from": [ - 2.6443869305745222, - 0.7281499843442172 + 2.6443869328963747, + 0.7281499835711335 ], - "radius": 0.2700000018024751, + "radius": 0.27000000239182703, "tag": { - "commentStart": 9174, - "end": 9181, + "commentStart": 9237, + "end": 9244, "moduleId": 0, - "start": 9174, + "start": 9237, "type": "TagDeclarator", "value": "o2Arc03" }, "to": [ - 2.2824776996294527, - 0.3400498524193454 + 2.2824776981457813, + 0.34004985344046407 ], "type": "Arc", "units": "in" @@ -12624,20 +12624,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1972777829522534, - 0.10205620973017071 + 2.197277780045819, + 0.10205621097433053 ], "tag": { - "commentStart": 9570, - "end": 9578, + "commentStart": 9633, + "end": 9641, "moduleId": 0, - "start": 9570, + "start": 9633, "type": "TagDeclarator", "value": "o2Line03" }, "to": [ - 2.355613068486364, - 0.271850015629843 + 2.355613066204165, + 0.2718500163736707 ], "type": "ToPoint", "units": "in" @@ -12676,12 +12676,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -12839,25 +12839,25 @@ description: Variables in memory after executing zoo-logo.kcl }, "ccw": true, "center": [ - 2.50000000000086, - 0.5000000000000057 + 2.500000000000816, + 0.5000000000002371 ], "from": [ - 2.355613068512856, - 0.27185001567166317 + 2.3556130662305046, + 0.27185001641524137 ], - "radius": 0.27000000246952705, + "radius": 0.2700000030619002, "tag": { - "commentStart": 9289, - "end": 9296, + "commentStart": 9352, + "end": 9359, "moduleId": 0, - "start": 9289, + "start": 9352, "type": "TagDeclarator", "value": "o2Arc04" }, "to": [ - 2.71752230073452, - 0.6599501485372291 + 2.7175223022479003, + 0.6599501474792382 ], "type": "Arc", "units": "in" @@ -12868,20 +12868,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.1241424133176126, - 0.17025604666800587 + 2.124142411384393, + 0.17025604921278056 ], "tag": { - "commentStart": 9404, - "end": 9412, + "commentStart": 9467, + "end": 9475, "moduleId": 0, - "start": 9404, + "start": 9467, "type": "TagDeclarator", "value": "o2Line01" }, "to": [ - 2.282477701147848, - 0.34004985353583894 + 2.2824777003694794, + 0.34004985507559454 ], "type": "ToPoint", "units": "in" @@ -12892,20 +12892,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.6443869306011063, - 0.7281499843861835 + 2.644386932922806, + 0.7281499836128499 ], "tag": { - "commentStart": 9488, - "end": 9496, + "commentStart": 9551, + "end": 9559, "moduleId": 0, - "start": 9488, + "start": 9551, "type": "TagDeclarator", "value": "o2Line02" }, "to": [ - 2.802722216549035, - 0.8979437908828091 + 2.802722219434765, + 0.8979437896583012 ], "type": "ToPoint", "units": "in" @@ -12916,20 +12916,20 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 2.7175222979387295, - 0.6599501464814688 + 2.7175222987567156, + 0.6599501449121116 ], "tag": { - "commentStart": 9652, - "end": 9660, + "commentStart": 9715, + "end": 9723, "moduleId": 0, - "start": 9652, + "start": 9715, "type": "TagDeclarator", "value": "o2Line04" }, "to": [ - 2.8758575862723452, - 0.8297439540444097 + 2.8758575881862294, + 0.8297439515169935 ], "type": "ToPoint", "units": "in" @@ -12968,12 +12968,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, @@ -13210,8 +13210,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "tag": { "commentStart": 1074, @@ -13222,8 +13222,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine01" }, "to": [ - 0.0250000000019479, - 0.16500000320161995 + 0.02500000000191471, + 0.16500000320169073 ], "type": "ToPoint", "units": "in" @@ -13234,8 +13234,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.0250000000019479, - 0.16500000320161995 + 0.02500000000191471, + 0.16500000320169073 ], "tag": { "commentStart": 1157, @@ -13246,8 +13246,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine02" }, "to": [ - 0.5722530846158204, - 0.7599999999993404 + 0.5722530846157872, + 0.759999999999411 ], "type": "ToPoint", "units": "in" @@ -13258,8 +13258,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.5722530846158204, - 0.7599999999993404 + 0.5722530846157872, + 0.759999999999411 ], "tag": { "commentStart": 1240, @@ -13270,8 +13270,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine03" }, "to": [ - 0.025000000003983447, - 0.759999999999515 + 0.025000000003950255, + 0.7599999999995856 ], "type": "ToPoint", "units": "in" @@ -13282,8 +13282,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000003983447, - 0.759999999999515 + 0.025000000003950255, + 0.7599999999995856 ], "tag": { "commentStart": 1323, @@ -13294,8 +13294,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine04" }, "to": [ - 0.025000000004661963, - 0.9749999999997455 + 0.025000000004628768, + 0.9749999999998161 ], "type": "ToPoint", "units": "in" @@ -13306,8 +13306,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.025000000004661963, - 0.9749999999997455 + 0.025000000004628768, + 0.9749999999998161 ], "tag": { "commentStart": 1406, @@ -13318,8 +13318,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine05" }, "to": [ - 0.625000000005742, - 0.9749999999999464 + 0.6250000000057087, + 0.975000000000017 ], "type": "ToPoint", "units": "in" @@ -13330,8 +13330,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.625000000005742, - 0.9749999999999464 + 0.6250000000057087, + 0.975000000000017 ], "tag": { "commentStart": 1489, @@ -13342,8 +13342,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine06" }, "to": [ - 0.625000000007099, - 0.8173489912353609 + 0.6250000000070657, + 0.8173489912354314 ], "type": "ToPoint", "units": "in" @@ -13354,8 +13354,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.625000000007099, - 0.8173489912353609 + 0.6250000000070657, + 0.8173489912354314 ], "tag": { "commentStart": 1572, @@ -13366,8 +13366,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine07" }, "to": [ - 0.7699999999942422, - 0.9750000000023993 + 0.7699999999942091, + 0.9750000000024699 ], "type": "ToPoint", "units": "in" @@ -13378,8 +13378,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.7699999999942422, - 0.9750000000023993 + 0.7699999999942091, + 0.9750000000024699 ], "tag": { "commentStart": 1655, @@ -13390,8 +13390,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine08" }, "to": [ - 0.9099999999954762, - 0.9750000000018456 + 0.9099999999954431, + 0.9750000000019162 ], "type": "ToPoint", "units": "in" @@ -13402,8 +13402,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999954762, - 0.9750000000018456 + 0.9099999999954431, + 0.9750000000019162 ], "tag": { "commentStart": 1738, @@ -13414,8 +13414,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine09" }, "to": [ - 0.9099999999967102, - 0.8350000000018732 + 0.909999999996677, + 0.8350000000019439 ], "type": "ToPoint", "units": "in" @@ -13426,8 +13426,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999967102, - 0.8350000000018732 + 0.909999999996677, + 0.8350000000019439 ], "tag": { "commentStart": 1821, @@ -13438,8 +13438,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine10" }, "to": [ - 0.36274691369315737, - 0.23999999999845167 + 0.3627469136931242, + 0.23999999999852248 ], "type": "ToPoint", "units": "in" @@ -13450,8 +13450,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.36274691369315737, - 0.23999999999845167 + 0.3627469136931242, + 0.23999999999852248 ], "tag": { "commentStart": 1904, @@ -13462,8 +13462,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine11" }, "to": [ - 0.9099999999992231, - 0.23999999999841187 + 0.90999999999919, + 0.23999999999848265 ], "type": "ToPoint", "units": "in" @@ -13474,8 +13474,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.9099999999992231, - 0.23999999999841187 + 0.90999999999919, + 0.23999999999848265 ], "tag": { "commentStart": 1987, @@ -13486,8 +13486,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine12" }, "to": [ - 0.909999999999855, - 0.024999999998245644 + 0.909999999999822, + 0.02499999999831642 ], "type": "ToPoint", "units": "in" @@ -13498,8 +13498,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.909999999999855, - 0.024999999998245644 + 0.909999999999822, + 0.02499999999831642 ], "tag": { "commentStart": 2070, @@ -13510,8 +13510,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine13" }, "to": [ - 0.3100000000003626, - 0.024999999998138397 + 0.3100000000003294, + 0.024999999998209173 ], "type": "ToPoint", "units": "in" @@ -13522,8 +13522,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.3100000000003626, - 0.024999999998138397 + 0.3100000000003294, + 0.024999999998209173 ], "tag": { "commentStart": 2153, @@ -13534,8 +13534,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine14" }, "to": [ - 0.3100000000009166, - 0.1826510087623727 + 0.31000000000088346, + 0.18265100876244356 ], "type": "ToPoint", "units": "in" @@ -13546,8 +13546,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.3100000000009166, - 0.1826510087623727 + 0.31000000000088346, + 0.18265100876244356 ], "tag": { "commentStart": 2236, @@ -13558,8 +13558,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine15" }, "to": [ - 0.16500000015676336, - 0.024999999999429413 + 0.1650000001567301, + 0.02499999999950019 ], "type": "ToPoint", "units": "in" @@ -13570,8 +13570,8 @@ description: Variables in memory after executing zoo-logo.kcl "sourceRange": [] }, "from": [ - 0.16500000015676336, - 0.024999999999429413 + 0.1650000001567301, + 0.02499999999950019 ], "tag": { "commentStart": 2319, @@ -13582,8 +13582,8 @@ description: Variables in memory after executing zoo-logo.kcl "value": "zLine16" }, "to": [ - 0.025000000000842026, - 0.024999999999440452 + 0.025000000000808834, + 0.024999999999511226 ], "type": "ToPoint", "units": "in" @@ -13622,12 +13622,12 @@ description: Variables in memory after executing zoo-logo.kcl }, "start": { "from": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "to": [ - 0.025000000001394965, - 0.024999999999440452 + 0.025000000001361773, + 0.024999999999511226 ], "units": "in", "tag": null, From f579295307c8721ec16c1627912521ed99a08ce8 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 17:26:03 +0200 Subject: [PATCH 74/78] update doc page --- docs/kcl-std/functions/std-solver-angleDimension.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/kcl-std/functions/std-solver-angleDimension.md b/docs/kcl-std/functions/std-solver-angleDimension.md index fb24077b43e..b4b42e20d6b 100644 --- a/docs/kcl-std/functions/std-solver-angleDimension.md +++ b/docs/kcl-std/functions/std-solver-angleDimension.md @@ -34,6 +34,10 @@ solver::angleDimension( profile = sketch(on = XY) { line1 = line(start = [var 0mm, var 0mm], end = [var 4mm, var 0mm]) line2 = line(start = [var 0mm, var 0mm], end = [var 2mm, var 3.464mm]) + line3 = line(start = [var 2mm, var 3.464mm], end = [var 4mm, var 0mm]) + coincident([line1.start, line2.start]) + coincident([line2.end, line3.start]) + coincident([line3.end, line1.end]) angleDimension(lines = [line1, line2], sector = 1) == 60deg } From d382e6c62fc1d01161b75b15ce43d16b7cba6a06 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 17:26:35 +0200 Subject: [PATCH 75/78] update angleDimension image and glb --- ..._fn_std-solver-angleDimension0_output.gltf | 847 ++++++++++++++++++ ..._example_fn_std-solver-angleDimension0.png | Bin 0 -> 67417 bytes 2 files changed, 847 insertions(+) create mode 100644 rust/kcl-lib/tests/outputs/models/serial_test_example_fn_std-solver-angleDimension0_output.gltf create mode 100644 rust/kcl-lib/tests/outputs/serial_test_example_fn_std-solver-angleDimension0.png diff --git a/rust/kcl-lib/tests/outputs/models/serial_test_example_fn_std-solver-angleDimension0_output.gltf b/rust/kcl-lib/tests/outputs/models/serial_test_example_fn_std-solver-angleDimension0_output.gltf new file mode 100644 index 00000000000..a505ab1347b --- /dev/null +++ b/rust/kcl-lib/tests/outputs/models/serial_test_example_fn_std-solver-angleDimension0_output.gltf @@ -0,0 +1,847 @@ +{ + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "count": 6, + "componentType": 5126, + "type": "VEC3", + "min": [ + 0.0019999800715595484, + 0, + -0.003464010078459978 + ], + "max": [ + 0.004000000189989805, + 0.0020000000949949026, + 0.00000001999999987845058 + ] + }, + { + "bufferView": 0, + "byteOffset": 12, + "count": 6, + "componentType": 5126, + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 0, + "count": 6, + "componentType": 5126, + "type": "VEC3", + "min": [ + 0.00000000999999993922529, + 0, + -0.003464010078459978 + ], + "max": [ + 0.0019999800715595484, + 0.0020000000949949026, + -0.00000000999999993922529 + ] + }, + { + "bufferView": 1, + "byteOffset": 12, + "count": 6, + "componentType": 5126, + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "count": 6, + "componentType": 5126, + "type": "VEC3", + "min": [ + 0.00000000999999993922529, + 0, + -0.00000000999999993922529 + ], + "max": [ + 0.004000000189989805, + 0.0020000000949949026, + 0.00000001999999987845058 + ] + }, + { + "bufferView": 2, + "byteOffset": 12, + "count": 6, + "componentType": 5126, + "type": "VEC3" + }, + { + "bufferView": 3, + "byteOffset": 0, + "count": 3, + "componentType": 5126, + "type": "VEC3", + "min": [ + 0.00000000999999993922529, + 0, + -0.003464010078459978 + ], + "max": [ + 0.004000000189989805, + 0, + 0.00000001999999987845058 + ] + }, + { + "bufferView": 3, + "byteOffset": 12, + "count": 3, + "componentType": 5126, + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 0, + "count": 3, + "componentType": 5126, + "type": "VEC3", + "min": [ + 0.00000000999999993922529, + 0.0020000000949949026, + -0.003464010078459978 + ], + "max": [ + 0.004000000189989805, + 0.0020000000949949026, + 0.00000001999999987845058 + ] + }, + { + "bufferView": 4, + "byteOffset": 12, + "count": 3, + "componentType": 5126, + "type": "VEC3" + } + ], + "asset": { + "generator": "zoo.dev", + "version": "2.0" + }, + "buffers": [ + { + "byteLength": 576, + "uri": "data:application/octet-stream;base64,bxKDO28SAzt3zKsybbNdPwAAAAC5AAC/bxKDOwAAAAB3zKsybbNdPwAAAAC5AAC/GRIDO28SAztyBGO7bbNdPwAAAAC5AAC/GRIDO28SAztyBGO7bbNdPwAAAAC5AAC/bxKDOwAAAAB3zKsybbNdPwAAAAC5AAC/GRIDOwAAAAByBGO7bbNdPwAAAAC5AAC/GRIDO28SAztyBGO7orNdvwAAAABcAAC/GRIDOwAAAAByBGO7orNdvwAAAABcAAC/d8wrMm8SAzt3zCuyorNdvwAAAABcAAC/d8wrMm8SAzt3zCuyorNdvwAAAABcAAC/GRIDOwAAAAByBGO7orNdvwAAAABcAAC/d8wrMgAAAAB3zCuyorNdvwAAAABcAAC/d8wrMm8SAzt3zCuyFhLVtgAAAAAAAIA/d8wrMgAAAAB3zCuyFhLVtgAAAAAAAIA/bxKDO28SAzt3zKsyFhLVtgAAAAAAAIA/bxKDO28SAzt3zKsyFhLVtgAAAAAAAIA/d8wrMgAAAAB3zCuyFhLVtgAAAAAAAIA/bxKDOwAAAAB3zKsyFhLVtgAAAAAAAIA/d8wrMgAAAAB3zCuyAAAAgAAAgL8AAACAGRIDOwAAAAByBGO7AAAAgAAAgL8AAACAbxKDOwAAAAB3zKsyAAAAgAAAgL8AAACAd8wrMm8SAzt3zCuyAAAAAAAAgD8AAAAAbxKDO28SAzt3zKsyAAAAAAAAgD8AAAAAGRIDO28SAztyBGO7AAAAAAAAgD8AAAAA" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteLength": 144, + "byteOffset": 0, + "byteStride": 24, + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 144, + "byteOffset": 144, + "byteStride": 24, + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 144, + "byteOffset": 288, + "byteStride": 24, + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 72, + "byteOffset": 432, + "byteStride": 24, + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 72, + "byteOffset": 504, + "byteStride": 24, + "target": 34962 + } + ], + "scene": 0, + "extensions": { + "KITTYCAD_boundary_representation": { + "solids": [ + { + "shells": [ + [ + 0, + 1 + ] + ], + "mesh": 0, + "extras": { + "KITTYCAD": { + "material": 0 + } + } + } + ], + "shells": [ + { + "faces": [ + [ + 0, + 1 + ], + [ + 1, + 1 + ], + [ + 2, + 1 + ], + [ + 3, + 1 + ], + [ + 4, + 1 + ] + ] + } + ], + "faces": [ + { + "surface": [ + 0, + 1 + ], + "loops": [ + [ + 0, + 1 + ] + ] + }, + { + "surface": [ + 1, + 1 + ], + "loops": [ + [ + 1, + 1 + ] + ] + }, + { + "surface": [ + 2, + 1 + ], + "loops": [ + [ + 2, + 1 + ] + ] + }, + { + "surface": [ + 3, + -1 + ], + "loops": [ + [ + 3, + 1 + ] + ] + }, + { + "surface": [ + 4, + 1 + ], + "loops": [ + [ + 4, + 1 + ] + ] + } + ], + "loops": [ + { + "edges": [ + [ + 0, + 1 + ], + [ + 1, + 1 + ], + [ + 2, + -1 + ], + [ + 3, + -1 + ] + ] + }, + { + "edges": [ + [ + 4, + 1 + ], + [ + 5, + 1 + ], + [ + 6, + -1 + ], + [ + 1, + -1 + ] + ] + }, + { + "edges": [ + [ + 7, + 1 + ], + [ + 3, + 1 + ], + [ + 8, + -1 + ], + [ + 5, + -1 + ] + ] + }, + { + "edges": [ + [ + 7, + -1 + ], + [ + 4, + -1 + ], + [ + 0, + -1 + ] + ] + }, + { + "edges": [ + [ + 2, + 1 + ], + [ + 6, + 1 + ], + [ + 8, + 1 + ] + ] + } + ], + "edges": [ + { + "curve": [ + 0, + 1 + ], + "start": 0, + "end": 1, + "t": [ + 0, + 0.003999947979824238 + ] + }, + { + "curve": [ + 1, + 1 + ], + "start": 1, + "end": 2, + "t": [ + 0, + 0.002 + ] + }, + { + "curve": [ + 2, + 1 + ], + "start": 3, + "end": 2, + "t": [ + 0, + 0.003999947979824238 + ] + }, + { + "curve": [ + 3, + 1 + ], + "start": 0, + "end": 3, + "t": [ + 0, + 0.002 + ] + }, + { + "curve": [ + 4, + 1 + ], + "start": 1, + "end": 4, + "t": [ + 0, + 0.003999896998786344 + ] + }, + { + "curve": [ + 5, + 1 + ], + "start": 4, + "end": 5, + "t": [ + 0, + 0.002 + ] + }, + { + "curve": [ + 6, + 1 + ], + "start": 2, + "end": 5, + "t": [ + 0, + 0.003999896998786344 + ] + }, + { + "curve": [ + 7, + 1 + ], + "start": 4, + "end": 0, + "t": [ + 0, + 0.0039999900001124996 + ] + }, + { + "curve": [ + 8, + 1 + ], + "start": 5, + "end": 3, + "t": [ + 0, + 0.0039999900001124996 + ] + } + ], + "vertices": [ + [ + 0.004, + 0, + 0.00000002 + ], + [ + 0.00199998, + 0, + -0.00346401 + ], + [ + 0.00199998, + 0.002, + -0.00346401 + ], + [ + 0.004, + 0.002, + 0.00000002 + ], + [ + 0.00000001, + 0, + -0.00000001 + ], + [ + 0.00000001, + 0.002, + -0.00000001 + ] + ], + "surfaces": [ + { + "type": "plane", + "plane": { + "xAxis": [ + 0.5000110012290514, + 0, + 0.8660190521287171 + ], + "yAxis": [ + 0, + -1, + 0 + ], + "origin": [ + 0.00299999, + 0.001, + -0.001732 + ] + } + }, + { + "type": "plane", + "plane": { + "xAxis": [ + 0.5000054992788864, + 0, + -0.8660222287510129 + ], + "yAxis": [ + 0, + -1, + -0 + ], + "origin": [ + 0.001, + 0.001, + -0.00173201 + ] + } + }, + { + "type": "plane", + "plane": { + "xAxis": [ + 0.9999999999798388, + 0, + 0.000006349999999871976 + ], + "yAxis": [ + 0, + 1, + -0 + ], + "origin": [ + 0.00200001, + 0.001, + 0.00000001 + ] + } + }, + { + "type": "plane", + "plane": { + "xAxis": [ + 1, + 0, + 0 + ], + "yAxis": [ + 0, + 0, + -1 + ], + "origin": [ + 0, + 0, + -0 + ] + } + }, + { + "type": "plane", + "plane": { + "xAxis": [ + 1, + 0, + 0 + ], + "yAxis": [ + 0, + 0, + -1 + ], + "origin": [ + 0, + 0.002, + -0 + ] + } + } + ], + "curves3D": [ + { + "type": "line", + "line": { + "origin": [ + 0.004, + 0, + 0.00000002 + ], + "direction": [ + -0.500011502671563, + 0, + -0.8660187626120611 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.00199998, + 0, + -0.00346401 + ], + "direction": [ + 0, + 1, + 0 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.004, + 0.002, + 0.00000002 + ], + "direction": [ + -0.500011502671563, + 0, + -0.8660187626120611 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.004, + 0, + 0.00000002 + ], + "direction": [ + 0, + 1, + 0 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.00199998, + 0, + -0.00346401 + ], + "direction": [ + -0.5000053752901225, + 0, + 0.866022300336997 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.00000001, + 0, + -0.00000001 + ], + "direction": [ + 0, + 1, + 0 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.00199998, + 0.002, + -0.00346401 + ], + "direction": [ + -0.5000053752901225, + 0, + 0.866022300336997 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.00000001, + 0, + -0.00000001 + ], + "direction": [ + 0.9999999999718748, + 0, + 0.000007500018749835938 + ] + } + }, + { + "type": "line", + "line": { + "origin": [ + 0.00000001, + 0.002, + -0.00000001 + ], + "direction": [ + 0.9999999999718748, + 0, + 0.000007500018749835938 + ] + } + } + ] + } + }, + "extensionsUsed": [ + "KITTYCAD_boundary_representation" + ], + "materials": [ + { + "alphaMode": "OPAQUE", + "doubleSided": false, + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.9, + 0.9, + 0.9, + 1 + ], + "metallicFactor": 1, + "roughnessFactor": 1 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ] + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "POSITION": 0, + "NORMAL": 1 + }, + "material": 0 + }, + { + "attributes": { + "POSITION": 2, + "NORMAL": 3 + }, + "material": 0 + }, + { + "attributes": { + "POSITION": 4, + "NORMAL": 5 + }, + "material": 0 + }, + { + "attributes": { + "POSITION": 6, + "NORMAL": 7 + }, + "material": 0 + }, + { + "attributes": { + "POSITION": 8, + "NORMAL": 9 + }, + "material": 0 + } + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ] + }, + { + "children": [ + 2 + ] + }, + { + "extensions": { + "KITTYCAD_boundary_representation": { + "solid": 0 + } + }, + "mesh": 0 + } + ], + "scenes": [ + { + "nodes": [ + 0 + ] + } + ] +} \ No newline at end of file diff --git a/rust/kcl-lib/tests/outputs/serial_test_example_fn_std-solver-angleDimension0.png b/rust/kcl-lib/tests/outputs/serial_test_example_fn_std-solver-angleDimension0.png new file mode 100644 index 0000000000000000000000000000000000000000..cc68f31f87b13998da77c845536af29b3765179c GIT binary patch literal 67417 zcmeIbYj~B_wKg0?Kw)Dl7TJ|bRDyIvHQlv_%E6^piquxNuSMP#Ote<%-VmZv42P1X zSVW{W3a?TdA+265-S9zFwjfGaig-Z8)cVnY0V1G8MF;^y4kYXO?t6?m=QE$R7PRlb z?+095$vR~{bB@D3?lI<=^O^r2H;wAq{etdUSy??t-*El^%F613hiClttgiS~J$v`9 zS)ICFH2V5$e>}a@p;tTqA@?UwzS$U*9A5bLyUXvp@y^vnwQJ4)|NPCeCx1}6?Aupd za=7*Wb^kT<&+~>&+Fp6}r`KlhTd{KW%b%zJXp7B%XY9D!rfpCE(G>6fMCLzw`SW1V zpv-?XZF?~G#~H7Ls|PFpG9lBI@LDkL=Jgqd#~~*xpSdr?@c2a?g(E*npOeh9E%E5- ziFpz|t+9ytpEgC$HctCk#5Pv0J`EmG;6Du>5d%359;dC!-?`f(aOPJ_qkeC%{ScDi8d;{Z_c9uFpi!8H@6 zZhOctDF;3Ll66N#$+jzNhPS*PYkxg)@ZG1b$UgAY#^k|7a&~fWPIB+M$X|Z@%Rh7* z@rYLvNfyt1zR#@ZYm!H@gCh+uANc*Ge!oh#&q#h+mVBf~pUaQjU3~oRr-x2^^u*y; z8vdTs@qSLn({*jD>e{AwmGQR3StC*k^TGH%jThE6t|_RWR#0D6x&FZKyH&*E%VKTM z#`g6o-P`A-y8pgq`Sg$b=WH3AI6C;)+oP^tBv+8{J}lSydgKacrd^@0USZE?OZR-X zrqg>BvFg0`O?gK~#lIZ2;ainQ2UTwRC%-x??W?O+bHIt?lM=^gRedn5>Vt`$hkrJD zjEsEx(Zv<-Cf?-m*9@6;MM3Kmg-@Mw=ym^+_WiTdzaK+yKO^4$R{Y)8WA&}g-<|gP zS0VZ0H#vu?b+emyw~bFUjj!vdO?1@O$qW9PKu`;{etNC9B+-<3>&lu5$3ChlJycU# zSu%5ZN!#QH3R~tDepD8;lwB214i6r`Y3a~6L`GEdu9CXh>yk90;sDD3v|e8Dmn(wv zq2!rg@fco5wVEC@ePQe%G(Bz4iT2iG?TtCXzb9H2B;H=|PJVFy@|%|Kd!n%Qi5Zj^ z%xL5IKnyc}a9!!aS?NX^ADU*Q^B!7YDGl~=5KLDh~0RmbPWTjs@UM0UsO ztB<_}owV=EOI{M}7I9VmZE)i|mF@5RL!YSVnx^)vGW$g9;@I9k@y0$gE~;%W83x6d zP2b#q`X}Q`@9Nk1$f$cf+1^qBeAhx%>y zr}bjGgA8xoGUmXEjSVMWx@YehL7%6G&sa2M_6I{gp=GW2CUB@Od8k2N@YmCVAEeEq zCVdu17QkxTw^X#B-RJTNAI0VrB?n$L<7h5qRrzlD#?Q*{6J4lfi7wI|u{Wmjlopqn@0rB`!;#++j}CceC}z3{H`J_kPDvRIT}-1g_nZkk@d{2qSdEy`XVxJ`h=K8=1Ka9De{E|* zuJO0QRlP)LTNV#g-H2JWiisWYjq8RqwY)X`t&(58RXuZQ&5WhZ8zmm?-P9%d@tEYV z3)}uwxGzx-tqg@$#7jOHGW(XBmJQzmfGjx()G8}|PbM_PpUSATsnpe{Imz4}eOkmx zc%`7n zogR0V2YHi^RZctl@#sAryX%&Y!u1r0|BlO)C=mN>Akih&SMpw-1ZQ~-zF65&0AFnQ za%a|<8SmWE@?cI&r^{gj@d35%g+K560FCU=(EJ8!M~qC&Yc~Q)qGN=-;M>?U*QM&e z@cwi|UQ+tml9mr*9k=jG!S~m;)_p`H<0XoZURu1#lUQ+Zyf|LX7Y6%cyD`;aX1%G?($&4b5JhHv%d}YI(uYyko)qqU1W_S$4eT^%;wY%sB5Kc}_}@?1&%tBd}Nl z?fJ8cDb(f_kt zt}^_Se;czm_;zi3@x=1@Dr)3XSn`H_gEwB{ISq+y+f|{zbOaAZwb2ycoq>OWEbgsN zeo-wktRLX=-Ta{M&I1op5#=!BBac?LJnGNoIJ~Agg^4xA`=(B4Z2E*sK_KSFPOORT zr;5hhQ6Ahl`B-c_5LqO*r)6Q??}WFCy&O_%&lheDgIBUR1q9j>0Aw%<_{*@;zr$Y+ zZfK?{uZf+wLM}*eNh~c&4ql4*JnmO-jQeV@?Jo7L1XX2$7OPW1=W@?=5_(?sm>#t5^0LM z6%4ka#qZy9KF0@(?3Flx=tyG5Pu;qnb$vxK*7{hlpFKQ^f)IbcPti6l{iWn-joLANR zeLEe|V<9+%N9=g3O(zK7xSPav2t2Ud;DkRWLUAMijr&Gta=yh?fqR? zh@hHe?!quKAO0E*G>UaEGdp=#b=MjLr zGJ4_i$7FV1mKYzAIeVPtH3qS7FuZpmDC!H_dfW%B=y&|Nd5zsGk8~g2 zzBjvG;yJS3bsJBxP7#|I#`9oks%h*@=Rp&oFNUrC)j@l;n8x^>2jV?y+sE8l&QSGU zL;HLG@It>zz0gn6FEsqne~#JDA+Dd^cu9arMKi3084iVQP)o%v4;Kq&`1xtZ;zYU~ z{vt!PqPeqV@DbIA*)Uoq08j(hY>Pk4seu6=6|eT9a7OCd@m6ZkD!VV;p~c{l?)4D# z7z>9+D27AB&)UZ`c#;3rFNB?Fc6_Sf73-RUz6q@#D2qWJQ!}GsL7%*%%=+5fDubcS zlma*#1&Zs9`MJr>+P5Z#7k~Nv;xkXlFavhM`gNG#){Oqf%E%FtM~VKEj64DOxobO7 zg(QX5g#CM9r$W&1*$idFwsomqSCd{dY}_|8i89HY!l0?JKDb2aQ?LbI2VZ#Q>F?e< zXWob}?%1%m@5YNAuN4od7jN)*ZT!L%uj{kjXB$GQoG{-kZtt4cy|z6LgDFxMABfE0 z&*u%i>Bw{QM*K$L@{a6T|LPe{Ds`*+MM?&e9H4G)lBqs<1s@M7-9H4z+0rBV3h3tr zm>uHud|dFsqU5t1s5W?b<*Tm)Sx&)pXYNh8(z1#SVQtojAAp;+^jvoQf0j4K$=TOz z3x2t_wPJIAaNdpsh5I+pKTiZHm-ND0YD!w2lVX;gB`Ju;8eS<0-&#bO&e?Gw=#R<$ zygc}COb+gc>9$^V@4hqtd3Rrv5>7j12yl^$k|B(9C>H$Nfe7>N2sBOg6MSOICxyuY2+@hxg5F9M=@m;?L`2F1}e64icB)7 zh)ywxsa*ZK1yB?C5#LgrJWzb}8hE=Beere#KM=~Y`}S=E+dgS2 z98rKxf-UrV@?aZOM6=}}w!u%6CB2NyGJ$Ab`J8X6i3LRkzq76=mp!#B201C0TvwIp zk_k?*5R$vEH}G>X@bj*6F`I4q!EKYLCge&`_a`%Uyx#B4lRHRoR}@Es5$SP>(P0dV zPe;F89$OkrMjil?Nje6E8*_VkaMRk>%3nf}tn5Bci1U*-NeW!`rlT-LhjsU+ho#TP z#D~Tj&x^fw`0(Y-3cn}@z@}W=tK+LTfR zY>L&TMM%o`^UCC-D&Iv?FynM9kjCBu`9k8a>^KnnfLHzWdpYljS}|#jUQ(h5OD#S4 zid#KQF8^L6_e<8#^Z}2B+6}L~vX#}*MrKPAB0)N0s0J)YOa}av;8(ZW_E8Kd*|R_W z-VDySU)x{j-FN(pofF#+04z&7Qk-VY+$iu>r*pa6VYV_)X16T?ET|m9MFodN4>)K8 z0QbMvwyvWM(-z+TUQXM8oIFe?mq+PNa$@>I!9538tvh;4tm&374j(?+fXh@W>&HaJ zYj8z)P37I?ecqsi9~v^fbHU+H3Vy4(brNe7%Q)h;!_k6EaCVd+1O*wq6>3>PqINgE zbqgwo!1p2Wp6{r)UXEV?j32C>F=gOQPk;0Yt}EB~CwyXE{KPDIAyn_Ml%O^uJt<&) zO?(^CsRCXz3_=D%FlKKd_#P_+NImh}oY;F?t9ET|>{@)Js{*2iHr7X)Q$t%x zv>cP1lon0*?B4xJWzbgH3b_>}Uqs~sHnk3-z8(gRyacF760sfN_zA&r*Vd}9^YhuK zqS5gIQO8ZZnYOw?CjwpnJyw+J1o2th>35jiioT+U=$F1vlE%7C& zW%f-^fA_VWYbI7S%CcuiG@)%uSv6{_ZcNRcr^BRZS_eu>>r1BJF?s6tsR#pv4LFs7 z4Zv~&crtkBfkHAEy6@5Z@|y1({^cLDKRJ1R8|xg62{{Lqpy`5`xNz&zy1k<23ZzCk zurAagmKLxau$ETA*_)VSvbq$z06nZ=D$8Ww`HqER=Ip%z@n>5?Aq z*uDFW{Ba#yfgtc?#@#b@!qhS*3@uj+S8Ql1D3eKhQidb1OGsHE+~8Q(JyJbut9d1D zx%S8~Ou2nqU3*UkCj_CO55f{B4((!r4Y7e{4J9WYMTR5RJ$vVpPhieXSIs*9#TCh9 zLy%loDuE&eNM4M}ypPV^&xPq%0Q-kU1i>Jz82~Ro(}ZIfF8NSVl70m%TZwYsKDzW5 zTQ`1_wjt|B2Q?Xxg}Bs}%LOTuUy>0`DEF47b*&e!Zd(FX8xDCkaO92r;6lI{&}=Mz zy^){yC<*Kfc_&^FSRtee1F0WX`thi%Psrmido7$3iB?s&XLRlIL~GyD=92glhNS=z zxg5rBQV}Hs#@ymvYKO;o$-4@V-!)_Xl37>L!-eu`CL|&V*E)MdFF&Hvm%5lf)lIc0 zPP~%X8VrE7!?QhW=jB03XzfTDy3}S#>VEZ?e-sT6Xtb6utL!YVKVI#s_%l;F1=ggo zcLI4yytxDfzP0b_nXiRZGivgKVEHhKA42MRTeoifV(Zbr&b#{moV+l7A`-iTlJux~ zKM-|&#fhtyHU4JekqT(H4r)hDIupLMRw91h@K#w)J!d(C^vGk`(JZ^Sk7^z93`_lD zYE^Y7MsNr$Q8U*ivVk=a*(6qrqj$%wZ!eFR(corQHqR81Ppn=x`%QjFX-zu6ZwexH z|Bg7aGIWAP7Mw-iD9nw=_1AxX6;g^baB*Zzv~~yrQPWyGVrXxyM&C>Fd;G4#Cu?R^ z)$I33w-#*pf(4tlpo@<+$wV4en*G_|2B@>2sH)pP@~-lg$!Q^1qS_$4=7)gpUa|4N*w>>Bc23;`9y8 zrDe>p$k`arIe$QWbpEh|>ifUg@$VYt2)jVQlP)s_L!!oirJwGIB=R_WP?)2y!0RV8 z<-CrmtxUqfHp+1|uUv@LRLeV)h3&WI{x!h28bW`WR?NzWiDs zmp^=PY9{Oa!fJ9_@yQ4TgLHek8wXLH9scpf*?XrIHcz98oV17-eBI~4O|jR~ z>J*VdjH~*EG{QI%3@jit0w)Fm6BQY%ftNpI;#1oGT{@@eq~FoU=G}9$B0|s+@zTTx zItsH|O>BNB*3wxFv(FPntJ|8P40JNlDtCu562vfKmBCY!k3BQ^Q>-!$2dRdFUiv(Sp06R$OSH%Vt6;Q3yr6NwDrg+v zTuXTfa30)v_@K(;WW~yk`p9Bo@XgHJ0Z4JITl`2ja)*_uIE*(HLjX7OL(&Jw8`>x0 z#Y+L>`1L>g-zo!q9{ctNV!2Q`f=<9XNb&4w>e5uvIRaeIrX?;LfB9K2kw{MaYdQC9 z2R1QxqITf1OkB1rhNf!=@0}|}nGNr5m0afQz>$;p$i&W%u-Z{G(sl?CLIE4g#9~(j z!x2uvY|n#%n&gqWo0_YEPyh$Zy!chOkE=WHZr$)NqNB$BZ%IapbgJ~@HQFO=t5U(g zM)0Gd$%k>Fy0FuB2y_G|^LBh-?S!UH2(1Y6CnXogO8Dz%<$bo}@&J*3o3>IkkIftY z>yu^~b?g{-rw=7pWh6SxOg~0y+|U}llP^UKfGVl}Ie7*8%?!XjwQZD#z1os zbX5J6kpO1D zDN?Dgr-lyIZoKT&+-q6{)kbDm&Jam}tbgzL@#8HuFKindtT$y2FrR_yIV3=MW(bh+ zob%y8c=7z&T@4(IP$3eLQ&XY52*UNzUbRSX67%(=&G4cx4jpQYW1S-g3er_0FTsuF zOZ-A6WW0#r2KO<)zV_P-hrKCkdKrNG^oUuhZ8&3#hJ6#r!WA z`-n^JSSq-9T*nD4zLJxh)C?EpNRXlJ#4kL%tc#8&Rl0~hB8j2*pkVPO` zBQVFnV zcu$F+i6@G38?RaW_^*qSSHj%4<>w*ZO?+-!;$eM#bLX80M&40gfB)`jHP|ULe2$JT zS@^8kwiJvP@2u6S%$qlFc*kdB>RTV*oOmKPIU={Qc)gcfKfcc&L)gz!(TuGUr2w_y>`Pzva?3F zxdd0*4SP-3?dW<sS-Fi3ck$&>&-HvDH+cos zi!lusp>RyIP!>h8mScK>(x7-S3_QZxHP%9#N@ES zU@Nt{HtBKd#1c*mObW9G&3+DR9jhkaS&ka1d8wH%_1^(@eDmZx5ossBu&@X#1&OjE zd@T5vwa?@2D*G3OTk$0|{EI8`62`=VE;J*1GatP>@Q*wC)^7L)-<~UPi#YWS{)O$_ zExg8T=n2-nw`|0$!LJ@Ta4G&i3(DJ+pS1|#g~GaQa_5WYqa)6}yiQ)O;>*D|C}5DY z;g97?^^sV1^W6a|c>8+}ahnVgG-D}-h|i4UoSx+e%@9%IyvxW_ zh6W21cS&*O$~#hgX#0yb1wCGs2y1pqb;Q5#hAOc?tGv8iucV^9jKYX|&IrowEDrfQ zwfyL993&syvhz(9?n*vrE&Cb9J{}LzEC|UyiK$h>QKCjL5<&(+IW z5}Ng(YIAyJQ}7`fmH1Ng8v4(R#(%6=trG}RuNo{~^$wk_S-k35FqN1Ws()wTuOF@M_O*42=GL{QT7#^;_yRSt}i=}iZ z4@_@e3z(nhVd3W%!C4V&+KRn~3FLth} z{zx~o1y-Qbw)Ze&_&)c;IRLne!`+G3Zk5-(aZRLvSGQFPcD6Q)b<^jajfRfIN5<#V zjPr@2WwlK;h1su)KGl_Ao>t*CA!PoBGN}~k(Xf*)Kv8Qy8R-&!y5hC`=EbO9HY(FA zSlikR#fr1bI1#Q@N=C&Q#Ar0%V=AgN;|&uGt}tP-BXK`#iQS)DzkbVt2$=VeV!0UO zDlyUQTG-qi8QmMO$d^8^tIiL|ih=33GH}snV9v(!jNe4W7tu2ZIA?O2^_^>3%^r39 zS3%=n=eA}CCdCAz@i2K}CFQaNu9^d&L^T4QePBiWLhV}1@kPDa1Ron4 zT{!Qu{_x8Ov!o_%WB4#fFN%MzbRuefYLY4D2SLG+F~+RXQtBaT?Jtne_T(BEqLUw@ zu#uH|Zj=BSTm0RjLq%D-E^PHX%yEkoCs0nhx09qE8UMnyQ0B|*J`2sewM2X4VM z8DwJh%aE7kf2-lO)fgs^pB8f=L`G-)ARQ1Y>j!ishTzBQN|C~A%D}mIY zRV$`DLW5u)A|K!)7it5yN9PGgS%HM;T#f?k#^VXyLJl!0ALrz1Az92oCH7@t501Ic zlCF_q3@BM1Wqgtb516yyXCa2KDw~iG-#oehd<18bi9C=A8cz@@vCG_G>`9p?a&$>j4MJ*aAZ1_<6g;!r#2&RqE!1Cd*k8=1R5kQjwYY;3z ze8YjsWjZzmlW-iW)F{9x=SI9+pKLqWi5nj0)tPnZpuxm83&oQJ&CX{yP}Y?yJtf@Y zBcq;Y3`C)|bWsZzNRalzlbMxxcmnc}0q`Qe!eAPS!R^Cbzzm`)(5t2`%%GH-~~D=M-&bC!3W5~6#BMcL=6Ics0PxF&!PK% zm26G1&tQvqi}DwR5KF-5E0#1y^O^_41je3gGUy_Mf`g<#wD;{KwDaMm@Dk&mw~{qN zVle&&&=BL(pkFLkY7VnT`7D+rg?H&l1qTUM&ab0Zh*4+KdKYPtu%{0^U{}aGfoRpO zqC+FpNL-6}&SmVbu|>7 zCBrers@`9*4|wiCcB1n=hhD5XTInPx6jb4Z63nJ9q4NSN7KCriM4_-m>yXVJh@mtB z7%etr8*q&XX;mwRXQUU(F?FPQZy!INpT)v?S7Vr6tX($cpbjsZHTi%HR>CmG1((1o zHikDgm=Vg0x+EiT(sC#x<`&@yDfpfDuCObg{om%s68ea5cAn6REk{7WIu`-tH8gy^ zMU(8W13q5?=3$tv3L_kfnw+>v>W~J(f4y@}YO_#J>X}8TV6Gp!s3)ri zH86(Vu9)BoHkpp1tY}MkkI5?aW-2mL^DyJEB)}#@VRpm-_tl!h_=t$vZ}07_DGxzV z4V?DMz^;4%Zq|&Epy+~n^w?k~EDQB1K*)Hl7MRcv=Srm^p$aX?8swE=%ebD>32S|D z`xPBn(&#AeJYm+M7l)&7+EEjuK?`JXLrUpTY=-M`O*ta)kbB`e$|L z71-9-0hDZuP&N2X@NnHKVm|Q({vEea+ zAB8~^ZMUy6>E*QTorNQwfdmxv-X9A?gBAs#K`zBmQLF{SvTYGq2)tn_Mmwq#HEOTk z>N|b=jedb}#l-$5e5~juwW2ONcI-fiHP=_T4)p|et>9uFJJS(T(EtEprWtLh3j;Th zk9jnAXR4jd%y-^x-2Q<{l~w06gpq8xfv72K$yQgKQ6XOuTm^f9odbfxi>SYZN??+& z7G(W7Ie-LRR`Sx7k}woQ6IO{nlJbe*ZxzLi4Pu~?=piGo5X=p)5kgA%C}O7~uYGL? zE4xLC$g6!xteIH7r~7j+zW7FG!|!PgK;FyX&*C?XMCcfTqs#>xLmz^{5Y$281WmY4Ws$=WyYUG3qJfYyxZT&rSVQa(^d3gF{ZW9BKu6 zbR8EWj2n^b^dWL2LgQ|0Vs@x@k1!l+-e~#cA_oobdi$(deIF1x+YoYc!7K!|Kub>X$x${+=zQ=p;o#ZuV2we%jg(muBO6IL^`c6|8ZKCGyj)sXO_tRP^{ zL3fmja7l_4#!je#yFs<77q=`w^gQ#Z+lTae>6*7^AI!Wd)VctY)D^IZ6<*%VnK2T! zH_jRz3b~Or1QQ})^(@f&aAXXlx@gucOP6PMasgqzrnp!#;lzw-Q^gSa*vVY<7}wD- zaQ@0=i~S`vSCE5|8`-A9jhS@)M8{;@YF4P~9;|w@)^-^)c5nc5<)31SH?{<&;Y77y zX2}{eTQbpzvze=_v#CCQek$9N{8Sczy6o7s>tk7?qlwEHq}PC~mfafh(fefK{dUpy z5TUr{YV78Lv?37G;|01jcOboHPV*a)=OE>37k0&csnZu#+LwXA#^&Y1oZ(caLaRzN zPmHalUQV?<;|?tf$c_{XW%ce1)#|sTBF@#qtn>@pDx#h6kQ?^l@B%t=-InN3B0>)B z+W5T9!Acx{)Jx}lZ;;ppC!8%qsAk@<<(0|(H|$#xOh@e+4G!q=gD1mr(!!Uy1o|3g z+&m%P(In-hG46 ziyr$mm-sI}d-M(a5_58stFZP1i^H|CN@#`~K&9iKPu=&=uHNq}>CdX}d?ApGymj;pDq$ zv9l|Yx{HukThYJ>P!eAe{0c?=OJv%=&&ATswY`Eu5Cm++|0;4<>_~++)R9g;=`1m` zXnIv{zjppyD37y7Zp&mIn@ zU^>+_a}U`Dz7q-r`gynI!bHg#mt%-Nr6Y#hU>zT2jlD}wJXLVL;e_z}-V(5izI z;KC@pL^ME+6TU$ht~uo;r37U<4y0WzpP2O!W_bhV*q1++vPa`GnPw*NQeJ9MWPMR_ zac5~*c6pi;Z3u6sjsaSxea0nRq(O!5devBWzuMpE+4E#V_KKAZF z;z-5J7-&Em2}O9IM(F{#i_5S2?4uZt#-2vAc_j+GKa`fJU?7%D7Hy7q9lhZjx!fKB zhn;aVAQN3=ge`cmGCfKYBb}SR_OY_yTQ1yQtXv8`WEYUPTZKA%$8gbo)l!2#q$glX zg(C$r1u$XEV{xbqA;lXvoE_hAq*)K=KI_>pQyr(W*9Yvjkl%E{=vm5g#sK z4Vz2yV*^+bL8;%O>DK}fe$)$J@fbS1V%Wldy-XMc6m3L|gfOBAM&oPb%KIMfJ0&Yp zW0?7x3lDP@Av?XqWl|;XFIuCZ+=5}FH~a;71xvmRMjU%Imy>Rvxaik-fF2>pWYOjY zKj@X$eRO*q8$&)*2Xo9svD@0pPyOO_(;P?O7jPZI1pb}K*b~1MM5GPq#pbG<`%W~((=jSE|ENbBvlnQjWpXX&W#-_2pYZH}`E^#oL=F$rTe()pC7BOPd4f{qy(xVZQvE$}hJ6W-JPw7!E1RTo#rN85->UM`+ zc{V75jy$OG7(Rjy{NQ}RlU%LO+}wh%3RY1Cw=y`~jUS1*uzid%{#68tcCavYw$SiE zQKX^txt_1~9I`7b(*AQ>)22}0zW~vz$Ko8Yx(3N6i&~Zley^UH z6suyjO&J)%5)~VP&9r8iaaH$tbJh%z6s#3Q0AaYT?pj(c;o})tGXM-y-b$fghF(G_ z;`&~qTU-hk#c?Y}!kNQg-q&pbudR>NM@nN{a*EOu#Y@hjG-eO(SEQY)8_HI8R$BmLzH}h5uJ_DcU<<}A58e`xM;)Rq|9(1`Rx8Pr4`xPk6sUV;p zN&y2PS-Cc~cWhcl2DL@qYsj%=NkMqKn1I`x9#5H?J z%$t5kZsR6+1Kv z4(R9{Lwg~xw;dJ=2*TT#{DyBK&c(PuWRVvuhbH_;(xoZcyBYjHFO2E3Er0N<=n>qC zZN2<+CK{FMbygFb6Hj6oIgwaP8JV!FfdTjk+2K!079m^?abOIM*j0y|-`G{mU(>0gnCOL?q#;*e1cbrD zDCRP2%;o-2th~`E>OkDVZyo6~C}Gp?F=0HKqXkpcRCroSfD7QVa6K5EhB)%o!W+SM zBt4*M5-brM9^+>K5r_^g)fXXmou-i=L~p5>r50U;fqX6uMCw?!pyWw_r-K2^$=sHU z(;HhS7JR=KLy}CEv#&J|X^wagP*Cs{VVhmZmA-A+7tfo~*w8)+j^MVwcX#pN5-Hki zTknS-{){Uh$%*1?=4-{!b&eABXm*V`nkifRv!+OOK^}l}Q5n=h(OlmP7Lr_vnh=&` z$0-FyQso@h6s8VKUyC(R-%Ed~ZA1C_s1TSE*80yCfvEUA0EOs*jMP|1fpw4e@st!e znOaEQ4|)YpAPr(|Ath{+u3${i)|8j_c8#{Xujtd$rLlvtZibZYLIQwMklGzE!NUw4 z$fA}?qyf~}1q|lbLyLC+NR3P`%WXspELE2GJI83G=U(<%|73FK^ql^gi|u+#pZ8@~ zU_MEdVGk$72YQITz=b&+z~^5m6~o*{63awroB1)(4NPZ3Qz7~wk)}8bV}tzpHXm}O zqk`{*)-#lQ+_P3!9senU60skOjWNQHrZeh5pnZtO*Az&GqPqkcip_jjO$8YgJA;3Z zih#7V3%vX3o1wFk?nl;O7Cdb2r|J<&WLk6HMqw#&13iSroZ5XX6wVJUG@L$TkT$hn*e>?4w8lSeYr7;yJBGY5V0Z=trj3{YE1sFeZL!i2GW zjyPC`!DyYzDUfBd3^e4KFxz@2q(g(j$dJ}cD(Tw=Y@FOv*+_Evy~n-UozOM+~& zLMaU&f*nMy*mtw6+zzu4{WPNmhiMsxs_9OI*7TLU_gybTVw35cWng6OGY^Uq&cT!# z9+NUi^(ufQMoaXmyM{oN;%|^PG}?mgL}0eyE?X^k;Sqw(vc%wRYFa(>{gAN@1X*1X z3`L>?G!c7--i&0Ve#P3lgvaZ9Wr6+}OF{FMn#_zTu%xMrebI;p%e4Ul9q?&{7E&q= zk;wL~t>|-Mh(z4)#)glQ-P16gQ4B%TueF$R%tEicFqa@nPa^<`h^m>%K~}=K;2!+g zb-iF=j3kpr@56p4dL7{H^Bjyz`TN6T!41C z=f+4!P&h?a6?|vW^owfAuPTa`<&cUSqk=o^qChW&1B`)xVjmk&>q3;7<_q1pBb1lj zs04Xg^4m7frufG{oCF{4C)0#2MMk0SNL*OLZ4Dqc^O29wef-P^I2JP$K3I?1bT#S_ zQPtYMzR!Ra8d{jKq%*%t#nLSBaLP`Snz20+3RQl#%V~>EF zFF{Ebar5!q#&(HTDlfGZxBptE0NF<8arD$D#m*>#*cniNZSK%oyB` z1l1DssTrM5d};5)eY4aP>=|6iY2Mhi&Bl}^eu1OD5R=}Q@57k=N#LqRtbBmkFhiVg zv>#)Uic%&6q1F7Fv*$4JH$MXEOcBk%+c9Kv?MiI4LyszU+L(k&YDrkg&+@k*fn8@B zs;r5@VUQ<9gyJv^TcX2M|p2$Jl<^uAeQN)b)9S5M2j>*T`Z#d)C{OnvsD(*@(Gm%}#42+!t zrFfqkEP((h>&j^=EK2~jAaeji=X;1#(M0}WNEiO*0qF$6N`jOF88tSmUVxQFEoeU2 zt%gby6@N4)YUZZX8!{RotN&R6sThsb(E9XLX81a$k9>S7~c3ZigRDo%H}GAr!cnl6E{o@r5q_UW7$eypyn zAqNx*#RBB2dB4G;CijYir@3JI7+E*P7qQAyz5r*1zkL&bgLAnyd<*A7AX@+};R>5u z0Jvtzu6sIXMH~4N{T!L=>ybIM&bC%aR?nP8Q^e5Wa-?7h1t{vnV&uQWRh6#7o#Dea ziYOYJup)`GehhkbDh0;m!ZRr``#;#pYRBea91d)G+g6jNZBINB3O~L`U_hM&!5#+f z|JT@0ghp)%A$1o~fh^{t(Yvax?|X7@UJSlL0ROLo2JET$wBqiH7_{4HG6~JwJSa391osRRG%t zkRo9LK_FTf8O~5Z7C>jThbR#1u&*k#tY#zw0)YG!s#yAQEI><96Q?bjs+CS!3~+UaDEU8h0YKZjNOEoUON-z+ob!+k|osde|$>Yzpbh8Cc`WUuCVNei|1!B zL)fFD2N@+HoV}fmM-0#}aNwc_oh|ECco9en^CV?tthxZvJ-E~gT)UBE zA=2hGm80x>d(c%@faM1kuGn{*SenbG1rQ#5G0{=&{vywA9>X}V0qS)Q$q&Ykj}sit zL=-O#UFL+0&)RtcZ4J&oXeQ_81fc7-2wzSdVD-8OFO8N8R05k6grE~mznwL?hNJki zuJU;dZ7_qpXwOx8bzFQg=`g{b|8X@$DE#MyAXNK?86X2F9fVV27fm=zPT7VI8M6Gj zejUdDpuBmFh*0Fm<)^X1P;m*K_PYg!btpp(b)74U#h>*8?MTcT`fDEp=+`s@m`^ zTWfR84ne-_nyUNMF>|hvg5NWT8049m;*_|%yR@$@QX*8?kWQ{avhY0W5oBlAkW>I_ zvv~4L==bXO9q{xMqe0*3`^00O4kIh?;`>;qQ^JPHaP=}@&*ePl)bo(~cQ@e{@hfQm zEe$x~R3To+#|zWK_Wyg~7gk z6egNnj!Gc9DzRTD!a)$sgGD&gCc3~_=ZcPK?3Mfr9N7RFuna3#)>$|&XWda))&d9@ z5c+IpSpl`k&Xl{*W~&%G?ksL-&%%CoRhni1c7C!_iRKXMV?dxy zVqp+ms5JPVgiKKu>Q`a7WKa!$fEluI2Sy@2T5LuBM}DJhN|`rImH_~|NnB5=qZ3jT z%A_Qtp|aeQXvjs(a0Vxk*U)jY#EbN?Rg*XopR|vo#l1ofgG~`w{MH_hf*)saB3F2C zP*T%VHe6PW6sI1HAT-BBAUY91+xMeTYroFLbqzo{+yjUct_8cba_Zxrlu~WXlGv;f ztwUlFV~?7);NIbZCLVdOG2)5=v3|=~G79x(UBe9y$hsiZXV1l0nLOl7b8K+2@G?LC zm=!s>7?3VSbIwi`Fz(3Z%4yysOq_966!wsJ(2oqS=>YM^Q3kSEJ_|=zL~#NhCWsfo z3^iZXrl6p;&Gn!2IKvOLF~#uELtlK6b%ZC!CF~}vj@q!E^}1QXnO1Y#TPR*}*#ypm z8X%jyU}+A$qXJHw^JAN#h_gonCk)FVmQsJRNGX9BSy^`>N;W;Pgaii4NTougK2I2B zzEoje=U`w@u|+b#6@4&CT`98bsM*)q<&M=eAGeibX5SKao$56tI&GDPVNzccLP4_y z2Zv9h*NX>A;ko1qqA)>^sK$W&*1xg<306DyF$^t45i(hRfY2g1$-scgb4e#h+X#@u zJ=u54OPzEtk!xM5`>oA&I)+JyYeSawFQ9D~;)&!s7s*-|AjGpzD^ve9g-=YHHQ%1- za!A2TFCtsum(jyq1!52b^mSIpi6mLT5I;^wtQJS7g*9TijUZ|(h;G;{hlI)2DS~T4 zzOh%Un4q|55JF27E6^qjMVAPc8W0@R*FtC^5_o!rv-y^*1O-7HKG}ekxHl2r=68Dm zDnb5%E$pRmKv8E@!vs)yg@;tAlUj{~e5nl3d8rQ=8^D0ku!lbOLfj%zm&Hnl?3vy_ zHTw>i24YA9`U+$!MRN`z!@oCX(9+Jwy@2tP{7PYz0R^4<5D}(CIk<@6&?VhgePvp- zu_y$(6WX&?EV}WvSSF{h#G%9zEQ-IuP9Moi+}c98PBct53GTuA`noAaMc8fqM*KS| z1xb$|tGf!j$~bGr4gd{iegZt-pa(4hTo`P{#SqEHpb4AHFashYS=`}g{qG@!5qrdZ z@P^77&#o2H1h1MU#IWK=sJ)?88Tw^G$n{ZVU+0pvn>0a2D`n7AvSO}XfS#yN4v}3)`M#cD&QGr zi$b3c1_`O6A#2%4D8Gv3You>|QP+Famd5M$z1g?;%;@I7w&pMgTJCb7BuD}2*psp* zfEtccQKBo7yNiq@tQru+y|Jlsjk=K}c)GJuMigqBL0AwJTA?~tsoF15%^Cr_`C0)W z2T){`a-1xLVOd^F`7Nvij}@R=Rv{C!tL$}QwS5>4$(W5L7l2j#adM!L+Nm@>KekGT zdNHZ!Gw1h^6VoLuTRu(#i%f$i$+ON5PxSeMdNjS*$0qaK@d+X`0}^`)EJ{nop1}y% zk7g}G77r~j%?^p}=^mZ!iu5II=Fml~WVTk^)GIhw3UnBBCN8Ui-1?JyCI;>#;BZC7CsgXl*u&hzOv}C?Q^PbFn22S3n*i-UmI9H*GN|2)$9}m?tJQ~4 zQ)8LhKecK_JjWedRj1kPWnMPSE>=yt+=L>Y9#y*fojY*oov=*wn2o#a1-`qK`gg&akwtMbd_x9mOdq=$ZIdrl^66bJFGTj<_3^ zgx!)IK<^H0>zggLxNidFw6Tt)yJ=#_g+XsSfFsT>z1ZN7uB8Y*SvD9y=npjZg7)`bce*;L2V2xkBC6jYRd8XQ}nwjrDLn38=x*-cpyl#dO2TIox^}d>~y7T)MZ!8{0bF(0*UE}Bzo~hg^JY?r7NeHxV&Yo1njvB7as8?hL2UuwY zvd#nx4B2}aMbImEGuCSvAbqO%eLT|{XVp?3;85O_qXGz7f>K7y8H7urm&+K9^q~q! zkV_@2AOx?J(GNw%mmA;g8$IH1WwOIn)#88PNzc*`%UwR)TIH?p;3Z57EE*O8MMvhY zaLr_0VKlRmz+O}=hDV{SDI|)JiPLR6JjN6eMpQJZ!jL6-L#kx!0i!FCRQfE1N(=&8 zl4Oj<{qlGu#g_DF>bA^w=!rGvNCPzC#nC4Y7KQL3_5j<^tV99npA~}*uUU&w%+P4d zz?j8k338FZ%j8&drL@p0IW$5qWUs+fBeIF45Ies}pW$ouB1qE2S0Qb#oEz(82F_J*36UWEZqbHapzE;fZ6wwpcTL~FFy-{M;NM+4TI_8-F@h&~ z0cc&ZjGP3Eb%uyY^Fv{#@+q343zb@QBuT+y_foF3AJ=MTjD znqbaVYC&NA7R4KMyx?NEQfSDjDh%K8?VAxunq_dJ9FXlAgEI)t%FApd7Qm3Wj1yfM zrG>*G{+cHmloeMDeKR0~1T_O~b3NX;PX$|&u^qGyo8OVkRbX>xkLXc7v92MNZ}oEc zGHm?o$rZP->W?KfV6Vnz@m&>*xHx=6+y?U(T5WwuBttiFmJ`u4%?00bN(2II3#X$; z8Y>Z7Q;)=7(<8-+#45zA%^0kMX*C=dlTSdE?69a{bDgsopVPq%bo)s!Eq?6SxwDgh zO8Uy=ovx2AxLwi&-f*M9RNd*l289HRqIsSGpdClbuw{gy=scm~9ayLue%jKf$6J zz6L&Ld2W_^6rV~?1TT{Jd|#6^81J(|3cu)A_!!JW7>@nzWk)1FvOH{8J78C`uyd?% zGz4b%SKw#_?EatY)@@>)Tz;4>_jHpTukl=2-A1V^QWEV)JUayiw5W_r`=*qNPx78G zELn(bk((c&ssb0Rr71;n1IR3tl0Na|;>$=g1ukF#k4ze2<(0fl-<6t6at+LlmIaVy zeF425dDy0cYU=y<-+zBfTlJl;mp1+f>541jDSA(Gw>_N=`Ijv6peBZENeJUn2x1Q6 z{lMPPlOQLJ@+gu?=C9#}sDuz6@)z?iViY-(;0j5S4Ok}7lK{B-I}O&-A`SEMw+c%7 z&2}89Rgy#q8XB0wI1u^~9i(mqFw>x>^FhX_D{+`A1bOfFpr;h#GL+%U-2SfQ0_k@^ zyF{ep!+D*S*tuhaBlma*1Oq5HW|V2j*2t_O;m;v@{0)?WT_C6y0F&5X(cgr)h&{QW z<~)$*WXwg(DYPKtc=$zsiv~NclG@DFMLJe0bQ@YRiih7?V27 z_UIzjhd?kXp6Ve5tJF+XJj>#;bu)ukc&Y{f;IRRZDrdx_IVp2g8&dPI;Y`d<42{(* ztln$HGp3nhUF7Gulzg$grQa(iZcK~uFpFHD7gq3ewkOMj!ZU@9lNQp*aQi4QpJM5Q z2ykO#9yBC7bb7vugvIiw3U>;4$3S6D-=@LxFCDOJb8v)f!?-0(hvdKpW-~~6SHvgi zZ^!J>DlK#X9?^fD1>GoKZ9aA6KK%0J19Y*JRjWC1ADS&OBCwA`O{kkM*o}pWN2V!SWC)SsU3{Zn0$&P^BEDh+1#(^AK_Me0o!Cn0iOoI4N|JkQ zAEru>4v7yjBvOtCuvp_!hIlu;#NA*)4K_!u@XlZHgQ3|}&3iG(4kett0cT{TvrN(y zo(RGnczhNAL#GonF%k)3HTr^eSrsjY568wLxg6y)6}1qop>Z`y7!&vt7R*r)am+~` zD~WOsxsC)jB?L-eq_yBtq*Xsd0iJ&tS#*M)wD*H&UxEji)JqBtHl zwXtxjG*eZa=6I+Y7*-C~5@`3skGPxIju@H*MuQsG@v}dFDg)SHT$8pv7Ov+ij}OWU zO~We<8^`nPRZ{YlKKhid0%g|`*h;~y6dVPF`7$HDFk~V`V&b%;5Izm#JLcvw4LoBa1VRo9#l^dPBtWqx zu*B4JFgxCIecHk8vhKkfL9~xUgPz3B!VJl!_uul9GRu5wD8=pjiP)->IDRXDs z6dIPo(WH+6oBv99QVw8vS*A%-Sgq==8xfr|mB<12K0-KCe37ST-aK|@fh2sC} zw%{}2WV}sm-1UEyxwAWi*Ic+5^g|x8#Rx#mqW8O_UqV(vKiqnAr+7n>dLh@BNCP2nxJP~-!K^R$)mQvCx-z*j*hC(F1+hSv7X zs8Yu2!bXNU%3tEkF>>gK5#&O3D7u) z*osCHAJwDrao8lbC*rQDOfSb({Q_%Shaw%oce-s_K`t;)&Ob|y!Pl6gEe%p|F9f|) z`mg2c;SimaHSAcAK_*DO4MfmnvXvHaee?1kD=R^B4=WsO57tLvtwZ*P*&X}-nvT%k zXYAgp_<8vI05>E;qvozD8ydf#vi2MN?{LX)hm@aj!Y0B#4=Zx@dG4%`>`HsgY>W`z zDy9a<${>mGrF3!e6`#l8yEIJ&CLl62VBX9VSm?0pU91v8jJO+=FGi-X>cX-Nq>sT$ zGSeDa1H_-Rr~%celzFO#bWpIHM)nF|XQ%F_8_Dbx=d|E(E9aqe!!@wycs_Aw9<_|y zft-__-P$b2zD8=&QnPf^3#*B??m3mqEhk5@2zE1oWJKJirk&WNh_lNtDK=L|sP@h1KXc zDeH4zMIbXVo$zP1s0y-UavDQ}oqQOug8wY_xFsFv3>g8)7tf*i3(7`3E@A*Gk{LRV z?M@z1{UjsBI=z^iMh_jaQ?07edx@pVzWotf(>35CSqB`m zrCRcM@Fq||{9Ku==iUat9AIy`zPfFUoGP7#BTJ65aRw(8Oq4j`<+!5DwJjQl?IGywP6J*^=&6i>-`}!v;|{$0H)kh{WF}VJPHxj z6ImFRB?>@H8gnTUl^NM^Y8dvJGAjr1TnJ12colq|dup%|9^@IV7d-rkCrr2~a(zft z!qZRVASa2gHTaXtvFOX#rLn8#S)sOn-St1w81$veywnIImU0t&qP6he%E zCZvcj2fJXGZh0)=Qfr;vv+8KjlJkU;9vzUrU{n7b=m9o{;$!d~Qz`Jw&$fWj{+u<2wR9MuJ~1Y! zVFQTf@{MQMo5^nNNUqUZ3D|_lkg5&EeI<5hXcM|BY!lj|UMvS2Vu=FjWq;Y%l$o+9 z3Z4Q8ZP*Px7Utr>spXrwRSU>dv^0eJV^Q zlPzFL119VlDC#D#3A`-FLF5gswR_xxJ40|(u~wrcUJnw$s>UcwVQ_j~cr}qFM(0uE zXeuIOqOmE`QLy6YUVToGGkn`HFLMo|3POJXLM^2#SXyX!HUZ1PiX&YRVuGa6ED~tZ zo=2ho^zcm^OV|tQ&Sk*O11gFN9_w4Y;oOuSq;9SUX`t7G1m14=F<7+E zTNECJx)8*zHq)F)huZ-~Ab7^KLwM_Xg&(IY$Fdm|zf#`@H zEyRe@O{$8u7gz+!0IrA%AS;#H9Z18qI1T+l`YjGEpN5l(C%RRTtHRR43#cfVY8BRc z5pN*2wBA1$iIfk-;6sbFK4CjOBT(pDqt3|(MjMpyWhutUqd28*`Wp?pW=pEIOyFLM zWx52w=J%N#XceCq9v$2+9giUg6TEL&1x}k2_K=q)-l} z;q8PqEpr`mQ^S6gXH1I|y%bAm1iUAuo)sw@GJDHi0qtE*;+9^>I7wR zPa|)p(m@7tcM?#${`xc?Xlo0ik906JYEsODA=sT>&L$*7#9Soxgd3q?N9*7Mi&UL> z+$*N#wjyhNOWy^YVQ1FV@L)A}u0?&gH}MS#C1@{q9NQ+p+?Q($F>*y4drdet;72nP zv0JtvqICuu6|{TCIIIR5vJ$98IU(+4#_fH={A@gC4+2^jrBKa|Jhw4HEjQhpHQi$r zwgzc@*RHDb*l?O7l0=7z$pmO4oDl5>JJYr!#QVAJTVuYIgF<@Vv+c^7BUl=Sz(FOD zWv9gt?vRru-i+mEi(1gICmLZikf{h!o~XfDYq1{xkK^kp18^9iGn=^Mj$*`6H+_t{ zCa{}c9H(bv1mGpYFu{CaGl-)wTqu=Icie^r&WC$Wb;pJvEViT<4y(gvz4P=?R-D|X z3=`+&xI~Z*7t)=Necu*5ZELJ4LEzj98Hd201Xzy8ewgox0fx4!Vs?^^DkKV?nu_8) z2T)(EZ&sHXtJMBJ1ZN(60lS5x%677paBcc%r5xkR5MCt~QFMrmUOoZ z?IIMO0|7>JBj)ILz=i-d7=0ra;EXt$dM#kXpk=$5F4-BDjYs;+jW8(S>! zZrF+-cH+Y$CM%9%T7(-@vq0Uk_}Gtt|lA>H9$B@LXSVx&a*b&6EvD z`0})lQ8J*&>fFhyhG8No_QlMA#>T)Qy+DFmB04W+2t7KLDOz1%Ok7^Yjo&6CjIhUz zE1e=b1QqNM?e>Cj9e=MV?M$87D@Qnqs`Xi4w$z%^W(kaIoUJwHSUb5J#JG;?=UJte z@`5c=SIo2bA5AXSBQhpT-F77zHP){ba**B;`fzg}q$mI$Q;}|IrtMe&6w&%}l5C2| zZ7j?KK5ya9d+6fACAbHqjUe+MF(tBd&%Is_;||{pA7#i7O&!cYgi(~@h3gcjHlY<8 zS}<12)D(_@{n`i))@-InC8{!5Mz2__{!< ziIb#3JS8o$b>WabXQgyrRxC&}SllKIe21OW;GrXBC!Gotv|TXM6g)MV&XDGa7${0> z093fzEi~?`5dPz|%IitUIS9Tn>PzD=r zphdu_wO`j&%WRblcf9Ww-UDxoVCjs@ZO#au2^`Q4LQNazngc7v{dvDFh6@X>Vtm#r z4P!G9ilKWp>BNdZ*LNZYYDz}<1`eF(XOp3z4^5kc**&5g%5jz!@&&V-PtNW0xsZS% z1B@}wj5aFUhAeP)f&C)9^FDg!v|`@YhnuI9xNjJ5HFHH+zzz4-ulH&@_SERr>mSCT z{ezS+5zHtGH4*Y-=p&>l4w^00)k zV{f7GAw(cK)dk{2pAn+HAwZ5=I&qp1j$hc1>6Y^?iA3i|N_!l=9lOTON!C2P0)2w0 z`V3{&$1MV07nW;xx&uey(KJBWK@2m*V{z(#y2fL9co@T7rO$d2rAoIGunY~;i&=ap zC3j>nKoOd~^{th6OQ!_fp!InbB79IRQ@~Qsk~HyM^FL*YOb)@Nl|Fip%n_0h6`7pWuwiwKG_1}f37?5PdiZo?C(l0Hp94XHfIYT2 z*uZP*Lhy=4X4tsl+J=F{4pKu0y)x>cE;NU}DoAOK?IiXEmH>Q}ihjAYw)XfLj}*Zj z+F2tZK{lsedbX8XC`&0uNL@k?%V39`XI!B3x)snZUa_&2Cm>_{ZG(Tyown+cu4>jp z%8dnJjoEw9-|*?Dj~F4M`%9{2z&zegA>4_4ih69iuaZ+5_vAy`oC$w;D1{|JU! z&{wHyXo5q^hFLZ)$bF-^@2384KpYW>%SUuY@Ewjph_@`i8^@z;Shg|3#0Gx0AiBLJ z_>^`4%klQyC!w2jOV+Lr>)Cr(=vg$$V`1y+&-0G|EbsV-HDKKjbwd7v_=HjDDR*2+ z@X|h*;s2$}hH=-EnWid+cpILqbwZVy4dAx4g7Z)6SgtK)l7eF(z!lNz3YEx_Z=w0o zfBnkVKY}*7fu2_hM&9hIXh-R%y%wbS<( zRP9($b-cdxaDDRcvg-T*OSrs;hxEK!zD))$C3~%s$$E}SqxF?=|GXd^(GGtAfihzV zf5FYc3{tlTDl&#IGqf0iKXR6RWM91Gl1I+EWRA^q%*X7TMA-0;!-vYF_+f;g$cGR) zcm2 zuDYR954`)33)aJ3uulAyi`6`;m?k32S%6Sn4V?n`sfH^>-AtJcV}!*}O9ADtOs1xC zrv}aZ;UK;cZP2!%D5N}$=OH)M&3@h)x9h+qx!t-Ew_!m|54Nq*C~}^CiiL&{;6-bg zsVvcCz*GJ?523*cT^)YAQ^<4@J7A}su}j{bWd(6rn#04=Z3~7_Y%xv<3HlMS(fAOC zAR4@=X$-}sPprvG5Vl;#N>~Fno_Y1w5Hulwm>BQKjVmEYfVauP^<*ljpsjs=VNurP zJNx2L!yRwtukG~Q!lKEYZ|_^XqwA~rYe9gDCf`|pVyAs)YOEHYLRiPgz$xVm%wv85 zzK+kBY2v{)+(42qY@3Rs1Mu;3+~|_$!lP{z;SLau9gX~ncc`$p^U({4ov~Y$10mQ1?LHDJBOI*93r+;?@n3$iEKeSF)IG$sF=H@aeN>5p(YOge$wh0 z->QxtOF!eU5B2-CLz;I84#V*V6hsbdT<6KZNC!W3hxs5lKjtrWz59g(mD|CU} zUBn)kmUz@2&LSW6el*2<+xMnrJmP20z4`1OHDCE(XJp~u=#e*Fzxuk{=lp-@ Cx;u0L literal 0 HcmV?d00001 From d0a91ca0710a8027453da1aba8c91304c94027f5 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 18:05:31 +0200 Subject: [PATCH 76/78] fix CI issue --- src/lang/modifyAst/angle.test.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lang/modifyAst/angle.test.ts b/src/lang/modifyAst/angle.test.ts index b020c4f3f69..ba7d752f27d 100644 --- a/src/lang/modifyAst/angle.test.ts +++ b/src/lang/modifyAst/angle.test.ts @@ -1,17 +1,18 @@ +import { join } from 'node:path' import { convertLegacyAngleToAngleDimension } from '@src/lang/modifyAst/angle' import type { Node } from '@rust/kcl-lib/bindings/Node' import { assertParse, recast } from '@src/lang/wasm' import type { Program, SourceRange } from '@src/lang/wasm' +import { loadAndInitialiseWasmInstance } from '@src/lang/wasmUtilsNode' import { err } from '@src/lib/trap' import type { ModuleType } from '@src/lib/wasm_lib_wrapper' -import { buildTheWorldAndNoEngineConnection } from '@src/unitTestUtils' -import { beforeEach, describe, expect, it } from 'vitest' +import { beforeAll, describe, expect, it } from 'vitest' -let instance: ModuleType = null! +const WASM_PATH = join(process.cwd(), 'public/kcl_wasm_lib_bg.wasm') +let instance: ModuleType -beforeEach(async () => { - if (instance) return - instance = (await buildTheWorldAndNoEngineConnection()).instance +beforeAll(async () => { + instance = await loadAndInitialiseWasmInstance(WASM_PATH) }) function legacyAngleRange(ast: Node): SourceRange { From 13792e853e760d1cbb4bda4a006ad4db4c04e3f8 Mon Sep 17 00:00:00 2001 From: Andrew Varga Date: Tue, 14 Jul 2026 18:27:28 +0200 Subject: [PATCH 77/78] fix CI --- src/lang/modifyAst/{angle.test.ts => angle.spec.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/lang/modifyAst/{angle.test.ts => angle.spec.ts} (100%) diff --git a/src/lang/modifyAst/angle.test.ts b/src/lang/modifyAst/angle.spec.ts similarity index 100% rename from src/lang/modifyAst/angle.test.ts rename to src/lang/modifyAst/angle.spec.ts From 393a5f39a36efbf67dd2424a1ffb0f21766a8612 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Irev-Dev Date: Wed, 15 Jul 2026 16:07:08 +1000 Subject: [PATCH 78/78] Refresh sketch solve lint diagnostics after synced outcomes --- src/lang/KclManager.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/lang/KclManager.ts b/src/lang/KclManager.ts index fea0c9ac35e..8a086ea4823 100644 --- a/src/lang/KclManager.ts +++ b/src/lang/KclManager.ts @@ -35,6 +35,7 @@ import { getSketchCheckpointLimit, parse, recast, + resultIsOk, } from '@src/lang/wasm' import type { ArtifactIndex } from '@src/lib/artifactIndex' import { buildArtifactIndex } from '@src/lib/artifactIndex' @@ -1268,6 +1269,9 @@ export class KclManager extends File { syncSketchSolveOutcome(code: string, sceneGraphDelta: SceneGraphDelta): void { const execState = execStateFromRust(sceneGraphDelta.exec_outcome) + this.diagnostics = [] + void this.refreshSketchSolveLintDiagnostics(code, execState) + this.execState = execState this.lastSuccessfulVariables = execState.variables this.lastSuccessfulOperations = execState.operations @@ -1283,6 +1287,30 @@ export class KclManager extends File { void this.updateArtifactGraph(execState.artifactGraph) } + private async refreshSketchSolveLintDiagnostics( + code: string, + execState: ExecState + ): Promise { + const instance = await this.systemDeps.wasmInstancePromise + const parseResult = parse(code, instance) + if (err(parseResult) || !resultIsOk(parseResult)) { + return + } + + const diagnostics = await lintAst({ + ast: parseResult.program, + sourceCode: code, + instance, + rustContext: this.rustContext, + legacyAngleRefactorMetadata: execState.legacyAngleRefactorMetadata, + }) + + if (this.code !== code) { + return + } + this.addDiagnostics(diagnostics) + } + hasErrors(): boolean { return this._astParseFailed || this.errors.length > 0 }