2024-06-17 12:13:19 -07:00
|
|
|
//! Standard library chamfers.
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use derive_docs::stdlib;
|
|
|
|
use kittycad::types::ModelingCmd;
|
|
|
|
use schemars::JsonSchema;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
errors::{KclError, KclErrorDetails},
|
2024-06-23 19:19:24 -07:00
|
|
|
executor::{ExtrudeGroup, FilletOrChamfer, MemoryItem},
|
2024-06-17 12:13:19 -07:00
|
|
|
std::Args,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001;
|
|
|
|
|
|
|
|
/// Data for chamfers.
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
|
|
|
#[ts(export)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
pub struct ChamferData {
|
2024-06-18 18:33:57 -07:00
|
|
|
/// The length of the chamfer.
|
|
|
|
pub length: f64,
|
2024-06-17 12:13:19 -07:00
|
|
|
/// The tags of the paths you want to chamfer.
|
|
|
|
pub tags: Vec<EdgeReference>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A string or a uuid.
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Ord, PartialOrd, Eq, Hash)]
|
|
|
|
#[ts(export)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
pub enum EdgeReference {
|
|
|
|
/// A uuid of an edge.
|
|
|
|
Uuid(uuid::Uuid),
|
|
|
|
/// A tag name of an edge.
|
|
|
|
Tag(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create chamfers on tagged paths.
|
|
|
|
pub async fn chamfer(args: Args) -> Result<MemoryItem, KclError> {
|
|
|
|
let (data, extrude_group): (ChamferData, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
|
|
|
|
|
|
|
let extrude_group = inner_chamfer(data, extrude_group, args).await?;
|
|
|
|
Ok(MemoryItem::ExtrudeGroup(extrude_group))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create chamfers on tagged paths.
|
|
|
|
///
|
|
|
|
/// ```no_run
|
|
|
|
/// const width = 20
|
|
|
|
/// const length = 10
|
|
|
|
/// const thickness = 1
|
2024-06-18 18:33:57 -07:00
|
|
|
/// const chamferLength = 2
|
2024-06-17 12:13:19 -07:00
|
|
|
///
|
|
|
|
/// const mountingPlateSketch = startSketchOn("XY")
|
|
|
|
/// |> startProfileAt([-width/2, -length/2], %)
|
|
|
|
/// |> lineTo([width/2, -length/2], %, 'edge1')
|
|
|
|
/// |> lineTo([width/2, length/2], %, 'edge2')
|
|
|
|
/// |> lineTo([-width/2, length/2], %, 'edge3')
|
|
|
|
/// |> close(%, 'edge4')
|
|
|
|
///
|
|
|
|
/// const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|
|
|
/// |> chamfer({
|
2024-06-18 18:33:57 -07:00
|
|
|
/// length: chamferLength,
|
2024-06-17 12:13:19 -07:00
|
|
|
/// tags: [
|
|
|
|
/// getNextAdjacentEdge('edge1', %),
|
|
|
|
/// getNextAdjacentEdge('edge2', %),
|
|
|
|
/// getNextAdjacentEdge('edge3', %),
|
|
|
|
/// getNextAdjacentEdge('edge4', %)
|
|
|
|
/// ],
|
|
|
|
/// }, %)
|
|
|
|
/// ```
|
|
|
|
#[stdlib {
|
|
|
|
name = "chamfer",
|
|
|
|
}]
|
|
|
|
async fn inner_chamfer(
|
|
|
|
data: ChamferData,
|
|
|
|
extrude_group: Box<ExtrudeGroup>,
|
|
|
|
args: Args,
|
|
|
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
|
|
|
// Check if tags contains any duplicate values.
|
|
|
|
let mut tags = data.tags.clone();
|
|
|
|
tags.sort();
|
|
|
|
tags.dedup();
|
|
|
|
if tags.len() != data.tags.len() {
|
|
|
|
return Err(KclError::Type(KclErrorDetails {
|
|
|
|
message: "Duplicate tags are not allowed.".to_string(),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2024-06-23 19:19:24 -07:00
|
|
|
let mut fillet_or_chamfers = Vec::new();
|
2024-06-17 12:13:19 -07:00
|
|
|
for tag in data.tags {
|
|
|
|
let edge_id = match tag {
|
|
|
|
EdgeReference::Uuid(uuid) => uuid,
|
|
|
|
EdgeReference::Tag(tag) => {
|
|
|
|
extrude_group
|
2024-06-21 23:50:30 -07:00
|
|
|
.sketch_group
|
|
|
|
.value
|
2024-06-17 12:13:19 -07:00
|
|
|
.iter()
|
|
|
|
.find(|p| p.get_name() == tag)
|
|
|
|
.ok_or_else(|| {
|
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!("No edge found with tag: `{}`", tag),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?
|
|
|
|
.get_base()
|
|
|
|
.geo_meta
|
|
|
|
.id
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-06-23 19:19:24 -07:00
|
|
|
let id = uuid::Uuid::new_v4();
|
2024-06-22 14:31:37 -07:00
|
|
|
args.batch_end_cmd(
|
2024-06-23 19:19:24 -07:00
|
|
|
id,
|
2024-06-17 12:13:19 -07:00
|
|
|
ModelingCmd::Solid3DFilletEdge {
|
|
|
|
edge_id,
|
|
|
|
object_id: extrude_group.id,
|
2024-06-18 18:33:57 -07:00
|
|
|
radius: data.length,
|
2024-06-17 12:13:19 -07:00
|
|
|
tolerance: DEFAULT_TOLERANCE, // We can let the user set this in the future.
|
|
|
|
cut_type: Some(kittycad::types::CutType::Chamfer),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await?;
|
2024-06-23 19:19:24 -07:00
|
|
|
|
|
|
|
fillet_or_chamfers.push(FilletOrChamfer::Chamfer {
|
|
|
|
id,
|
|
|
|
edge_id,
|
|
|
|
length: data.length,
|
|
|
|
});
|
2024-06-17 12:13:19 -07:00
|
|
|
}
|
|
|
|
|
2024-06-23 19:19:24 -07:00
|
|
|
let mut extrude_group = extrude_group.clone();
|
|
|
|
extrude_group.fillet_or_chamfers = fillet_or_chamfers;
|
|
|
|
|
2024-06-17 12:13:19 -07:00
|
|
|
Ok(extrude_group)
|
|
|
|
}
|