Skip to content

Commit 5c471da

Browse files
Major axis 2 (#7971)
* change major radius to axis * working sketch with major axis * change docs * make trig consistent * clippy fix * more clippy * graphite fixes * major_axis encodes major radius length and direction * update modeling-api to v130 * fix sim-test with local engine * fix docs with local engine --------- Co-authored-by: Adam Sunderland <[email protected]>
1 parent c6ee9ec commit 5c471da

File tree

15 files changed

+167
-58
lines changed

15 files changed

+167
-58
lines changed

docs/kcl-std/functions/std-sketch-ellipse.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ Construct a 2-dimensional ellipse, of the specified major/minor radius, centered
1111
ellipse(
1212
@sketchOrSurface: Sketch | Plane | Face,
1313
center: Point2d,
14-
majorRadius: number(Length),
1514
minorRadius: number(Length),
15+
majorRadius?: number(Length),
16+
majorAxis?: Point2d,
1617
tag?: tag,
1718
): Sketch
1819
```
@@ -25,8 +26,9 @@ ellipse(
2526
|----------|------|-------------|----------|
2627
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
2728
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center of the ellipse. | Yes |
28-
| `majorRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The major radius of the ellipse. | Yes |
2929
| `minorRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The minor radius of the ellipse. | Yes |
30+
| `majorRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The major radius of the ellipse. Equivalent to majorAxis = [majorRadius, 0]. | No |
31+
| `majorAxis` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The major axis of the ellipse. | No |
3032
| `tag` | `tag` | Create a new tag which refers to this ellipse. | No |
3133

3234
### Returns

docs/kcl-std/functions/std-sketch-elliptic.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ elliptic(
1313
center: Point2d,
1414
angleStart: number(Angle),
1515
angleEnd: number(Angle),
16-
majorRadius: number(Length),
1716
minorRadius: number(Length),
17+
majorRadius?: number(Length),
18+
majorAxis?: Point2d,
1819
tag?: tag,
1920
): Sketch
2021
```
@@ -29,8 +30,9 @@ elliptic(
2930
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center of the ellipse. | Yes |
3031
| `angleStart` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Where along the ellptic should this segment start? | Yes |
3132
| `angleEnd` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Where along the ellptic should this segment end? | Yes |
32-
| `majorRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The major radius, a, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1. | Yes |
3333
| `minorRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The minor radius, b, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1. | Yes |
34+
| `majorRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The major radius, a, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1. Equivalent to majorAxis = [majorRadius, 0]. | No |
35+
| `majorAxis` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The major axis of the elliptic. | No |
3436
| `tag` | `tag` | Create a new tag which refers to this arc. | No |
3537

3638
### Returns

rust/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dashmap = { version = "6.1.0" }
3636
http = "1"
3737
indexmap = "2.10.0"
3838
kittycad = { version = "0.3.37", default-features = false, features = ["js", "requests"] }
39-
kittycad-modeling-cmds = { version = "=0.2.129", features = ["ts-rs", "websocket"] }
39+
kittycad-modeling-cmds = { version = "0.2.130", features = ["ts-rs", "websocket"] }
4040
lazy_static = "1.5.0"
4141
miette = "7.6.0"
4242
pyo3 = { version = "0.25.1" }

rust/kcl-lib/src/execution/geometry.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ pub(crate) enum GetTangentialInfoFromPathsResult {
742742
Ellipse {
743743
center: [f64; 2],
744744
ccw: bool,
745-
major_radius: f64,
745+
major_axis: [f64; 2],
746746
_minor_radius: f64,
747747
},
748748
}
@@ -761,10 +761,10 @@ impl GetTangentialInfoFromPathsResult {
761761
} => [center[0] + radius, center[1] + if *ccw { -1.0 } else { 1.0 }],
762762
GetTangentialInfoFromPathsResult::Ellipse {
763763
center,
764-
major_radius,
764+
major_axis,
765765
ccw,
766766
..
767-
} => [center[0] + major_radius, center[1] + if *ccw { -1.0 } else { 1.0 }],
767+
} => [center[0] + major_axis[0], center[1] + if *ccw { -1.0 } else { 1.0 }],
768768
}
769769
}
770770
}
@@ -1272,7 +1272,7 @@ pub enum Path {
12721272
#[serde(flatten)]
12731273
base: BasePath,
12741274
center: [f64; 2],
1275-
major_radius: f64,
1275+
major_axis: [f64; 2],
12761276
minor_radius: f64,
12771277
ccw: bool,
12781278
},
@@ -1524,13 +1524,13 @@ impl Path {
15241524
// TODO: (bc) fix me
15251525
Path::Ellipse {
15261526
center,
1527-
major_radius,
1527+
major_axis,
15281528
minor_radius,
15291529
ccw,
15301530
..
15311531
} => GetTangentialInfoFromPathsResult::Ellipse {
15321532
center: *center,
1533-
major_radius: *major_radius,
1533+
major_axis: *major_axis,
15341534
_minor_radius: *minor_radius,
15351535
ccw: *ccw,
15361536
},

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

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -538,14 +538,16 @@ pub async fn ellipse(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
538538
let sketch_or_surface =
539539
args.get_unlabeled_kw_arg("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
540540
let center = args.get_kw_arg("center", &RuntimeType::point2d(), exec_state)?;
541-
let major_radius = args.get_kw_arg("majorRadius", &RuntimeType::length(), exec_state)?;
541+
let major_radius = args.get_kw_arg_opt("majorRadius", &RuntimeType::length(), exec_state)?;
542+
let major_axis = args.get_kw_arg_opt("majorAxis", &RuntimeType::point2d(), exec_state)?;
542543
let minor_radius = args.get_kw_arg("minorRadius", &RuntimeType::length(), exec_state)?;
543544
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
544545

545546
let sketch = inner_ellipse(
546547
sketch_or_surface,
547548
center,
548549
major_radius,
550+
major_axis,
549551
minor_radius,
550552
tag,
551553
exec_state,
@@ -557,10 +559,12 @@ pub async fn ellipse(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
557559
})
558560
}
559561

562+
#[allow(clippy::too_many_arguments)]
560563
async fn inner_ellipse(
561564
sketch_surface_or_group: SketchOrSurface,
562565
center: [TyF64; 2],
563-
major_radius: TyF64,
566+
major_radius: Option<TyF64>,
567+
major_axis: Option<[TyF64; 2]>,
564568
minor_radius: TyF64,
565569
tag: Option<TagNode>,
566570
exec_state: &mut ExecState,
@@ -573,7 +577,27 @@ async fn inner_ellipse(
573577
let (center_u, ty) = untype_point(center.clone());
574578
let units = ty.expect_length();
575579

576-
let from = [center_u[0] + major_radius.to_length_units(units), center_u[1]];
580+
let major_axis = match (major_axis, major_radius) {
581+
(Some(_), Some(_)) | (None, None) => {
582+
return Err(KclError::new_type(KclErrorDetails::new(
583+
"Provide either `majorAxis` or `majorRadius`.".to_string(),
584+
vec![args.source_range],
585+
)));
586+
}
587+
(Some(major_axis), None) => major_axis,
588+
(None, Some(major_radius)) => [
589+
major_radius.clone(),
590+
TyF64 {
591+
n: 0.0,
592+
ty: major_radius.ty,
593+
},
594+
],
595+
};
596+
597+
let from = [
598+
center_u[0] + major_axis[0].to_length_units(units),
599+
center_u[1] + major_axis[1].to_length_units(units),
600+
];
577601
let from_t = [TyF64::new(from[0], ty), TyF64::new(from[1], ty)];
578602

579603
let sketch =
@@ -584,14 +608,15 @@ async fn inner_ellipse(
584608

585609
let id = exec_state.next_uuid();
586610

611+
let axis = KPoint2d::from(untyped_point_to_mm([major_axis[0].n, major_axis[1].n], units)).map(LengthUnit);
587612
exec_state
588613
.batch_modeling_cmd(
589614
ModelingCmdMeta::from_args_id(&args, id),
590615
ModelingCmd::from(mcmd::ExtendPath {
591616
path: sketch.id.into(),
592617
segment: PathSegment::Ellipse {
593618
center: KPoint2d::from(point_to_mm(center)).map(LengthUnit),
594-
major_radius: LengthUnit(major_radius.to_mm()),
619+
major_axis: axis,
595620
minor_radius: LengthUnit(minor_radius.to_mm()),
596621
start_angle: Angle::from_degrees(angle_start.to_degrees()),
597622
end_angle: Angle::from_degrees(angle_end.to_degrees()),
@@ -611,7 +636,7 @@ async fn inner_ellipse(
611636
metadata: args.source_range.into(),
612637
},
613638
},
614-
major_radius: major_radius.to_length_units(units),
639+
major_axis: major_axis.map(|x| x.to_length_units(units)),
615640
minor_radius: minor_radius.to_length_units(units),
616641
center: center_u,
617642
ccw: angle_start < angle_end,

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

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,7 +2003,8 @@ pub async fn elliptic(exec_state: &mut ExecState, args: Args) -> Result<KclValue
20032003
let center = args.get_kw_arg("center", &RuntimeType::point2d(), exec_state)?;
20042004
let angle_start = args.get_kw_arg("angleStart", &RuntimeType::degrees(), exec_state)?;
20052005
let angle_end = args.get_kw_arg("angleEnd", &RuntimeType::degrees(), exec_state)?;
2006-
let major_radius = args.get_kw_arg("majorRadius", &RuntimeType::length(), exec_state)?;
2006+
let major_radius = args.get_kw_arg_opt("majorRadius", &RuntimeType::length(), exec_state)?;
2007+
let major_axis = args.get_kw_arg_opt("majorAxis", &RuntimeType::point2d(), exec_state)?;
20072008
let minor_radius = args.get_kw_arg("minorRadius", &RuntimeType::length(), exec_state)?;
20082009
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
20092010

@@ -2013,6 +2014,7 @@ pub async fn elliptic(exec_state: &mut ExecState, args: Args) -> Result<KclValue
20132014
angle_start,
20142015
angle_end,
20152016
major_radius,
2017+
major_axis,
20162018
minor_radius,
20172019
tag,
20182020
exec_state,
@@ -2030,7 +2032,8 @@ pub(crate) async fn inner_elliptic(
20302032
center: [TyF64; 2],
20312033
angle_start: TyF64,
20322034
angle_end: TyF64,
2033-
major_radius: TyF64,
2035+
major_radius: Option<TyF64>,
2036+
major_axis: Option<[TyF64; 2]>,
20342037
minor_radius: TyF64,
20352038
tag: Option<TagNode>,
20362039
exec_state: &mut ExecState,
@@ -2041,21 +2044,47 @@ pub(crate) async fn inner_elliptic(
20412044

20422045
let (center_u, _) = untype_point(center);
20432046

2047+
let major_axis = match (major_axis, major_radius) {
2048+
(Some(_), Some(_)) | (None, None) => {
2049+
return Err(KclError::new_type(KclErrorDetails::new(
2050+
"Provide either `majorAxis` or `majorRadius`.".to_string(),
2051+
vec![args.source_range],
2052+
)));
2053+
}
2054+
(Some(major_axis), None) => major_axis,
2055+
(None, Some(major_radius)) => [
2056+
major_radius.clone(),
2057+
TyF64 {
2058+
n: 0.0,
2059+
ty: major_radius.ty,
2060+
},
2061+
],
2062+
};
20442063
let start_angle = Angle::from_degrees(angle_start.to_degrees());
20452064
let end_angle = Angle::from_degrees(angle_end.to_degrees());
2065+
let major_axis_magnitude = (major_axis[0].to_length_units(from.units) * major_axis[0].to_length_units(from.units)
2066+
+ major_axis[1].to_length_units(from.units) * major_axis[1].to_length_units(from.units))
2067+
.sqrt();
20462068
let to = [
2047-
center_u[0] + major_radius.to_length_units(from.units) * libm::cos(end_angle.to_radians()),
2048-
center_u[1] + minor_radius.to_length_units(from.units) * libm::sin(end_angle.to_radians()),
2069+
major_axis_magnitude * libm::cos(end_angle.to_radians()),
2070+
minor_radius.to_length_units(from.units) * libm::sin(end_angle.to_radians()),
20492071
];
2072+
let major_axis_angle = libm::atan2(major_axis[1].n, major_axis[0].n);
20502073

2074+
let point = [
2075+
center_u[0] + to[0] * libm::cos(major_axis_angle) - to[1] * libm::sin(major_axis_angle),
2076+
center_u[1] + to[0] * libm::sin(major_axis_angle) + to[1] * libm::cos(major_axis_angle),
2077+
];
2078+
2079+
let axis = major_axis.map(|x| x.to_mm());
20512080
exec_state
20522081
.batch_modeling_cmd(
20532082
ModelingCmdMeta::from_args_id(&args, id),
20542083
ModelingCmd::from(mcmd::ExtendPath {
20552084
path: sketch.id.into(),
20562085
segment: PathSegment::Ellipse {
20572086
center: KPoint2d::from(untyped_point_to_mm(center_u, from.units)).map(LengthUnit),
2058-
major_radius: LengthUnit(major_radius.to_mm()),
2087+
major_axis: axis.map(LengthUnit).into(),
20592088
minor_radius: LengthUnit(minor_radius.to_mm()),
20602089
start_angle,
20612090
end_angle,
@@ -2067,11 +2096,11 @@ pub(crate) async fn inner_elliptic(
20672096
let current_path = Path::Ellipse {
20682097
ccw: start_angle < end_angle,
20692098
center: center_u,
2070-
major_radius: major_radius.to_mm(),
2099+
major_axis: axis,
20712100
minor_radius: minor_radius.to_mm(),
20722101
base: BasePath {
20732102
from: from.ignore_units(),
2074-
to,
2103+
to: point,
20752104
tag: tag.clone(),
20762105
units: sketch.units,
20772106
geo_meta: GeoMeta {

rust/kcl-lib/std/sketch.kcl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,12 @@ export fn ellipse(
362362
/// The center of the ellipse.
363363
@(snippetArray = ["0", "0"])
364364
center: Point2d,
365-
/// The major radius of the ellipse.
366-
majorRadius: number(Length),
367365
/// The minor radius of the ellipse.
368366
minorRadius: number(Length),
367+
/// The major radius of the ellipse. Equivalent to majorAxis = [majorRadius, 0].
368+
majorRadius?: number(Length),
369+
/// The major axis of the ellipse.
370+
majorAxis?: Point2d,
369371
/// Create a new tag which refers to this ellipse.
370372
tag?: tag,
371373
): Sketch {}
@@ -2228,12 +2230,14 @@ export fn elliptic(
22282230
/// Where along the ellptic should this segment end?
22292231
@(includeInSnippet = true)
22302232
angleEnd: number(Angle),
2231-
/// The major radius, a, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1.
2232-
@(includeInSnippet = true)
2233-
majorRadius: number(Length),
22342233
/// The minor radius, b, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1.
22352234
@(includeInSnippet = true)
22362235
minorRadius: number(Length),
2236+
/// The major radius, a, of the elliptic equation x^2 / a^2 + y^2 / b^2 = 1. Equivalent to majorAxis = [majorRadius, 0].
2237+
majorRadius?: number(Length),
2238+
/// The major axis of the elliptic.
2239+
@(includeInSnippet = true)
2240+
majorAxis?: Point2d,
22372241
/// Create a new tag which refers to this arc.
22382242
tag?: tag,
22392243
): Sketch {}

rust/kcl-lib/tests/elliptic_curve_inches_regression/artifact_commands.snap

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ description: Artifact commands elliptic_curve_inches_regression.kcl
9393
"x": 0.0,
9494
"y": 1545.7213433999998
9595
},
96-
"major_radius": 2302.732377,
96+
"major_axis": {
97+
"x": 2302.732377,
98+
"y": 0.0
99+
},
97100
"minor_radius": 426.8591158,
98101
"start_angle": {
99102
"unit": "degrees",

rust/kcl-lib/tests/elliptic_curve_inches_regression/artifact_graph_flowchart.snap.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ flowchart LR
33
subgraph path2 [Path]
44
2["Path<br>[322, 390, 0]"]
55
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
6-
3["Segment<br>[396, 560, 0]"]
6+
3["Segment<br>[396, 563, 0]"]
77
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
8-
4["Segment<br>[566, 678, 0]"]
8+
4["Segment<br>[569, 681, 0]"]
99
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
10-
5["Segment<br>[684, 793, 0]"]
10+
5["Segment<br>[687, 796, 0]"]
1111
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
12-
6["Segment<br>[799, 910, 0]"]
12+
6["Segment<br>[802, 913, 0]"]
1313
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
14-
7["Segment<br>[916, 1026, 0]"]
14+
7["Segment<br>[919, 1029, 0]"]
1515
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
16-
8["Segment<br>[1032, 1039, 0]"]
16+
8["Segment<br>[1035, 1042, 0]"]
1717
%% [ProgramBodyItem { index: 2 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
1818
9[Solid2d]
1919
end

0 commit comments

Comments
 (0)