Compare commits
13 Commits
v0.56.1
...
mike/engin
Author | SHA1 | Date | |
---|---|---|---|
5bea90ad9a | |||
d23ddc19eb | |||
e65358f635 | |||
0a1201e680 | |||
9db013e672 | |||
0196d72a2d | |||
e6af4078bd | |||
2b233dc705 | |||
b11e8af9c7 | |||
c017847d7b | |||
9635eea8c1 | |||
5a2df642b1 | |||
621e41080e |
@ -1,3 +1,4 @@
|
|||||||
src/wasm-lib/*
|
src/wasm-lib/*
|
||||||
|
src/lib/engine-utils/engine.js
|
||||||
*.typegen.ts
|
*.typegen.ts
|
||||||
packages/codemirror-lsp-client/dist/*
|
packages/codemirror-lsp-client/dist/*
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -66,3 +66,7 @@ venv
|
|||||||
|
|
||||||
# electron
|
# electron
|
||||||
out/
|
out/
|
||||||
|
|
||||||
|
# engine wasm utils
|
||||||
|
src/lib/engine-utils/engine.wasm
|
||||||
|
src/lib/engine-utils/engine.js
|
||||||
|
@ -110,6 +110,7 @@ const initialise = async () => {
|
|||||||
const fullUrl = wasmUrl()
|
const fullUrl = wasmUrl()
|
||||||
const input = await fetch(fullUrl)
|
const input = await fetch(fullUrl)
|
||||||
const buffer = await input.arrayBuffer()
|
const buffer = await input.arrayBuffer()
|
||||||
|
|
||||||
return await init(buffer)
|
return await init(buffer)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error initialising WASM', e)
|
console.log('Error initialising WASM', e)
|
||||||
|
31
src/lib/engineUtils.ts
Normal file
31
src/lib/engineUtils.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import EngineUtils from '@engine-utils'
|
||||||
|
|
||||||
|
type KCEngineUtilsEvaluatePath = {
|
||||||
|
(sketch: string, t: number): string
|
||||||
|
}
|
||||||
|
let kcEngineUtilsEvaluatePath: KCEngineUtilsEvaluatePath
|
||||||
|
|
||||||
|
export async function init() {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
EngineUtils().then((module) => {
|
||||||
|
kcEngineUtilsEvaluatePath = module.cwrap(
|
||||||
|
'kcEngineUtilsEvaluatePath',
|
||||||
|
'string',
|
||||||
|
['string', 'number']
|
||||||
|
)
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTruePathEndPos(sketch: string) {
|
||||||
|
if (!kcEngineUtilsEvaluatePath) {
|
||||||
|
await init()
|
||||||
|
}
|
||||||
|
|
||||||
|
return kcEngineUtilsEvaluatePath(sketch, 1.0)
|
||||||
|
}
|
12
src/wasm-lib/Cargo.lock
generated
12
src/wasm-lib/Cargo.lock
generated
@ -121,9 +121,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.89"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
]
|
]
|
||||||
@ -1684,9 +1684,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad-modeling-cmds"
|
name = "kittycad-modeling-cmds"
|
||||||
version = "0.2.68"
|
version = "0.2.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e3aedfcc1d8ea9995ec3eb78a6743c585c9380475c48701797f107489b696aa"
|
checksum = "b135696d07a4fab928e5abace4dd05f4976eafab5d73e5747a85dc5a684b936c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -3005,9 +3005,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.128"
|
version = "1.0.132"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.6.0",
|
"indexmap 2.6.0",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
@ -72,7 +72,7 @@ members = [
|
|||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
http = "1"
|
http = "1"
|
||||||
kittycad = { version = "0.3.23", default-features = false, features = ["js", "requests"] }
|
kittycad = { version = "0.3.23", default-features = false, features = ["js", "requests"] }
|
||||||
kittycad-modeling-cmds = { version = "0.2.68", features = ["websocket"] }
|
kittycad-modeling-cmds = { version = "0.2.70", features = ["websocket"] }
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "executor"
|
name = "executor"
|
||||||
|
@ -68,7 +68,7 @@ tokio-tungstenite = { version = "0.24.0", features = ["rustls-tls-native-roots"]
|
|||||||
tower-lsp = { version = "0.20.0", features = ["proposed"] }
|
tower-lsp = { version = "0.20.0", features = ["proposed"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["engine"]
|
default = ["engine"] # add wasm-engine-utils here when we're ready
|
||||||
cli = ["dep:clap"]
|
cli = ["dep:clap"]
|
||||||
# For the lsp server, when run with stdout for rpc we want to disable println.
|
# For the lsp server, when run with stdout for rpc we want to disable println.
|
||||||
# This is used for editor extensions that use the lsp server.
|
# This is used for editor extensions that use the lsp server.
|
||||||
@ -77,6 +77,10 @@ engine = []
|
|||||||
pyo3 = ["dep:pyo3"]
|
pyo3 = ["dep:pyo3"]
|
||||||
# Helper functions also used in benchmarks.
|
# Helper functions also used in benchmarks.
|
||||||
lsp-test-util = []
|
lsp-test-util = []
|
||||||
|
#if enabled, kcl will link directly against a wasm build of the engine utils lib to save latency
|
||||||
|
wasm-engine-utils = []
|
||||||
|
#if enabled, kcl will link directly against a native build of the engine utils lib to save latency (not yet functional)
|
||||||
|
native-engine-utils = []
|
||||||
|
|
||||||
tabled = ["dep:tabled"]
|
tabled = ["dep:tabled"]
|
||||||
|
|
||||||
|
57
src/wasm-lib/kcl/src/engine/engine_utils.rs
Normal file
57
src/wasm-lib/kcl/src/engine/engine_utils.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//! Functions for calling into the engine-utils library (a set of C++ utilities containing various logic for client-side CAD processing)
|
||||||
|
//! Note that this binary may not be available to all builds of kcl, so fallbacks that call the engine API should be implemented
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
std::Args,
|
||||||
|
};
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::ffi::{CString, CStr};
|
||||||
|
use kittycad_modeling_cmds::{length_unit::LengthUnit, shared::Point3d};
|
||||||
|
|
||||||
|
mod cpp {
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn kcEngineUtilsEvaluatePath(sketch: *const c_char, t: f64) -> *const c_char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn is_available() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_true_path_end_pos(sketch: String, args: &Args) -> Result<Point3d<LengthUnit>, KclError> {
|
||||||
|
let c_string = CString::new(sketch).map_err(|e| {
|
||||||
|
KclError::Internal(KclErrorDetails {
|
||||||
|
message: format!("{:?}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
let arg = c_string.into_raw();
|
||||||
|
let result_string: String;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let result = cpp::kcEngineUtilsEvaluatePath(arg, 1.0);
|
||||||
|
let result_cstr = CStr::from_ptr(result);
|
||||||
|
let str_slice: &str = result_cstr.to_str().map_err(|e| {
|
||||||
|
KclError::Internal(KclErrorDetails {
|
||||||
|
message: format!("{:?}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
let str_buf: String = str_slice.to_owned();
|
||||||
|
result_string = str_buf.clone();
|
||||||
|
let _ = CString::from_raw(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
let point: Point3d<f64> = serde_json::from_str(&result_string).map_err(|e| {
|
||||||
|
KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Failed to path position from json: {}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Point3d::<f64>::from(point).map(LengthUnit))
|
||||||
|
}
|
35
src/wasm-lib/kcl/src/engine/engine_utils_api.rs
Normal file
35
src/wasm-lib/kcl/src/engine/engine_utils_api.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//! Functions for calling into the engine-utils library (a set of C++ utilities containing various logic for client-side CAD processing)
|
||||||
|
//! Note that this binary may not be available to all builds of kcl, so fallbacks that call the engine API should be implemented
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
std::Args,
|
||||||
|
};
|
||||||
|
use crate::engine::kcmc::{each_cmd as mcmd, ModelingCmd};
|
||||||
|
use anyhow::Result;
|
||||||
|
use kittycad_modeling_cmds::{length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Point3d, websocket::OkWebSocketResponseData};
|
||||||
|
|
||||||
|
pub fn is_available() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_true_path_end_pos(sketch: String, args: &Args) -> Result<Point3d<LengthUnit>, KclError> {
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
|
let resp = args.send_modeling_cmd(id, ModelingCmd::from(mcmd::EngineUtilEvaluatePath {
|
||||||
|
path_json: sketch,
|
||||||
|
t: 1.0,
|
||||||
|
})).await?;
|
||||||
|
|
||||||
|
let OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response: OkModelingCmdResponse::EngineUtilEvaluatePath(point),
|
||||||
|
} = &resp
|
||||||
|
else {
|
||||||
|
return Err(KclError::Engine(KclErrorDetails {
|
||||||
|
message: format!("mcmd::EngineUtilEvaluatePath response was not as expected: {:?}", resp),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(point.pos)
|
||||||
|
}
|
56
src/wasm-lib/kcl/src/engine/engine_utils_wasm.rs
Normal file
56
src/wasm-lib/kcl/src/engine/engine_utils_wasm.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//! Functions for calling into the engine-utils library (a set of C++ utilities containing various logic for client-side CAD processing)
|
||||||
|
//! Note that this binary may not be available to all builds of kcl, so fallbacks that call the engine API should be implemented
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
errors::{KclError, KclErrorDetails},
|
||||||
|
std::Args,
|
||||||
|
};
|
||||||
|
use anyhow::Result;
|
||||||
|
use kittycad_modeling_cmds::{length_unit::LengthUnit, shared::Point3d};
|
||||||
|
mod cpp {
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "/../../lib/engineUtils.ts")]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(js_name = getTruePathEndPos, catch)]
|
||||||
|
pub fn get_true_path_end_pos(sketch: String) -> Result<js_sys::Promise, js_sys::Error>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_available() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn call_cpp<F>(args: &Args, f: F) -> Result<String, KclError>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Result<js_sys::Promise, js_sys::Error>,
|
||||||
|
{
|
||||||
|
let promise = f().map_err(|e| {
|
||||||
|
KclError::Internal(KclErrorDetails {
|
||||||
|
message: format!("{:?}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let result = crate::wasm::JsFuture::from(promise).await.map_err(|e| {
|
||||||
|
KclError::Internal(KclErrorDetails {
|
||||||
|
message: format!("{:?}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(result.as_string().unwrap_or_default())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_true_path_end_pos(sketch: String, args: &Args) -> Result<Point3d<LengthUnit>, KclError> {
|
||||||
|
let result_str = call_cpp(args, || cpp::get_true_path_end_pos(sketch.into())).await?;
|
||||||
|
|
||||||
|
let point: Point3d<f64> = serde_json::from_str(&result_str).map_err(|e| {
|
||||||
|
KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Failed to path position from json: {}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Point3d::<f64>::from(point).map(LengthUnit))
|
||||||
|
}
|
@ -8,6 +8,17 @@ pub mod conn_mock;
|
|||||||
#[cfg(feature = "engine")]
|
#[cfg(feature = "engine")]
|
||||||
pub mod conn_wasm;
|
pub mod conn_wasm;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
#[cfg(feature = "native-engine-utils")]
|
||||||
|
pub mod engine_utils;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[cfg(feature = "wasm-engine-utils")]
|
||||||
|
pub mod engine_utils_wasm;
|
||||||
|
|
||||||
|
#[cfg(feature = "engine")]
|
||||||
|
#[cfg(any(not(target_arch = "wasm32"), all(not(feature = "native-engine-utils"), not(feature = "wasm-engine-utils"))))]
|
||||||
|
pub mod engine_utils_api;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
|
@ -1601,6 +1601,19 @@ pub enum Path {
|
|||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
base: BasePath,
|
base: BasePath,
|
||||||
},
|
},
|
||||||
|
/// An arc (only used for engine-utils arg serialization for now)
|
||||||
|
Arc {
|
||||||
|
#[serde(flatten)]
|
||||||
|
base: BasePath,
|
||||||
|
/// angle range
|
||||||
|
#[ts(type = "[number, number]")]
|
||||||
|
angle_range: [f64; 2],
|
||||||
|
/// center
|
||||||
|
#[ts(type = "[number, number]")]
|
||||||
|
center: [f64; 2],
|
||||||
|
/// the arc's radius
|
||||||
|
radius: f64,
|
||||||
|
},
|
||||||
/// A arc that is tangential to the last path segment that goes to a point
|
/// A arc that is tangential to the last path segment that goes to a point
|
||||||
TangentialArcTo {
|
TangentialArcTo {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@ -1620,6 +1633,10 @@ pub enum Path {
|
|||||||
center: [f64; 2],
|
center: [f64; 2],
|
||||||
/// arc's direction
|
/// arc's direction
|
||||||
ccw: bool,
|
ccw: bool,
|
||||||
|
/// the arc's radius
|
||||||
|
radius: f64,
|
||||||
|
/// the arc's angle offset
|
||||||
|
offset: f64,
|
||||||
},
|
},
|
||||||
// TODO: consolidate segment enums, remove Circle. https://github.com/KittyCAD/modeling-app/issues/3940
|
// TODO: consolidate segment enums, remove Circle. https://github.com/KittyCAD/modeling-app/issues/3940
|
||||||
/// a complete arc
|
/// a complete arc
|
||||||
@ -1668,6 +1685,7 @@ impl Path {
|
|||||||
Path::TangentialArcTo { base, .. } => base.geo_meta.id,
|
Path::TangentialArcTo { base, .. } => base.geo_meta.id,
|
||||||
Path::TangentialArc { base, .. } => base.geo_meta.id,
|
Path::TangentialArc { base, .. } => base.geo_meta.id,
|
||||||
Path::Circle { base, .. } => base.geo_meta.id,
|
Path::Circle { base, .. } => base.geo_meta.id,
|
||||||
|
Path::Arc { base, .. } => base.geo_meta.id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1680,6 +1698,7 @@ impl Path {
|
|||||||
Path::TangentialArcTo { base, .. } => base.tag.clone(),
|
Path::TangentialArcTo { base, .. } => base.tag.clone(),
|
||||||
Path::TangentialArc { base, .. } => base.tag.clone(),
|
Path::TangentialArc { base, .. } => base.tag.clone(),
|
||||||
Path::Circle { base, .. } => base.tag.clone(),
|
Path::Circle { base, .. } => base.tag.clone(),
|
||||||
|
Path::Arc { base, .. } => base.tag.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1692,6 +1711,7 @@ impl Path {
|
|||||||
Path::TangentialArcTo { base, .. } => base,
|
Path::TangentialArcTo { base, .. } => base,
|
||||||
Path::TangentialArc { base, .. } => base,
|
Path::TangentialArc { base, .. } => base,
|
||||||
Path::Circle { base, .. } => base,
|
Path::Circle { base, .. } => base,
|
||||||
|
Path::Arc { base, .. } => base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1704,6 +1724,7 @@ impl Path {
|
|||||||
Path::TangentialArcTo { base, .. } => Some(base),
|
Path::TangentialArcTo { base, .. } => Some(base),
|
||||||
Path::TangentialArc { base, .. } => Some(base),
|
Path::TangentialArc { base, .. } => Some(base),
|
||||||
Path::Circle { base, .. } => Some(base),
|
Path::Circle { base, .. } => Some(base),
|
||||||
|
Path::Arc { base, .. } => Some(base),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,6 +256,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
});
|
});
|
||||||
Some(extrude_surface)
|
Some(extrude_surface)
|
||||||
}
|
}
|
||||||
|
Path::Arc { .. } => todo!(),
|
||||||
}
|
}
|
||||||
} else if args.ctx.is_mock() {
|
} else if args.ctx.is_mock() {
|
||||||
// Only pre-populate the extrude surface if we are in mock mode.
|
// Only pre-populate the extrude surface if we are in mock mode.
|
||||||
|
@ -6,7 +6,7 @@ use anyhow::Result;
|
|||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
|
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
|
||||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds::{self as kcmc, units};
|
||||||
use kittycad_modeling_cmds::shared::PathSegment;
|
use kittycad_modeling_cmds::shared::PathSegment;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
@ -21,13 +21,26 @@ use crate::{
|
|||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
utils::{
|
utils::{
|
||||||
arc_angles, arc_center_and_end, get_tangent_point_from_previous_arc, get_tangential_arc_to_info,
|
arc_angles, arc_center_and_end, arc_start_center_and_end, get_tangent_point_from_previous_arc,
|
||||||
get_x_component, get_y_component, intersection_with_parallel_line, TangentialArcInfoInput,
|
get_tangential_arc_to_info, get_x_component, get_y_component, intersection_with_parallel_line,
|
||||||
|
TangentialArcInfoInput,
|
||||||
},
|
},
|
||||||
Args,
|
Args,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
#[cfg(feature = "native-engine-utils")]
|
||||||
|
use crate::engine::engine_utils;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
#[cfg(feature = "wasm-engine-utils")]
|
||||||
|
use crate::engine::engine_utils_wasm as engine_utils;
|
||||||
|
|
||||||
|
#[cfg(feature = "engine")]
|
||||||
|
#[cfg(any(not(target_arch = "wasm32"), all(not(feature = "native-engine-utils"), not(feature = "wasm-engine-utils"))))]
|
||||||
|
use crate::engine::engine_utils_api as engine_utils;
|
||||||
|
|
||||||
/// A tag for a face.
|
/// A tag for a face.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
@ -1495,7 +1508,45 @@ pub(crate) async fn inner_arc(
|
|||||||
} => {
|
} => {
|
||||||
let a_start = Angle::from_degrees(*angle_start);
|
let a_start = Angle::from_degrees(*angle_start);
|
||||||
let a_end = Angle::from_degrees(*angle_end);
|
let a_end = Angle::from_degrees(*angle_end);
|
||||||
let (center, end) = arc_center_and_end(from, a_start, a_end, *radius);
|
|
||||||
|
let (_, center, mut end) = arc_start_center_and_end(from, a_start, a_end, *radius);
|
||||||
|
|
||||||
|
if engine_utils::is_available() {
|
||||||
|
let mut path_plus_arc = sketch.clone();
|
||||||
|
let to = [0.0, 0.0];
|
||||||
|
let arc = Path::Arc {
|
||||||
|
base: BasePath {
|
||||||
|
from: from.into(),
|
||||||
|
to,
|
||||||
|
tag: None,
|
||||||
|
geo_meta: GeoMeta {
|
||||||
|
id: uuid::Uuid::new_v4(),
|
||||||
|
metadata: args.source_range.into(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
angle_range: [*angle_start, *angle_end],
|
||||||
|
center: [center.x, center.y],
|
||||||
|
radius: *radius,
|
||||||
|
};
|
||||||
|
|
||||||
|
path_plus_arc.value.push(arc);
|
||||||
|
|
||||||
|
let sketch_json_value = serde_json::to_string(&path_plus_arc).map_err(|e| {
|
||||||
|
KclError::Type(KclErrorDetails {
|
||||||
|
message: format!("Failed to convert sketch to json: {}", e),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
//???? someone double check me on this unit conversion - mike
|
||||||
|
let units = units::UnitLength::Millimeters;
|
||||||
|
let result_end = engine_utils::get_true_path_end_pos(sketch_json_value, &args).await?;
|
||||||
|
end = Point2d {
|
||||||
|
x: result_end.x.to_millimeters(units),
|
||||||
|
y: result_end.y.to_millimeters(units),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
(center, a_start, a_end, *radius, end)
|
(center, a_start, a_end, *radius, end)
|
||||||
}
|
}
|
||||||
ArcData::CenterToRadius { center, to, radius } => {
|
ArcData::CenterToRadius { center, to, radius } => {
|
||||||
@ -1616,7 +1667,7 @@ async fn inner_tangential_arc(
|
|||||||
|
|
||||||
let id = exec_state.id_generator.next_uuid();
|
let id = exec_state.id_generator.next_uuid();
|
||||||
|
|
||||||
let (center, to, ccw) = match data {
|
let (center, to, ccw, radius, offset) = match data {
|
||||||
TangentialArcData::RadiusAndOffset { radius, offset } => {
|
TangentialArcData::RadiusAndOffset { radius, offset } => {
|
||||||
// KCL stdlib types use degrees.
|
// KCL stdlib types use degrees.
|
||||||
let offset = Angle::from_degrees(offset);
|
let offset = Angle::from_degrees(offset);
|
||||||
@ -1654,13 +1705,15 @@ async fn inner_tangential_arc(
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(center, to.into(), ccw)
|
(center, to.into(), ccw, radius, offset)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let current_path = Path::TangentialArc {
|
let current_path = Path::TangentialArc {
|
||||||
ccw,
|
ccw,
|
||||||
center: center.into(),
|
center: center.into(),
|
||||||
|
radius,
|
||||||
|
offset: offset.to_degrees(),
|
||||||
base: BasePath {
|
base: BasePath {
|
||||||
from: from.into(),
|
from: from.into(),
|
||||||
to,
|
to,
|
||||||
|
@ -221,6 +221,33 @@ pub fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, r
|
|||||||
(center, end)
|
(center, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn arc_start_center_and_end(
|
||||||
|
from: Point2d,
|
||||||
|
start_angle: Angle,
|
||||||
|
end_angle: Angle,
|
||||||
|
radius: f64,
|
||||||
|
) -> (Point2d, Point2d, Point2d) {
|
||||||
|
let start_angle = start_angle.to_radians();
|
||||||
|
let end_angle = end_angle.to_radians();
|
||||||
|
|
||||||
|
let center = Point2d {
|
||||||
|
x: -1.0 * (radius * start_angle.cos() - from.x),
|
||||||
|
y: -1.0 * (radius * start_angle.sin() - from.y),
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = Point2d {
|
||||||
|
x: center.x + radius * start_angle.cos(),
|
||||||
|
y: center.y + radius * start_angle.sin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let end = Point2d {
|
||||||
|
x: center.x + radius * end_angle.cos(),
|
||||||
|
y: center.y + radius * end_angle.sin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(start, center, end)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn arc_angles(
|
pub fn arc_angles(
|
||||||
from: Point2d,
|
from: Point2d,
|
||||||
to: Point2d,
|
to: Point2d,
|
||||||
|
@ -58,6 +58,7 @@ const config = defineConfig({
|
|||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@kittycad/codemirror-lsp-client': '/packages/codemirror-lsp-client/src',
|
'@kittycad/codemirror-lsp-client': '/packages/codemirror-lsp-client/src',
|
||||||
|
'@engine-utils': '/src/lib/engine-utils/engine.js',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [react(), viteTsconfigPaths(), eslint(), version(), lezer()],
|
plugins: [react(), viteTsconfigPaths(), eslint(), version(), lezer()],
|
||||||
|
Reference in New Issue
Block a user