Generalise and simplify offsetPlane (#5429)

* Generalise and simplify offsetPlane

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

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Nick Cameron
2025-02-20 15:55:29 +13:00
committed by GitHub
parent 695c432d1e
commit f35cd3ef26
6 changed files with 151 additions and 102 deletions

View File

@ -9,7 +9,7 @@ Offset a plane by a distance along its normal.
For example, if you offset the 'XZ' plane by 10, the new plane will be parallel to the 'XZ' plane and 10 units away from it.
```js
offsetPlane(std_plane: StandardPlane, offset: number) -> Plane
offsetPlane(plane: PlaneData, offset: number) -> Plane
```
@ -17,7 +17,7 @@ offsetPlane(std_plane: StandardPlane, offset: number) -> Plane
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `std_plane` | [`StandardPlane`](/docs/kcl/types/StandardPlane) | Which standard plane (e.g. XY) should this new plane be created from? | Yes |
| `plane` | [`PlaneData`](/docs/kcl/types/PlaneData) | The plane (e.g. 'XY') which this new plane is created from. | Yes |
| `offset` | `number` | Distance from the standard plane this new plane will be created at. | Yes |
### Returns

View File

@ -147531,12 +147531,12 @@
"keywordArguments": true,
"args": [
{
"name": "std_plane",
"type": "StandardPlane",
"name": "plane",
"type": "PlaneData",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "StandardPlane",
"description": "One of the standard planes.",
"title": "PlaneData",
"description": "Orientation data that can be used to construct a plane, not a plane in itself.",
"oneOf": [
{
"description": "The XY plane.",
@ -147579,12 +147579,89 @@
"enum": [
"-YZ"
]
},
{
"description": "A defined plane.",
"type": "object",
"required": [
"plane"
],
"properties": {
"plane": {
"type": "object",
"required": [
"origin",
"xAxis",
"yAxis",
"zAxis"
],
"properties": {
"origin": {
"description": "Origin of the plane.",
"allOf": [
{
"$ref": "#/components/schemas/Point3d"
}
]
},
"xAxis": {
"description": "What should the planes X axis be?",
"allOf": [
{
"$ref": "#/components/schemas/Point3d"
}
]
},
"yAxis": {
"description": "What should the planes Y axis be?",
"allOf": [
{
"$ref": "#/components/schemas/Point3d"
}
]
},
"zAxis": {
"description": "The z-axis (normal).",
"allOf": [
{
"$ref": "#/components/schemas/Point3d"
}
]
}
}
}
},
"additionalProperties": false
}
]
],
"definitions": {
"Point3d": {
"type": "object",
"required": [
"x",
"y",
"z"
],
"properties": {
"x": {
"type": "number",
"format": "double"
},
"y": {
"type": "number",
"format": "double"
},
"z": {
"type": "number",
"format": "double"
}
}
}
}
},
"required": true,
"includeInSnippet": true,
"description": "Which standard plane (e.g. XY) should this new plane be created from?",
"description": "The plane (e.g. 'XY') which this new plane is created from.",
"labelRequired": false
},
{
@ -147594,7 +147671,31 @@
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
"format": "double",
"definitions": {
"Point3d": {
"type": "object",
"required": [
"x",
"y",
"z"
],
"properties": {
"x": {
"type": "number",
"format": "double"
},
"y": {
"type": "number",
"format": "double"
},
"z": {
"type": "number",
"format": "double"
}
}
}
}
},
"required": true,
"includeInSnippet": true,

View File

@ -1,3 +1,5 @@
use std::ops::{Add, AddAssign, Mul};
use anyhow::Result;
use indexmap::IndexMap;
use kittycad_modeling_cmds as kcmc;
@ -353,11 +355,6 @@ impl Plane {
}
}
/// The standard planes are XY, YZ and XZ (in both positive and negative)
pub fn is_standard(&self) -> bool {
!self.is_custom()
}
/// The standard planes are XY, YZ and XZ (in both positive and negative)
/// Custom planes are any other plane that the user might specify.
pub fn is_custom(&self) -> bool {
@ -696,6 +693,36 @@ impl From<Point3d> for kittycad_modeling_cmds::shared::Point3d<LengthUnit> {
}
}
impl Add for Point3d {
type Output = Point3d;
fn add(self, rhs: Self) -> Self::Output {
Point3d {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl AddAssign for Point3d {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs
}
}
impl Mul<f64> for Point3d {
type Output = Point3d;
fn mul(self, rhs: f64) -> Self::Output {
Point3d {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
/// A base path.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]

View File

@ -874,21 +874,6 @@ impl<'a> FromKclValue<'a> for crate::std::polar::PolarCoordsData {
}
}
impl<'a> FromKclValue<'a> for crate::std::planes::StandardPlane {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let s = arg.as_str()?;
match s {
"XY" | "xy" => Some(Self::XY),
"-XY" | "-xy" => Some(Self::NegXY),
"XZ" | "xz" => Some(Self::XZ),
"-XZ" | "-xz" => Some(Self::NegXZ),
"YZ" | "yz" => Some(Self::YZ),
"-YZ" | "-yz" => Some(Self::NegYZ),
_ => None,
}
}
}
impl<'a> FromKclValue<'a> for crate::execution::Plane {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.as_plane().cloned()

View File

@ -3,57 +3,19 @@
use derive_docs::stdlib;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Color, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
errors::KclError,
execution::{ExecState, KclValue, Plane, PlaneType},
std::{sketch::PlaneData, Args},
std::Args,
};
/// One of the standard planes.
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub enum StandardPlane {
/// The XY plane.
#[serde(rename = "XY", alias = "xy")]
XY,
/// The opposite side of the XY plane.
#[serde(rename = "-XY", alias = "-xy")]
NegXY,
/// The XZ plane.
#[serde(rename = "XZ", alias = "xz")]
XZ,
/// The opposite side of the XZ plane.
#[serde(rename = "-XZ", alias = "-xz")]
NegXZ,
/// The YZ plane.
#[serde(rename = "YZ", alias = "yz")]
YZ,
/// The opposite side of the YZ plane.
#[serde(rename = "-YZ", alias = "-yz")]
NegYZ,
}
impl From<StandardPlane> for PlaneData {
fn from(value: StandardPlane) -> Self {
match value {
StandardPlane::XY => PlaneData::XY,
StandardPlane::NegXY => PlaneData::NegXY,
StandardPlane::XZ => PlaneData::XZ,
StandardPlane::NegXZ => PlaneData::NegXZ,
StandardPlane::YZ => PlaneData::YZ,
StandardPlane::NegYZ => PlaneData::NegYZ,
}
}
}
use super::sketch::PlaneData;
/// Offset a plane by a distance along its normal.
pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
// let (std_plane, offset): (StandardPlane, f64) = args.get_data_and_float()?;
let std_plane = args.get_unlabeled_kw_arg("stdPlane")?;
let std_plane = args.get_unlabeled_kw_arg("plane")?;
let offset = args.get_kw_arg("offset")?;
let plane = inner_offset_plane(std_plane, offset, exec_state).await?;
make_offset_plane_in_engine(&plane, exec_state, &args).await?;
@ -148,43 +110,17 @@ pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclV
keywords = true,
unlabeled_first = true,
args = {
std_plane = { docs = "Which standard plane (e.g. XY) should this new plane be created from?" },
plane = { docs = "The plane (e.g. 'XY') which this new plane is created from." },
offset = { docs = "Distance from the standard plane this new plane will be created at." },
}
}]
async fn inner_offset_plane(
std_plane: StandardPlane,
offset: f64,
exec_state: &mut ExecState,
) -> Result<Plane, KclError> {
// Convert to the plane type.
let plane_data: PlaneData = std_plane.into();
// Convert to a plane.
let mut plane = Plane::from_plane_data(plane_data, exec_state);
// Though offset planes are derived from standard planes, they are not
async fn inner_offset_plane(plane: PlaneData, offset: f64, exec_state: &mut ExecState) -> Result<Plane, KclError> {
let mut plane = Plane::from_plane_data(plane, exec_state);
// Though offset planes might be derived from standard planes, they are not
// standard planes themselves.
plane.value = PlaneType::Custom;
match std_plane {
StandardPlane::XY => {
plane.origin.z += offset;
}
StandardPlane::XZ => {
plane.origin.y -= offset;
}
StandardPlane::YZ => {
plane.origin.x += offset;
}
StandardPlane::NegXY => {
plane.origin.z -= offset;
}
StandardPlane::NegXZ => {
plane.origin.y += offset;
}
StandardPlane::NegYZ => {
plane.origin.x -= offset;
}
}
plane.origin += plane.z_axis * offset;
Ok(plane)
}

View File

@ -1296,7 +1296,7 @@ pub(crate) async fn inner_start_profile_at(
args.flush_batch_for_solid_set(exec_state, face.solid.clone().into())
.await?;
}
SketchSurface::Plane(plane) if !plane.is_standard() => {
SketchSurface::Plane(plane) if plane.is_custom() => {
// Hide whatever plane we are sketching on.
// This is especially helpful for offset planes, which would be visible otherwise.
args.batch_end_cmd(