Turn on units of measure (BREAKING CHANGE) (#6343)

* Turn on uom checks

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Convert all lengths to mm for engine calls

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-04-23 10:58:35 +12:00
committed by GitHub
parent 3d22f6cd66
commit b7385d5f25
339 changed files with 35471 additions and 17237 deletions

View File

@ -13,10 +13,16 @@ use kittycad_modeling_cmds::shared::PathSegment;
use schemars::JsonSchema;
use serde::Serialize;
use super::{args::TyF64, utils::untype_point};
use super::{
args::TyF64,
utils::{point_to_len_unit, point_to_mm, point_to_typed, untype_point, untyped_point_to_mm},
};
use crate::{
errors::{KclError, KclErrorDetails},
execution::{types::RuntimeType, BasePath, ExecState, GeoMeta, KclValue, Path, Sketch, SketchSurface},
execution::{
types::{RuntimeType, UnitLen},
BasePath, ExecState, GeoMeta, KclValue, Path, Sketch, SketchSurface,
},
parsing::ast::types::TagNode,
std::{
sketch::NEW_TAG_KW,
@ -41,15 +47,7 @@ pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
let sketch = inner_circle(
sketch_or_surface,
untype_point(center).0,
radius.n,
tag,
exec_state,
args,
)
.await?;
let sketch = inner_circle(sketch_or_surface, center, radius, tag, exec_state, args).await?;
Ok(KclValue::Sketch {
value: Box::new(sketch),
})
@ -57,8 +55,8 @@ pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
async fn inner_circle(
sketch_or_surface: SketchOrSurface,
center: [f64; 2],
radius: f64,
center: [TyF64; 2],
radius: TyF64,
tag: Option<TagNode>,
exec_state: &mut ExecState,
args: Args,
@ -67,17 +65,15 @@ async fn inner_circle(
SketchOrSurface::SketchSurface(surface) => surface,
SketchOrSurface::Sketch(s) => s.on,
};
let units = sketch_surface.units();
let sketch = crate::std::sketch::inner_start_profile_at(
[center[0] + radius, center[1]],
sketch_surface,
None,
exec_state,
args.clone(),
)
.await?;
let (center_u, ty) = untype_point(center.clone());
let units = ty.expect_length();
let from = [center_u[0] + radius.to_length_units(units), center_u[1]];
let from_t = [TyF64::new(from[0], ty.clone()), TyF64::new(from[1], ty)];
let sketch =
crate::std::sketch::inner_start_profile_at(from_t, sketch_surface, None, exec_state, args.clone()).await?;
let from = [center[0] + radius, center[1]];
let angle_start = Angle::zero();
let angle_end = Angle::turn();
@ -90,8 +86,8 @@ async fn inner_circle(
segment: PathSegment::Arc {
start: angle_start,
end: angle_end,
center: KPoint2d::from(center).map(LengthUnit),
radius: radius.into(),
center: KPoint2d::from(point_to_mm(center)).map(LengthUnit),
radius: LengthUnit(radius.to_mm()),
relative: false,
},
}),
@ -109,8 +105,8 @@ async fn inner_circle(
metadata: args.source_range.into(),
},
},
radius,
center,
radius: radius.to_length_units(units),
center: center_u,
ccw: angle_start < angle_end,
};
@ -135,16 +131,7 @@ pub async fn circle_three_point(exec_state: &mut ExecState, args: Args) -> Resul
let p3 = args.get_kw_arg_typed("p3", &RuntimeType::point2d(), exec_state)?;
let tag = args.get_kw_arg_opt("tag")?;
let sketch = inner_circle_three_point(
sketch_surface_or_group,
untype_point(p1).0,
untype_point(p2).0,
untype_point(p3).0,
tag,
exec_state,
args,
)
.await?;
let sketch = inner_circle_three_point(sketch_surface_or_group, p1, p2, p3, tag, exec_state, args).await?;
Ok(KclValue::Sketch {
value: Box::new(sketch),
})
@ -174,13 +161,20 @@ pub async fn circle_three_point(exec_state: &mut ExecState, args: Args) -> Resul
// path so it can be used for other features, otherwise it's lost.
async fn inner_circle_three_point(
sketch_surface_or_group: SketchOrSurface,
p1: [f64; 2],
p2: [f64; 2],
p3: [f64; 2],
p1: [TyF64; 2],
p2: [TyF64; 2],
p3: [TyF64; 2],
tag: Option<TagNode>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Sketch, KclError> {
let ty = p1[0].ty.clone();
let units = ty.expect_length();
let p1 = point_to_len_unit(p1, units);
let p2 = point_to_len_unit(p2, units);
let p3 = point_to_len_unit(p3, units);
let center = calculate_circle_center(p1, p2, p3);
// It can be the distance to any of the 3 points - they all lay on the circumference.
let radius = distance(center, p2);
@ -189,16 +183,15 @@ async fn inner_circle_three_point(
SketchOrSurface::SketchSurface(surface) => surface,
SketchOrSurface::Sketch(group) => group.on,
};
let sketch = crate::std::sketch::inner_start_profile_at(
[center[0] + radius, center[1]],
sketch_surface,
None,
exec_state,
args.clone(),
)
.await?;
let from = [center[0] + radius, center[1]];
let from = [
TyF64::new(center[0] + radius, ty.clone()),
TyF64::new(center[1], ty.clone()),
];
let sketch =
crate::std::sketch::inner_start_profile_at(from.clone(), sketch_surface, None, exec_state, args.clone())
.await?;
let angle_start = Angle::zero();
let angle_end = Angle::turn();
@ -211,8 +204,8 @@ async fn inner_circle_three_point(
segment: PathSegment::Arc {
start: angle_start,
end: angle_end,
center: KPoint2d::from(center).map(LengthUnit),
radius: radius.into(),
center: KPoint2d::from(untyped_point_to_mm(center, units)).map(LengthUnit),
radius: units.adjust_to(radius, UnitLen::Mm).0.into(),
relative: false,
},
}),
@ -221,10 +214,11 @@ async fn inner_circle_three_point(
let current_path = Path::CircleThreePoint {
base: BasePath {
from,
to: from,
// It's fine to untype here because we know `from` has units as its units.
from: untype_point(from.clone()).0,
to: untype_point(from).0,
tag: tag.clone(),
units: sketch.units,
units,
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
@ -270,7 +264,7 @@ pub async fn polygon(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
sketch_surface_or_group,
radius,
num_sides.n as u64,
untype_point(center).0,
center,
inscribed,
exec_state,
args,
@ -324,7 +318,7 @@ async fn inner_polygon(
sketch_surface_or_group: SketchOrSurface,
radius: TyF64,
num_sides: u64,
center: [f64; 2],
center: [TyF64; 2],
inscribed: Option<bool>,
exec_state: &mut ExecState,
args: Args,
@ -343,9 +337,9 @@ async fn inner_polygon(
}));
}
let sketch_surface = match sketch_surface_or_group {
SketchOrSurface::SketchSurface(surface) => surface,
SketchOrSurface::Sketch(group) => group.on,
let (sketch_surface, units) = match sketch_surface_or_group {
SketchOrSurface::SketchSurface(surface) => (surface, radius.ty.expect_length()),
SketchOrSurface::Sketch(group) => (group.on, group.units),
};
let half_angle = std::f64::consts::PI / num_sides as f64;
@ -360,18 +354,26 @@ async fn inner_polygon(
let angle_step = std::f64::consts::TAU / num_sides as f64;
let center_u = point_to_len_unit(center, units);
let vertices: Vec<[f64; 2]> = (0..num_sides)
.map(|i| {
let angle = angle_step * i as f64;
[
center[0] + radius_to_vertices * angle.cos(),
center[1] + radius_to_vertices * angle.sin(),
center_u[0] + radius_to_vertices * angle.cos(),
center_u[1] + radius_to_vertices * angle.sin(),
]
})
.collect();
let mut sketch =
crate::std::sketch::inner_start_profile_at(vertices[0], sketch_surface, None, exec_state, args.clone()).await?;
let mut sketch = crate::std::sketch::inner_start_profile_at(
point_to_typed(vertices[0], units),
sketch_surface,
None,
exec_state,
args.clone(),
)
.await?;
// Draw all the lines with unique IDs and modified tags
for vertex in vertices.iter().skip(1) {
@ -383,7 +385,9 @@ async fn inner_polygon(
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Line {
end: KPoint2d::from(*vertex).with_z(0.0).map(LengthUnit),
end: KPoint2d::from(untyped_point_to_mm(*vertex, units))
.with_z(0.0)
.map(LengthUnit),
relative: false,
},
}),
@ -392,7 +396,7 @@ async fn inner_polygon(
let current_path = Path::ToPoint {
base: BasePath {
from: from.into(),
from: from.ignore_units(),
to: *vertex,
tag: None,
units: sketch.units,
@ -415,7 +419,9 @@ async fn inner_polygon(
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Line {
end: KPoint2d::from(vertices[0]).with_z(0.0).map(LengthUnit),
end: KPoint2d::from(untyped_point_to_mm(vertices[0], units))
.with_z(0.0)
.map(LengthUnit),
relative: false,
},
}),
@ -424,7 +430,7 @@ async fn inner_polygon(
let current_path = Path::ToPoint {
base: BasePath {
from: from.into(),
from: from.ignore_units(),
to: vertices[0],
tag: None,
units: sketch.units,