Merge branch 'main' into cut-release-v0.25.1

This commit is contained in:
Frank Noirot
2024-09-06 18:15:29 -04:00
committed by GitHub
6 changed files with 184 additions and 61 deletions

View File

@ -364,45 +364,48 @@ test.describe('Testing settings', () => {
async ({ browser: _ }, testInfo) => {
const { electronApp, page } = await setupElectron({
testInfo,
folderSetupFn: async () => {},
folderSetupFn: async (dir) => {
const bracketDir = join(dir, 'project-000')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('cube.kcl'),
join(bracketDir, 'main.kcl')
)
await fsp.copyFile(
executorInputPath('cylinder.kcl'),
join(bracketDir, '2.kcl')
)
},
})
const kclCube = await fsp.readFile(executorInputPath('cube.kcl'), 'utf-8')
const kclCylinder = await fsp.readFile(
executorInputPath('cylinder.kcl'),
'utf8'
)
const {
openKclCodePanel,
openFilePanel,
createAndSelectProject,
pasteCodeInEditor,
createNewFileAndSelect,
waitForPageLoad,
selectFile,
editorTextMatches,
} = await getUtils(page, test)
await page.setViewportSize({ width: 1200, height: 500 })
page.on('console', console.log)
await test.step('Precondition: No projects exist', async () => {
await test.step('Precondition: Open to second project file', async () => {
await expect(page.getByTestId('home-section')).toBeVisible()
const projectLinksPre = page.getByTestId('project-link')
await expect(projectLinksPre).toHaveCount(0)
await page.getByText('project-000').click()
await waitForPageLoad()
await openKclCodePanel()
await openFilePanel()
await editorTextMatches(kclCube)
await selectFile('2.kcl')
await editorTextMatches(kclCylinder)
})
await createAndSelectProject('project-000')
await openKclCodePanel()
const kclCube = await fsp.readFile(
'src/wasm-lib/tests/executor/inputs/cube.kcl',
'utf-8'
)
await pasteCodeInEditor(kclCube)
await openFilePanel()
await createNewFileAndSelect('2.kcl')
const kclCylinder = await fsp.readFile(
'src/wasm-lib/tests/executor/inputs/cylinder.kcl',
'utf-8'
)
await pasteCodeInEditor(kclCylinder)
const settingsOpenButton = page.getByRole('link', {
name: 'settings Settings',
})
@ -410,6 +413,9 @@ test.describe('Testing settings', () => {
await test.step('Open and close settings', async () => {
await settingsOpenButton.click()
await expect(
page.getByRole('heading', { name: 'Settings', exact: true })
).toBeVisible()
await settingsCloseButton.click()
})

View File

@ -1,5 +1,5 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use kcl_lib::test_server;
use kcl_lib::{settings::types::UnitLength::Mm, test_server};
use tokio::runtime::Runtime;
pub fn bench_execute(c: &mut Criterion) {
@ -13,26 +13,42 @@ pub fn bench_execute(c: &mut Criterion) {
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
// precision and counteract the resulting noise.
group.sample_size(10);
group.bench_with_input(BenchmarkId::new("execute_", name), &code, |b, &s| {
group.bench_with_input(BenchmarkId::new("execute", name), &code, |b, &s| {
let rt = Runtime::new().unwrap();
// Spawn a future onto the runtime
b.iter(|| {
rt.block_on(test_server::execute_and_snapshot(
s,
kcl_lib::settings::types::UnitLength::Mm,
))
.unwrap();
rt.block_on(test_server::execute_and_snapshot(s, Mm)).unwrap();
});
});
group.finish();
}
}
criterion_group!(benches, bench_execute);
pub fn bench_lego(c: &mut Criterion) {
let mut group = c.benchmark_group("executor_lego_pattern");
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
// precision and counteract the resulting noise.
group.sample_size(10);
// Create lego bricks with N x 10 bumps, where N is each element of `sizes`.
let sizes = vec![1, 2, 4];
for size in sizes {
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
let rt = Runtime::new().unwrap();
let code = LEGO_PROGRAM.replace("{{N}}", &size.to_string());
// Spawn a future onto the runtime
b.iter(|| {
rt.block_on(test_server::execute_and_snapshot(&code, Mm)).unwrap();
});
});
}
group.finish();
}
criterion_group!(benches, bench_lego, bench_execute);
criterion_main!(benches);
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
const SERVER_RACK_HEAVY_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-heavy.kcl");
const SERVER_RACK_LITE_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-lite.kcl");
const LEGO_PROGRAM: &str = include_str!("../../tests/executor/inputs/slow_lego.kcl.tmpl");

View File

@ -1,8 +1,10 @@
//! Functions related to extruding.
use std::collections::HashMap;
use anyhow::Result;
use derive_docs::stdlib;
use kittycad::types::ExtrusionFaceCapType;
use kittycad::types::{ExtrusionFaceCapType, ExtrusionFaceInfo};
use schemars::JsonSchema;
use uuid::Uuid;
@ -99,7 +101,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
)
.await?;
args.send_modeling_cmd(
args.batch_modeling_cmd(
id,
kittycad::types::ModelingCmd::Extrude {
target: sketch_group.id,
@ -112,7 +114,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
// Disable the sketch mode.
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
.await?;
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, id, args.clone()).await?);
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, args.clone()).await?);
}
Ok(extrude_groups.into())
@ -121,7 +123,6 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
pub(crate) async fn do_post_extrude(
sketch_group: SketchGroup,
length: f64,
id: Uuid,
args: Args,
) -> Result<Box<ExtrudeGroup>, KclError> {
// Bring the object to the front of the scene.
@ -165,7 +166,7 @@ pub(crate) async fn do_post_extrude(
let solid3d_info = args
.send_modeling_cmd(
id,
uuid::Uuid::new_v4(),
kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo {
edge_id,
object_id: sketch_group.id,
@ -218,26 +219,11 @@ pub(crate) async fn do_post_extrude(
.await?;
}
// Create a hashmap for quick id lookup
let mut face_id_map = std::collections::HashMap::new();
// creating fake ids for start and end caps is to make extrudes mock-execute safe
let (mut start_cap_id, mut end_cap_id) = if args.ctx.is_mock {
(Some(Uuid::new_v4()), Some(Uuid::new_v4()))
} else {
(None, None)
};
for face_info in face_infos {
match face_info.cap {
ExtrusionFaceCapType::Bottom => start_cap_id = face_info.face_id,
ExtrusionFaceCapType::Top => end_cap_id = face_info.face_id,
ExtrusionFaceCapType::None => {
if let Some(curve_id) = face_info.curve_id {
face_id_map.insert(curve_id, face_info.face_id);
}
}
}
}
let Faces {
sides: face_id_map,
start_cap_id,
end_cap_id,
} = analyze_faces(&args, face_infos);
// Iterate over the sketch_group.value array and add face_id to GeoMeta
let new_value = sketch_group
.value
@ -301,3 +287,37 @@ pub(crate) async fn do_post_extrude(
edge_cuts: vec![],
}))
}
#[derive(Default)]
struct Faces {
/// Maps curve ID to face ID for each side.
sides: HashMap<Uuid, Option<Uuid>>,
/// Top face ID.
end_cap_id: Option<Uuid>,
/// Bottom face ID.
start_cap_id: Option<Uuid>,
}
fn analyze_faces(args: &Args, face_infos: Vec<ExtrusionFaceInfo>) -> Faces {
let mut faces = Faces {
sides: HashMap::with_capacity(face_infos.len()),
..Default::default()
};
if args.ctx.is_mock {
// Create fake IDs for start and end caps, to make extrudes mock-execute safe
faces.start_cap_id = Some(Uuid::new_v4());
faces.end_cap_id = Some(Uuid::new_v4());
}
for face_info in face_infos {
match face_info.cap {
ExtrusionFaceCapType::Bottom => faces.start_cap_id = face_info.face_id,
ExtrusionFaceCapType::Top => faces.end_cap_id = face_info.face_id,
ExtrusionFaceCapType::None => {
if let Some(curve_id) = face_info.curve_id {
faces.sides.insert(curve_id, face_info.face_id);
}
}
}
}
faces
}

View File

@ -170,5 +170,5 @@ async fn inner_loft(
.await?;
// Using the first sketch as the base curve, idk we might want to change this later.
do_post_extrude(sketch_groups[0].clone(), 0.0, id, args).await
do_post_extrude(sketch_groups[0].clone(), 0.0, args).await
}

View File

@ -299,7 +299,7 @@ async fn inner_revolve(
}
}
do_post_extrude(sketch_group, 0.0, id, args).await
do_post_extrude(sketch_group, 0.0, args).await
}
#[cfg(test)]

View File

@ -0,0 +1,81 @@
// 2x8 Lego Brick
// A standard Lego brick with 2 bumps wide and 8 bumps long.
// Define constants
const lbumps = 10 // number of bumps long
const wbumps = {{N}} // number of bumps wide
const pitch = 8.0
const clearance = 0.1
const bumpDiam = 4.8
const bumpHeight = 1.8
const height = 9.6
const t = (pitch - (2 * clearance) - bumpDiam) / 2.0
const totalLength = lbumps * pitch - (2.0 * clearance)
const totalWidth = wbumps * pitch - (2.0 * clearance)
// Create the plane for the pegs. This is a hack so that the pegs can be patterned along the face of the lego base.
const pegFace = {
plane: {
origin: { x: 0, y: 0, z: height },
xAxis: { x: 1, y: 0, z: 0 },
yAxis: { x: 0, y: 1, z: 0 },
zAxis: { x: 0, y: 0, z: 1 }
}
}
// Create the plane for the tubes underneath the lego. This is a hack so that the tubes can be patterned underneath the lego.
const tubeFace = {
plane: {
origin: { x: 0, y: 0, z: height - t },
xAxis: { x: 1, y: 0, z: 0 },
yAxis: { x: 0, y: 1, z: 0 },
zAxis: { x: 0, y: 0, z: 1 }
}
}
// Make the base
const s = startSketchOn('XY')
|> startProfileAt([-totalWidth / 2, -totalLength / 2], %)
|> line([totalWidth, 0], %)
|> line([0, totalLength], %)
|> line([-totalWidth, 0], %)
|> close(%)
|> extrude(height, %)
// Sketch and extrude a rectangular shape to create the shell underneath the lego. This is a hack until we have a shell function.
const shellExtrude = startSketchOn(s, "start")
|> startProfileAt([
-(totalWidth / 2 - t),
-(totalLength / 2 - t)
], %)
|> line([totalWidth - (2 * t), 0], %)
|> line([0, totalLength - (2 * t)], %)
|> line([-(totalWidth - (2 * t)), 0], %)
|> close(%)
|> extrude(-(height - t), %)
fn tr = (i) => {
let j = i + 1
let x = (j/wbumps) * pitch
let y = (j % wbumps) * pitch
return {
translate: [x, y, 0],
}
}
// Create the pegs on the top of the base
const totalBumps = (wbumps * lbumps)-1
const peg = startSketchOn(s, 'end')
|> circle([
-(pitch*(wbumps-1)/2),
-(pitch*(lbumps-1)/2)
], bumpDiam / 2, %)
|> patternLinear2d({
axis: [1, 0],
repetitions: wbumps-1,
distance: pitch
}, %)
|> patternLinear2d({
axis: [0, 1],
repetitions: lbumps-1,
distance: pitch
}, %)
|> extrude(bumpHeight, %)
// |> patternTransform(int(totalBumps-1), tr, %)