2023-08-24 15:34:51 -07:00
|
|
|
//! Functions related to line segments.
|
|
|
|
|
2023-08-29 14:12:48 -07:00
|
|
|
use anyhow::Result;
|
|
|
|
use derive_docs::stdlib;
|
|
|
|
use schemars::JsonSchema;
|
|
|
|
|
2023-08-24 15:34:51 -07:00
|
|
|
use crate::{
|
|
|
|
errors::{KclError, KclErrorDetails},
|
2024-06-24 14:45:07 -07:00
|
|
|
executor::{MemoryItem, SketchGroup, TagIdentifier},
|
2024-06-19 13:57:50 -07:00
|
|
|
std::{utils::between, Args},
|
2023-08-24 15:34:51 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Returns the segment end of x.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn segment_end_x(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_segment_end_x(&segment_name, sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the segment end of x.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const exampleSketch = startSketchOn('XZ')
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([20, 0], %, "thing")
|
|
|
|
/// |> line([0, 5], %)
|
|
|
|
/// |> line([segEndX("thing", %), 0], %)
|
|
|
|
/// |> line([-20, 10], %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "segEndX",
|
|
|
|
}]
|
2024-06-24 14:45:07 -07:00
|
|
|
fn inner_segment_end_x(
|
|
|
|
segment_name: &TagIdentifier,
|
|
|
|
sketch_group: Box<SketchGroup>,
|
|
|
|
args: Args,
|
|
|
|
) -> Result<f64, KclError> {
|
|
|
|
let line = sketch_group.get_base_by_tag_or_start(segment_name).ok_or_else(|| {
|
2023-08-29 14:12:48 -07:00
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
|
|
segment_name
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?;
|
2023-08-24 15:34:51 -07:00
|
|
|
|
2023-08-25 13:41:04 -07:00
|
|
|
Ok(line.to[0])
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the segment end of y.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn segment_end_y(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_segment_end_y(&segment_name, sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the segment end of y.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const exampleSketch = startSketchOn('XZ')
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([20, 0], %)
|
|
|
|
/// |> line([0, 3], %, "thing")
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
/// |> line([0, segEndY("thing", %)], %)
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "segEndY",
|
|
|
|
}]
|
2024-06-24 14:45:07 -07:00
|
|
|
fn inner_segment_end_y(
|
|
|
|
segment_name: &TagIdentifier,
|
|
|
|
sketch_group: Box<SketchGroup>,
|
|
|
|
args: Args,
|
|
|
|
) -> Result<f64, KclError> {
|
|
|
|
let line = sketch_group.get_base_by_tag_or_start(segment_name).ok_or_else(|| {
|
2023-08-29 14:12:48 -07:00
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
|
|
segment_name
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?;
|
2023-08-24 15:34:51 -07:00
|
|
|
|
2023-08-25 13:41:04 -07:00
|
|
|
Ok(line.to[1])
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the last segment of x.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn last_segment_x(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let sketch_group = args.get_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_last_segment_x(sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the last segment of x.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([5, 0], %)
|
|
|
|
/// |> line([20, 5], %)
|
|
|
|
/// |> line([0, lastSegX(%)], %)
|
|
|
|
/// |> line([-15, 0], %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "lastSegX",
|
|
|
|
}]
|
2023-09-20 18:27:08 -07:00
|
|
|
fn inner_last_segment_x(sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let last_line = sketch_group
|
|
|
|
.value
|
|
|
|
.last()
|
|
|
|
.ok_or_else(|| {
|
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a SketchGroup with at least one segment, found `{:?}`",
|
|
|
|
sketch_group
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?
|
|
|
|
.get_base();
|
|
|
|
|
2023-08-25 13:41:04 -07:00
|
|
|
Ok(last_line.to[0])
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the last segment of y.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn last_segment_y(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let sketch_group = args.get_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_last_segment_y(sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the last segment of y.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([5, 0], %)
|
|
|
|
/// |> line([20, 5], %)
|
|
|
|
/// |> line([0, lastSegY(%)], %)
|
|
|
|
/// |> line([-15, 0], %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "lastSegY",
|
|
|
|
}]
|
2023-09-20 18:27:08 -07:00
|
|
|
fn inner_last_segment_y(sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let last_line = sketch_group
|
|
|
|
.value
|
|
|
|
.last()
|
|
|
|
.ok_or_else(|| {
|
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a SketchGroup with at least one segment, found `{:?}`",
|
|
|
|
sketch_group
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?
|
|
|
|
.get_base();
|
|
|
|
|
2023-08-25 13:41:04 -07:00
|
|
|
Ok(last_line.to[1])
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the length of the segment.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn segment_length(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_segment_length(&segment_name, sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the length of the segment.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> angledLine({
|
|
|
|
/// angle: 60,
|
|
|
|
/// length: 10,
|
|
|
|
/// }, %, "thing")
|
|
|
|
/// |> tangentialArc({
|
|
|
|
/// offset: -120,
|
|
|
|
/// radius: 5,
|
|
|
|
/// }, %)
|
|
|
|
/// |> angledLine({
|
|
|
|
/// angle: -60,
|
|
|
|
/// length: segLen("thing", %),
|
|
|
|
/// }, %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "segLen",
|
|
|
|
}]
|
2024-06-24 14:45:07 -07:00
|
|
|
fn inner_segment_length(
|
|
|
|
segment_name: &TagIdentifier,
|
|
|
|
sketch_group: Box<SketchGroup>,
|
|
|
|
args: Args,
|
|
|
|
) -> Result<f64, KclError> {
|
|
|
|
let path = sketch_group.get_path_by_tag(segment_name).ok_or_else(|| {
|
2023-08-25 13:41:04 -07:00
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
|
|
segment_name
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?;
|
2023-08-24 15:34:51 -07:00
|
|
|
let line = path.get_base();
|
|
|
|
|
|
|
|
let result = ((line.from[1] - line.to[1]).powi(2) + (line.from[0] - line.to[0]).powi(2)).sqrt();
|
2023-08-25 13:41:04 -07:00
|
|
|
|
|
|
|
Ok(result)
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the angle of the segment.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn segment_angle(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let (segment_name, sketch_group) = args.get_segment_name_sketch_group()?;
|
2023-08-25 13:41:04 -07:00
|
|
|
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_segment_angle(&segment_name, sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the angle of the segment.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const exampleSketch = startSketchOn('XZ')
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([10, 0], %)
|
|
|
|
/// |> line([5, 10], %, 'seg01')
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
/// |> angledLine([segAng('seg01', %), 10], %)
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
/// |> angledLine([segAng('seg01', %), -15], %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const example = extrude(4, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "segAng",
|
|
|
|
}]
|
2024-06-24 14:45:07 -07:00
|
|
|
fn inner_segment_angle(
|
|
|
|
segment_name: &TagIdentifier,
|
|
|
|
sketch_group: Box<SketchGroup>,
|
|
|
|
args: Args,
|
|
|
|
) -> Result<f64, KclError> {
|
|
|
|
let path = sketch_group.get_path_by_tag(segment_name).ok_or_else(|| {
|
2023-08-25 13:41:04 -07:00
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
|
|
segment_name
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?;
|
2023-08-24 15:34:51 -07:00
|
|
|
let line = path.get_base();
|
|
|
|
|
2023-10-24 16:32:41 -07:00
|
|
|
let result = between(line.from.into(), line.to.into());
|
2023-08-25 13:41:04 -07:00
|
|
|
|
2023-09-14 15:51:26 -06:00
|
|
|
Ok(result.degrees())
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the angle to match the given length for x.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn angle_to_match_length_x(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let (segment_name, to, sketch_group) = args.get_segment_name_to_number_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_angle_to_match_length_x(&segment_name, to, sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the angle to match the given length for x.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([2, 5], %, 'seg01')
|
|
|
|
/// |> angledLineToX([
|
|
|
|
/// -angleToMatchLengthX('seg01', 7, %),
|
|
|
|
/// 10
|
|
|
|
/// ], %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const extrusion = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "angleToMatchLengthX",
|
|
|
|
}]
|
|
|
|
fn inner_angle_to_match_length_x(
|
2024-06-24 14:45:07 -07:00
|
|
|
segment_name: &TagIdentifier,
|
2023-08-25 13:41:04 -07:00
|
|
|
to: f64,
|
2023-09-19 14:20:14 -07:00
|
|
|
sketch_group: Box<SketchGroup>,
|
2023-09-20 18:27:08 -07:00
|
|
|
args: Args,
|
2023-08-25 13:41:04 -07:00
|
|
|
) -> Result<f64, KclError> {
|
2024-06-24 14:45:07 -07:00
|
|
|
let path = sketch_group.get_path_by_tag(segment_name).ok_or_else(|| {
|
2023-08-25 13:41:04 -07:00
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
|
|
segment_name
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?;
|
2023-08-24 15:34:51 -07:00
|
|
|
let line = path.get_base();
|
|
|
|
|
|
|
|
let length = ((line.from[1] - line.to[1]).powi(2) + (line.from[0] - line.to[0]).powi(2)).sqrt();
|
|
|
|
|
|
|
|
let last_line = sketch_group
|
|
|
|
.value
|
|
|
|
.last()
|
|
|
|
.ok_or_else(|| {
|
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a SketchGroup with at least one segment, found `{:?}`",
|
|
|
|
sketch_group
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?
|
|
|
|
.get_base();
|
|
|
|
|
|
|
|
let diff = (to - last_line.to[0]).abs();
|
|
|
|
|
2024-03-21 14:14:32 +11:00
|
|
|
let angle_r = (diff / length).acos();
|
2023-08-24 15:34:51 -07:00
|
|
|
|
|
|
|
if diff > length {
|
2023-08-25 13:41:04 -07:00
|
|
|
Ok(0.0)
|
2023-08-24 15:34:51 -07:00
|
|
|
} else {
|
2023-09-13 22:25:41 -06:00
|
|
|
Ok(angle_r.to_degrees())
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the angle to match the given length for y.
|
2023-09-20 18:27:08 -07:00
|
|
|
pub async fn angle_to_match_length_y(args: Args) -> Result<MemoryItem, KclError> {
|
2023-08-24 15:34:51 -07:00
|
|
|
let (segment_name, to, sketch_group) = args.get_segment_name_to_number_sketch_group()?;
|
2023-09-20 18:27:08 -07:00
|
|
|
let result = inner_angle_to_match_length_y(&segment_name, to, sketch_group, args.clone())?;
|
2023-08-25 13:41:04 -07:00
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the angle to match the given length for y.
|
2024-03-13 12:56:46 -07:00
|
|
|
///
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
2024-05-14 17:10:47 -07:00
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
/// |> line([1, 2], %, 'seg01')
|
|
|
|
/// |> angledLine({
|
|
|
|
/// angle: angleToMatchLengthY('seg01', 15, %),
|
|
|
|
/// length: 5,
|
|
|
|
/// }, %)
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
/// |> close(%)
|
|
|
|
///
|
|
|
|
/// const extrusion = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
/// ```
|
2023-08-25 13:41:04 -07:00
|
|
|
#[stdlib {
|
|
|
|
name = "angleToMatchLengthY",
|
|
|
|
}]
|
|
|
|
fn inner_angle_to_match_length_y(
|
2024-06-24 14:45:07 -07:00
|
|
|
segment_name: &TagIdentifier,
|
2023-08-25 13:41:04 -07:00
|
|
|
to: f64,
|
2023-09-19 14:20:14 -07:00
|
|
|
sketch_group: Box<SketchGroup>,
|
2023-09-20 18:27:08 -07:00
|
|
|
args: Args,
|
2023-08-25 13:41:04 -07:00
|
|
|
) -> Result<f64, KclError> {
|
2024-06-24 14:45:07 -07:00
|
|
|
let path = sketch_group.get_path_by_tag(segment_name).ok_or_else(|| {
|
2023-08-25 13:41:04 -07:00
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a segment name that exists in the given SketchGroup, found `{}`",
|
|
|
|
segment_name
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?;
|
2023-08-24 15:34:51 -07:00
|
|
|
let line = path.get_base();
|
|
|
|
|
|
|
|
let length = ((line.from[1] - line.to[1]).powi(2) + (line.from[0] - line.to[0]).powi(2)).sqrt();
|
|
|
|
|
|
|
|
let last_line = sketch_group
|
|
|
|
.value
|
|
|
|
.last()
|
|
|
|
.ok_or_else(|| {
|
|
|
|
KclError::Type(KclErrorDetails {
|
|
|
|
message: format!(
|
|
|
|
"Expected a SketchGroup with at least one segment, found `{:?}`",
|
|
|
|
sketch_group
|
|
|
|
),
|
|
|
|
source_ranges: vec![args.source_range],
|
|
|
|
})
|
|
|
|
})?
|
|
|
|
.get_base();
|
|
|
|
|
|
|
|
let diff = (to - last_line.to[1]).abs();
|
|
|
|
|
2024-03-21 14:14:32 +11:00
|
|
|
let angle_r = (diff / length).asin();
|
2023-08-24 15:34:51 -07:00
|
|
|
|
|
|
|
if diff > length {
|
2023-08-25 13:41:04 -07:00
|
|
|
Ok(0.0)
|
2023-08-24 15:34:51 -07:00
|
|
|
} else {
|
2023-09-13 22:25:41 -06:00
|
|
|
Ok(angle_r.to_degrees())
|
2023-08-24 15:34:51 -07:00
|
|
|
}
|
|
|
|
}
|