use face edge info for some mirrors (#7174)

* use face edge info for some mirrors

* add functionality for other mirror function

* Fix to create new Sketch when mirror results in a new path

* use the original ids and clone the sketches

* remove mirror param

* clippy fix

* debuggin, rm yarn

* Revert "remove mirror param"

This reverts commit a848e243f8.

* use arrbitrary edge_id as sketch mirror id

* additinoal clenaup

* Update rust/kcl-lib/src/std/mirror.rs

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* set .mirror for continuous case

* fix warning

* works without the for loops

* add error handling

* remove duplicate setter

* rm unused var

* clenaup

* unused import

* remove unused let

* Update snapshots

* Update snapshots

* cleanup

* update sim tests

---------

Co-authored-by: gserena <serena@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Serena Gandhi
2025-06-23 12:27:03 -05:00
committed by GitHub
parent 631b63b1b6
commit 1e1bdbd6e7
13 changed files with 67 additions and 175 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -175,10 +175,10 @@ pub(crate) async fn do_post_extrude<'a>(
) )
.await?; .await?;
let any_edge_id = if let Some(id) = edge_id { let any_edge_id = if let Some(edge_id) = sketch.mirror {
id
} else if let Some(edge_id) = sketch.mirror {
edge_id edge_id
} else if let Some(id) = edge_id {
id
} else { } else {
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded. // The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
// So, let's just use the first one. // So, let's just use the first one.

View File

@ -3,8 +3,8 @@
use anyhow::Result; use anyhow::Result;
use kcmc::{each_cmd as mcmd, ModelingCmd}; use kcmc::{each_cmd as mcmd, ModelingCmd};
use kittycad_modeling_cmds::{ use kittycad_modeling_cmds::{
self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, output::EntityGetAllChildUuids, self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Point3d,
shared::Point3d, websocket::OkWebSocketResponseData, websocket::OkWebSocketResponseData,
}; };
use crate::{ use crate::{
@ -41,19 +41,14 @@ async fn inner_mirror_2d(
) -> Result<Vec<Sketch>, KclError> { ) -> Result<Vec<Sketch>, KclError> {
let mut starting_sketches = sketches.clone(); let mut starting_sketches = sketches.clone();
// Update all to have a mirror.
starting_sketches.iter_mut().for_each(|sketch| {
sketch.mirror = Some(exec_state.next_uuid());
});
if args.ctx.no_engine_commands().await { if args.ctx.no_engine_commands().await {
return Ok(starting_sketches); return Ok(starting_sketches);
} }
match axis { match axis {
Axis2dOrEdgeReference::Axis { direction, origin } => { Axis2dOrEdgeReference::Axis { direction, origin } => {
exec_state let resp = exec_state
.batch_modeling_cmd( .send_modeling_cmd(
(&args).into(), (&args).into(),
ModelingCmd::from(mcmd::EntityMirror { ModelingCmd::from(mcmd::EntityMirror {
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(), ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
@ -70,12 +65,42 @@ async fn inner_mirror_2d(
}), }),
) )
.await?; .await?;
if let OkWebSocketResponseData::Modeling {
modeling_response: OkModelingCmdResponse::EntityMirror(mirror_info),
} = &resp
{
let face_edge_info = &mirror_info.entity_face_edge_ids;
starting_sketches
.iter_mut()
.zip(face_edge_info.iter())
.try_for_each(|(sketch, info)| {
sketch.id = info.object_id;
let first_edge = info.edges.first().copied();
match first_edge {
Some(edge) => sketch.mirror = Some(edge),
None => {
return Err(KclError::new_engine(KclErrorDetails::new(
"No edges found in mirror info".to_string(),
vec![args.source_range],
)))
}
}
Ok(())
})?;
} else {
return Err(KclError::new_engine(KclErrorDetails::new(
format!("EntityMirror response was not as expected: {:?}", resp),
vec![args.source_range],
)));
};
} }
Axis2dOrEdgeReference::Edge(edge) => { Axis2dOrEdgeReference::Edge(edge) => {
let edge_id = edge.get_engine_id(exec_state, &args)?; let edge_id = edge.get_engine_id(exec_state, &args)?;
exec_state let resp = exec_state
.batch_modeling_cmd( .send_modeling_cmd(
(&args).into(), (&args).into(),
ModelingCmd::from(mcmd::EntityMirrorAcrossEdge { ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
ids: starting_sketches.iter().map(|sketch| sketch.id).collect(), ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
@ -83,41 +108,36 @@ async fn inner_mirror_2d(
}), }),
) )
.await?; .await?;
}
};
// After the mirror, get the first child uuid for the path. if let OkWebSocketResponseData::Modeling {
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded. modeling_response: OkModelingCmdResponse::EntityMirrorAcrossEdge(mirror_info),
// But if you mirror2d a sketch these IDs might change so we need to get the children versus } = &resp
// using the IDs we already have. {
// We only do this with mirrors because otherwise it is a waste of a websocket call. let face_edge_info = &mirror_info.entity_face_edge_ids;
for sketch in &mut starting_sketches {
let response = exec_state
.send_modeling_cmd(
(&args).into(),
ModelingCmd::from(mcmd::EntityGetAllChildUuids { entity_id: sketch.id }),
)
.await?;
let OkWebSocketResponseData::Modeling {
modeling_response:
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids { entity_ids: child_ids }),
} = response
else {
return Err(KclError::new_internal(KclErrorDetails::new(
"Expected a successful response from EntityGetAllChildUuids".to_string(),
vec![args.source_range],
)));
};
if child_ids.len() >= 2 { starting_sketches
// The first child is the original sketch, the second is the mirrored sketch. .iter_mut()
let child_id = child_ids[1]; .zip(face_edge_info.iter())
sketch.mirror = Some(child_id); .try_for_each(|(sketch, info)| {
} else { sketch.id = info.object_id;
return Err(KclError::new_type(KclErrorDetails::new( let first_edge = info.edges.first().copied();
"Expected child uuids to be >= 2".to_string(), match first_edge {
vec![args.source_range], Some(edge) => sketch.mirror = Some(edge),
))); None => {
return Err(KclError::new_engine(KclErrorDetails::new(
"No edges found in mirror info".to_string(),
vec![args.source_range],
)))
}
}
Ok(())
})?;
} else {
return Err(KclError::new_engine(KclErrorDetails::new(
format!("EntityMirrorAcrossEdge response was not as expected: {:?}", resp),
vec![args.source_range],
)));
};
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -148,14 +148,6 @@ description: Artifact commands bottle.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -327,14 +327,6 @@ description: Artifact commands cold-plate.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -4828,14 +4828,6 @@ description: Artifact commands cpu-cooler.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -4856,14 +4848,6 @@ description: Artifact commands cpu-cooler.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -6095,14 +6079,6 @@ description: Artifact commands cpu-cooler.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -6436,14 +6412,6 @@ description: Artifact commands cpu-cooler.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -1136,14 +1136,6 @@ description: Artifact commands helium-tank.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -1362,14 +1354,6 @@ description: Artifact commands helium-tank.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -176,14 +176,6 @@ description: Artifact commands i-beam.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -204,14 +196,6 @@ description: Artifact commands i-beam.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -342,14 +342,6 @@ description: Artifact commands t-slot-rail.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -370,14 +362,6 @@ description: Artifact commands t-slot-rail.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -398,14 +382,6 @@ description: Artifact commands t-slot-rail.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],

View File

@ -1170,14 +1170,6 @@ description: Artifact commands subtract_regression10.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -1639,14 +1631,6 @@ description: Artifact commands subtract_regression10.kcl
"edge_id": "[uuid]" "edge_id": "[uuid]"
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],
@ -1895,14 +1879,6 @@ description: Artifact commands subtract_regression10.kcl
} }
} }
}, },
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "entity_get_all_child_uuids",
"entity_id": "[uuid]"
}
},
{ {
"cmdId": "[uuid]", "cmdId": "[uuid]",
"range": [], "range": [],