@ -3092,3 +3092,24 @@ mod error_revolve_on_edge_get_edge {
 | 
			
		||||
        super::execute(TEST_NAME, true).await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
mod mirror_sketch_extrude_2_artifacts {
 | 
			
		||||
    const TEST_NAME: &str = "mirror_sketch_extrude_2_artifacts";
 | 
			
		||||
 | 
			
		||||
    /// Test parsing KCL.
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn parse() {
 | 
			
		||||
        super::parse(TEST_NAME)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Test that parsing and unparsing KCL produces the original KCL input.
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn unparse() {
 | 
			
		||||
        super::unparse(TEST_NAME).await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Test that KCL is executed correctly.
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn kcl_test_execute() {
 | 
			
		||||
        super::execute(TEST_NAME, true).await
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,12 @@
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
 | 
			
		||||
use kittycad_modeling_cmds::{
 | 
			
		||||
    self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, output::EntityGetAllChildUuids,
 | 
			
		||||
    shared::Point3d, websocket::OkWebSocketResponseData,
 | 
			
		||||
    self as kcmc,
 | 
			
		||||
    length_unit::LengthUnit,
 | 
			
		||||
    ok_response::OkModelingCmdResponse,
 | 
			
		||||
    output::{EntityMirror, EntityMirrorAcrossEdge},
 | 
			
		||||
    shared::Point3d,
 | 
			
		||||
    websocket::OkWebSocketResponseData,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
@ -54,72 +58,83 @@ async fn inner_mirror_2d(
 | 
			
		||||
        return Ok(starting_sketches);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    match axis {
 | 
			
		||||
        Axis2dOrEdgeReference::Axis { direction, origin } => {
 | 
			
		||||
            args.batch_modeling_cmd(
 | 
			
		||||
                exec_state.next_uuid(),
 | 
			
		||||
                ModelingCmd::from(mcmd::EntityMirror {
 | 
			
		||||
                    ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
 | 
			
		||||
                    axis: Point3d {
 | 
			
		||||
                        x: direction[0].to_mm(),
 | 
			
		||||
                        y: direction[1].to_mm(),
 | 
			
		||||
                        z: 0.0,
 | 
			
		||||
                    },
 | 
			
		||||
                    point: Point3d {
 | 
			
		||||
                        x: LengthUnit(origin[0].to_mm()),
 | 
			
		||||
                        y: LengthUnit(origin[1].to_mm()),
 | 
			
		||||
                        z: LengthUnit(0.0),
 | 
			
		||||
                    },
 | 
			
		||||
                }),
 | 
			
		||||
            )
 | 
			
		||||
            .await?;
 | 
			
		||||
        }
 | 
			
		||||
        Axis2dOrEdgeReference::Edge(edge) => {
 | 
			
		||||
            let edge_id = edge.get_engine_id(exec_state, &args)?;
 | 
			
		||||
    for sketch in &starting_sketches.clone() {
 | 
			
		||||
        let results = match &axis {
 | 
			
		||||
            Axis2dOrEdgeReference::Axis { direction, origin } => {
 | 
			
		||||
                let response = args
 | 
			
		||||
                    .send_modeling_cmd(
 | 
			
		||||
                        sketch.mirror.unwrap(), // This is safe we just made it above.
 | 
			
		||||
                        ModelingCmd::from(mcmd::EntityMirror {
 | 
			
		||||
                            ids: vec![sketch.id],
 | 
			
		||||
                            axis: Point3d {
 | 
			
		||||
                                x: direction[0].to_mm(),
 | 
			
		||||
                                y: direction[1].to_mm(),
 | 
			
		||||
                                z: 0.0,
 | 
			
		||||
                            },
 | 
			
		||||
                            point: Point3d {
 | 
			
		||||
                                x: LengthUnit(origin[0].to_mm()),
 | 
			
		||||
                                y: LengthUnit(origin[1].to_mm()),
 | 
			
		||||
                                z: LengthUnit(0.0),
 | 
			
		||||
                            },
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                    .await?;
 | 
			
		||||
 | 
			
		||||
            args.batch_modeling_cmd(
 | 
			
		||||
                exec_state.next_uuid(),
 | 
			
		||||
                ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
 | 
			
		||||
                    ids: starting_sketches.iter().map(|sketch| sketch.id).collect(),
 | 
			
		||||
                    edge_id,
 | 
			
		||||
                }),
 | 
			
		||||
            )
 | 
			
		||||
            .await?;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
                let OkWebSocketResponseData::Modeling {
 | 
			
		||||
                    modeling_response:
 | 
			
		||||
                        OkModelingCmdResponse::EntityMirror(EntityMirror {
 | 
			
		||||
                            entity_face_edge_ids, ..
 | 
			
		||||
                        }),
 | 
			
		||||
                } = response
 | 
			
		||||
                else {
 | 
			
		||||
                    return Err(KclError::Internal(KclErrorDetails {
 | 
			
		||||
                        message: "Expected a successful response from EntityMirror".to_string(),
 | 
			
		||||
                        source_ranges: vec![args.source_range],
 | 
			
		||||
                    }));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
    // After the mirror, get the first child uuid for the path.
 | 
			
		||||
    // The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
 | 
			
		||||
    // But if you mirror2d a sketch these IDs might change so we need to get the children versus
 | 
			
		||||
    // using the IDs we already have.
 | 
			
		||||
    // We only do this with mirrors because otherwise it is a waste of a websocket call.
 | 
			
		||||
    for sketch in &mut starting_sketches {
 | 
			
		||||
        let response = args
 | 
			
		||||
            .send_modeling_cmd(
 | 
			
		||||
                exec_state.next_uuid(),
 | 
			
		||||
                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::Internal(KclErrorDetails {
 | 
			
		||||
                message: "Expected a successful response from EntityGetAllChildUuids".to_string(),
 | 
			
		||||
                source_ranges: vec![args.source_range],
 | 
			
		||||
            }));
 | 
			
		||||
                entity_face_edge_ids
 | 
			
		||||
            }
 | 
			
		||||
            Axis2dOrEdgeReference::Edge(edge) => {
 | 
			
		||||
                let edge_id = edge.get_engine_id(exec_state, &args)?;
 | 
			
		||||
 | 
			
		||||
                let response = args
 | 
			
		||||
                    .send_modeling_cmd(
 | 
			
		||||
                        sketch.mirror.unwrap(), // This is safe we just made it above.
 | 
			
		||||
                        ModelingCmd::from(mcmd::EntityMirrorAcrossEdge {
 | 
			
		||||
                            ids: vec![sketch.id],
 | 
			
		||||
                            edge_id,
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                    .await?;
 | 
			
		||||
 | 
			
		||||
                let OkWebSocketResponseData::Modeling {
 | 
			
		||||
                    modeling_response:
 | 
			
		||||
                        OkModelingCmdResponse::EntityMirrorAcrossEdge(EntityMirrorAcrossEdge {
 | 
			
		||||
                            entity_face_edge_ids, ..
 | 
			
		||||
                        }),
 | 
			
		||||
                } = response
 | 
			
		||||
                else {
 | 
			
		||||
                    return Err(KclError::Internal(KclErrorDetails {
 | 
			
		||||
                        message: "Expected a successful response from EntityMirrorAcrossEdge".to_string(),
 | 
			
		||||
                        source_ranges: vec![args.source_range],
 | 
			
		||||
                    }));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                entity_face_edge_ids
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if child_ids.len() >= 2 {
 | 
			
		||||
            // The first child is the original sketch, the second is the mirrored sketch.
 | 
			
		||||
            let child_id = child_ids[1];
 | 
			
		||||
            sketch.mirror = Some(child_id);
 | 
			
		||||
        } else {
 | 
			
		||||
            return Err(KclError::Type(KclErrorDetails {
 | 
			
		||||
                message: "Expected child uuids to be >= 2".to_string(),
 | 
			
		||||
                source_ranges: vec![args.source_range],
 | 
			
		||||
            }));
 | 
			
		||||
        println!("Mirror response: {:?}", results);
 | 
			
		||||
        for result in results {
 | 
			
		||||
            if result.object_id != sketch.id {
 | 
			
		||||
                // Add a new sketch to the list.
 | 
			
		||||
                let mut new_sketch = sketch.clone();
 | 
			
		||||
                new_sketch.id = result.object_id;
 | 
			
		||||
                new_sketch.original_id = sketch.id;
 | 
			
		||||
 | 
			
		||||
                starting_sketches.push(new_sketch);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2591
									
								
								rust/kcl-lib/tests/mirror_sketch_extrude_2_artifacts/ast.snap
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2591
									
								
								rust/kcl-lib/tests/mirror_sketch_extrude_2_artifacts/ast.snap
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
@settings(defaultLengthUnit = in)
 | 
			
		||||
 | 
			
		||||
// Define parameters
 | 
			
		||||
trussSupportAngle = 15
 | 
			
		||||
height = 120
 | 
			
		||||
thickness = 4
 | 
			
		||||
 | 
			
		||||
sketch001 = startSketchOn(YZ)
 | 
			
		||||
profile001 = startProfile(sketch001, at = [60, 0])
 | 
			
		||||
  |> xLine(length = -120)
 | 
			
		||||
  |> yLine(length = 12)
 | 
			
		||||
  |> angledLine(angle = 25, endAbsoluteX = 0, tag = $tag001)
 | 
			
		||||
  |> angledLine(angle = -25, endAbsoluteX = 60)
 | 
			
		||||
  |> close()
 | 
			
		||||
 | 
			
		||||
profile002 = startProfile(sketch001, at = [60-thickness, thickness])
 | 
			
		||||
  |> xLine(endAbsolute = thickness/2)
 | 
			
		||||
  |> yLine(endAbsolute = segEndY(tag001)-thickness) // update
 | 
			
		||||
  |> angledLine(endAbsoluteX = profileStartX(%), angle = -25)
 | 
			
		||||
  |> close(%)
 | 
			
		||||
 | 
			
		||||
profile003 = startProfile(sketch001, at = [-60+thickness, thickness])
 | 
			
		||||
  |> xLine(endAbsolute = -thickness/2)
 | 
			
		||||
  |> yLine(endAbsolute = segEndY(tag001)-thickness) // update
 | 
			
		||||
  |> angledLine(endAbsoluteX = profileStartX(%), angle = 205)
 | 
			
		||||
  |> close(%)
 | 
			
		||||
 | 
			
		||||
// profile003 = mirror2d(profile002, axis = Y)
 | 
			
		||||
 | 
			
		||||
profile004 = subtract2d(profile001, tool = profile002)
 | 
			
		||||
subtract2d(profile001, tool = profile003)
 | 
			
		||||
 | 
			
		||||
body001 = extrude(profile001, length = 2)
 | 
			
		||||
 | 
			
		||||
sketch002 = startSketchOn(offsetPlane(YZ, offset = .1))
 | 
			
		||||
profile006 = startProfile(sketch002, at = [thickness/2-1, 14])
 | 
			
		||||
  |> angledLine(angle = 30, length = 25)
 | 
			
		||||
  |> angledLine(angle = -25, length = 5)
 | 
			
		||||
  |> angledLine(angle = 210, endAbsoluteX = profileStartX(%))
 | 
			
		||||
  |> close(%)
 | 
			
		||||
 | 
			
		||||
profile007 = mirror2d(profile006, axis = Y)
 | 
			
		||||
 | 
			
		||||
beams = extrude([ profile007], length = 1.8)
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 20 KiB  | 
@ -0,0 +1,48 @@
 | 
			
		||||
---
 | 
			
		||||
source: kcl-lib/src/simulation_tests.rs
 | 
			
		||||
description: Result of unparsing mirror_sketch_extrude_2_artifacts.kcl
 | 
			
		||||
---
 | 
			
		||||
@settings(defaultLengthUnit = in)
 | 
			
		||||
 | 
			
		||||
// Define parameters
 | 
			
		||||
trussSupportAngle = 15
 | 
			
		||||
height = 120
 | 
			
		||||
thickness = 4
 | 
			
		||||
 | 
			
		||||
sketch001 = startSketchOn(YZ)
 | 
			
		||||
profile001 = startProfile(sketch001, at = [60, 0])
 | 
			
		||||
  |> xLine(length = -120)
 | 
			
		||||
  |> yLine(length = 12)
 | 
			
		||||
  |> angledLine(angle = 25, endAbsoluteX = 0, tag = $tag001)
 | 
			
		||||
  |> angledLine(angle = -25, endAbsoluteX = 60)
 | 
			
		||||
  |> close()
 | 
			
		||||
 | 
			
		||||
profile002 = startProfile(sketch001, at = [60 - thickness, thickness])
 | 
			
		||||
  |> xLine(endAbsolute = thickness / 2)
 | 
			
		||||
  |> yLine(endAbsolute = segEndY(tag001) - thickness) // update
 | 
			
		||||
  |> angledLine(endAbsoluteX = profileStartX(%), angle = -25)
 | 
			
		||||
  |> close(%)
 | 
			
		||||
 | 
			
		||||
profile003 = startProfile(sketch001, at = [-60 + thickness, thickness])
 | 
			
		||||
  |> xLine(endAbsolute = -thickness / 2)
 | 
			
		||||
  |> yLine(endAbsolute = segEndY(tag001) - thickness) // update
 | 
			
		||||
  |> angledLine(endAbsoluteX = profileStartX(%), angle = 205)
 | 
			
		||||
  |> close(%)
 | 
			
		||||
 | 
			
		||||
// profile003 = mirror2d(profile002, axis = Y)
 | 
			
		||||
 | 
			
		||||
profile004 = subtract2d(profile001, tool = profile002)
 | 
			
		||||
subtract2d(profile001, tool = profile003)
 | 
			
		||||
 | 
			
		||||
body001 = extrude(profile001, length = 2)
 | 
			
		||||
 | 
			
		||||
sketch002 = startSketchOn(offsetPlane(YZ, offset = .1))
 | 
			
		||||
profile006 = startProfile(sketch002, at = [thickness / 2 - 1, 14])
 | 
			
		||||
  |> angledLine(angle = 30, length = 25)
 | 
			
		||||
  |> angledLine(angle = -25, length = 5)
 | 
			
		||||
  |> angledLine(angle = 210, endAbsoluteX = profileStartX(%))
 | 
			
		||||
  |> close(%)
 | 
			
		||||
 | 
			
		||||
profile007 = mirror2d(profile006, axis = Y)
 | 
			
		||||
 | 
			
		||||
beams = extrude([profile007], length = 1.8)
 | 
			
		||||
		Reference in New Issue
	
	Block a user