added parabolic and hyperbolic curves
This commit is contained in:
@ -58,12 +58,14 @@ lazy_static! {
|
||||
Box::new(crate::std::segment::SegAng),
|
||||
Box::new(crate::std::segment::TangentToEnd),
|
||||
Box::new(crate::std::shapes::CircleThreePoint),
|
||||
Box::new(crate::std::shapes::Ellipse),
|
||||
// Box::new(crate::std::shapes::Ellipse),
|
||||
Box::new(crate::std::shapes::Polygon),
|
||||
Box::new(crate::std::sketch::Conic),
|
||||
Box::new(crate::std::sketch::EllipticalArc),
|
||||
Box::new(crate::std::sketch::Elliptic),
|
||||
Box::new(crate::std::sketch::Hyperbolic),
|
||||
Box::new(crate::std::sketch::InvoluteCircular),
|
||||
Box::new(crate::std::sketch::Line),
|
||||
Box::new(crate::std::sketch::Parabolic),
|
||||
Box::new(crate::std::sketch::XLine),
|
||||
Box::new(crate::std::sketch::YLine),
|
||||
Box::new(crate::std::sketch::AngledLine),
|
||||
@ -223,6 +225,10 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
||||
|e, a| Box::pin(crate::std::shapes::circle(e, a)),
|
||||
StdFnProps::default("std::sketch::circle"),
|
||||
),
|
||||
("sketch", "ellipse") => (
|
||||
|e, a| Box::pin(crate::std::shapes::ellipse(e, a)),
|
||||
StdFnProps::default("std::sketch::ellipse"),
|
||||
),
|
||||
("prelude", "helix") => (
|
||||
|e, a| Box::pin(crate::std::helix::helix(e, a)),
|
||||
StdFnProps::default("std::helix").include_in_feature_tree(),
|
||||
|
@ -495,25 +495,6 @@ pub async fn ellipse(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
})
|
||||
}
|
||||
|
||||
/// Construct an ellipse derived from center and major/minor axes.
|
||||
///
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn(XY)
|
||||
/// |> ellipse(center = [10,10], majorRadius = 5, minorRadius = 2)
|
||||
/// |> extrude(length = 5)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "ellipse",
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
sketch_surface_or_group = { docs = "Plane or surface to sketch on" },
|
||||
center = {docs = "The center of the ellipse."},
|
||||
major_radius = {docs = "The length along the x axis."},
|
||||
minor_radius = {docs = "The length along the y axis."},
|
||||
tag = {docs = "Identifier for the circle to reference elsewhere."},
|
||||
},
|
||||
tags = ["sketch"]
|
||||
}]
|
||||
async fn inner_ellipse(
|
||||
sketch_surface_or_group: SketchOrSurface,
|
||||
center: [TyF64; 2],
|
||||
|
@ -2413,7 +2413,7 @@ async fn inner_subtract_2d(
|
||||
}
|
||||
|
||||
/// Draw an elliptical arc.
|
||||
pub async fn elliptical_arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
pub async fn elliptic(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
|
||||
@ -2427,7 +2427,7 @@ pub async fn elliptical_arc(exec_state: &mut ExecState, args: Args) -> Result<Kc
|
||||
let interior_absolute: Option<[TyF64; 2]> =
|
||||
args.get_kw_arg_opt_typed("interiorAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let new_sketch = inner_elliptical_arc(
|
||||
let new_sketch = inner_elliptic(
|
||||
sketch,
|
||||
center,
|
||||
angle_start,
|
||||
@ -2449,7 +2449,7 @@ pub async fn elliptical_arc(exec_state: &mut ExecState, args: Args) -> Result<Kc
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn(XZ)
|
||||
/// |> startProfile(at = [0, 0])
|
||||
/// |> ellipticalArc(
|
||||
/// |> elliptic(
|
||||
/// endAbsolute = [10,0],
|
||||
/// interiorAbsolute = [5,5]
|
||||
/// )
|
||||
@ -2457,7 +2457,7 @@ pub async fn elliptical_arc(exec_state: &mut ExecState, args: Args) -> Result<Kc
|
||||
/// example = extrude(exampleSketch, length = 10)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "ellipticalArc",
|
||||
name = "elliptic",
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
sketch = { docs = "Which sketch should this path be added to?" },
|
||||
@ -2473,7 +2473,7 @@ pub async fn elliptical_arc(exec_state: &mut ExecState, args: Args) -> Result<Kc
|
||||
tags = ["sketch"]
|
||||
}]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn inner_elliptical_arc(
|
||||
pub(crate) async fn inner_elliptic(
|
||||
sketch: Sketch,
|
||||
center: [TyF64; 2],
|
||||
angle_start: TyF64,
|
||||
@ -2554,11 +2554,207 @@ pub(crate) async fn inner_elliptical_arc(
|
||||
Ok(new_sketch)
|
||||
}
|
||||
|
||||
pub async fn hyperbolic(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
|
||||
let semi_major: TyF64 = args.get_kw_arg_typed("semiMajor", &RuntimeType::length(), exec_state)?;
|
||||
let semi_minor: TyF64 = args.get_kw_arg_typed("semiMinor", &RuntimeType::length(), exec_state)?;
|
||||
let interior: [TyF64; 2] = args.get_kw_arg_typed("interior", &RuntimeType::point2d(), exec_state)?;
|
||||
let end: [TyF64; 2] = args.get_kw_arg_typed("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
|
||||
let new_sketch = inner_hyperbolic(sketch, semi_major, semi_minor, interior, end, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
value: Box::new(new_sketch),
|
||||
})
|
||||
}
|
||||
|
||||
/// Calculate the tangent of a hyperbolic given a point on the curve
|
||||
fn hyperbolic_tangent(point: Point2d, semi_major: f64, semi_minor: f64) -> [f64; 2] {
|
||||
(point.y * semi_major.powf(2.0), point.x * semi_minor.powf(2.0)).into()
|
||||
}
|
||||
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn(XY)
|
||||
/// |> startProfile(at = [0,0])
|
||||
/// |> hyperbolic(
|
||||
/// end = [10,0],
|
||||
/// semiMajor = 2,
|
||||
/// semiMinor = 1,
|
||||
/// interior = [0,0]
|
||||
/// )
|
||||
/// |>close()
|
||||
///```
|
||||
#[stdlib {
|
||||
name = "hyperbolic",
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
sketch = { docs = "Which sketch should this path be added to?" },
|
||||
semi_major = { docs = "The tangent of the conic at the start point (the end of the previous path segement)" },
|
||||
semi_minor = { docs = "The tangent of the conic at the end point" },
|
||||
interior = { docs = "Any point between the arc's start and end?" },
|
||||
end = { docs = "Where should this arc end?" },
|
||||
tag = { docs = "Create a new tag which refers to this line"},
|
||||
},
|
||||
tags = ["sketch"]
|
||||
}]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn inner_hyperbolic(sketch: Sketch, semi_major: TyF64, semi_minor: TyF64, interior: [TyF64; 2], end: [TyF64; 2], tag: Option<TagNode>, exec_state: &mut ExecState, args: Args
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
let id = exec_state.next_uuid();
|
||||
|
||||
let (interior, _) = untype_point(interior);
|
||||
let (end, _) = untype_point(end);
|
||||
let end_point = Point2d {
|
||||
x: end[0],
|
||||
y: end[1],
|
||||
units: from.units,
|
||||
};
|
||||
|
||||
let semi_major_u = semi_major.to_length_units(from.units);
|
||||
let semi_minor_u = semi_minor.to_length_units(from.units);
|
||||
|
||||
let start_tangent = hyperbolic_tangent(from, semi_major_u, semi_minor_u);
|
||||
let end_tangent = hyperbolic_tangent(end_point, semi_major_u, semi_minor_u);
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::ExtendPath {
|
||||
path: sketch.id.into(),
|
||||
segment: PathSegment::ConicTo {
|
||||
start_tangent: KPoint2d::from(untyped_point_to_mm(start_tangent, from.units)).map(LengthUnit),
|
||||
end_tangent: KPoint2d::from(untyped_point_to_mm(end_tangent, from.units)).map(LengthUnit),
|
||||
end: KPoint2d::from(untyped_point_to_mm(end, from.units)).map(LengthUnit),
|
||||
interior: KPoint2d::from(untyped_point_to_mm(interior, from.units)).map(LengthUnit),
|
||||
relative: false,
|
||||
},
|
||||
}),
|
||||
).await?;
|
||||
|
||||
let current_path = Path::Conic {
|
||||
base: BasePath {
|
||||
from: from.ignore_units(),
|
||||
to: end,
|
||||
tag: tag.clone(),
|
||||
units: sketch.units,
|
||||
geo_meta: GeoMeta {
|
||||
id,
|
||||
metadata: args.source_range.into(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let mut new_sketch = sketch.clone();
|
||||
if let Some(tag) = &tag {
|
||||
new_sketch.add_tag(tag, ¤t_path, exec_state);
|
||||
}
|
||||
|
||||
new_sketch.paths.push(current_path);
|
||||
|
||||
Ok(new_sketch)
|
||||
|
||||
}
|
||||
|
||||
pub async fn parabolic(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
|
||||
let coefficient: TyF64 = args.get_kw_arg_typed("coefficient", &RuntimeType::count(), exec_state)?;
|
||||
let interior: [TyF64; 2] = args.get_kw_arg_typed("interior", &RuntimeType::point2d(), exec_state)?;
|
||||
let end: [TyF64; 2] = args.get_kw_arg_typed("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
|
||||
let new_sketch = inner_parabolic(sketch, coefficient, interior, end, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
value: Box::new(new_sketch),
|
||||
})
|
||||
}
|
||||
|
||||
fn parabolic_tangent(point: Point2d, coefficient: f64) -> [f64; 2] {
|
||||
(1.0, 2.0 * coefficient * point.x).into()
|
||||
}
|
||||
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn(XY)
|
||||
/// |> startProfile(at = [0,0])
|
||||
/// |> parabolic(
|
||||
/// end = [10,0],
|
||||
/// coefficient = 2,
|
||||
/// interior = [0,0]
|
||||
/// )
|
||||
/// |>close()
|
||||
///```
|
||||
#[stdlib {
|
||||
name = "parabolic",
|
||||
unlabeled_first = true,
|
||||
args = {
|
||||
sketch = { docs = "Which sketch should this path be added to?" },
|
||||
coefficient = { docs = "The tangent of the conic at the end point" },
|
||||
interior = { docs = "Any point between the arc's start and end?" },
|
||||
end = { docs = "Where should this arc end?" },
|
||||
tag = { docs = "Create a new tag which refers to this line"},
|
||||
},
|
||||
tags = ["sketch"]
|
||||
}]
|
||||
pub(crate) async fn inner_parabolic(sketch: Sketch, coefficient: TyF64, interior: [TyF64; 2], end: [TyF64; 2], tag: Option<TagNode>, exec_state: &mut ExecState, args: Args
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from = sketch.current_pen_position()?;
|
||||
let id = exec_state.next_uuid();
|
||||
|
||||
let (interior, _) = untype_point(interior);
|
||||
let (end, _) = untype_point(end);
|
||||
let end_point = Point2d {
|
||||
x: end[0],
|
||||
y: end[1],
|
||||
units: from.units,
|
||||
};
|
||||
|
||||
let start_tangent = parabolic_tangent(from, coefficient.n);
|
||||
let end_tangent = parabolic_tangent(end_point, coefficient.n);
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::ExtendPath {
|
||||
path: sketch.id.into(),
|
||||
segment: PathSegment::ConicTo {
|
||||
start_tangent: KPoint2d::from(untyped_point_to_mm(start_tangent, from.units)).map(LengthUnit),
|
||||
end_tangent: KPoint2d::from(untyped_point_to_mm(end_tangent, from.units)).map(LengthUnit),
|
||||
end: KPoint2d::from(untyped_point_to_mm(end, from.units)).map(LengthUnit),
|
||||
interior: KPoint2d::from(untyped_point_to_mm(interior, from.units)).map(LengthUnit),
|
||||
relative: false,
|
||||
},
|
||||
}),
|
||||
).await?;
|
||||
|
||||
let current_path = Path::Conic {
|
||||
base: BasePath {
|
||||
from: from.ignore_units(),
|
||||
to: end,
|
||||
tag: tag.clone(),
|
||||
units: sketch.units,
|
||||
geo_meta: GeoMeta {
|
||||
id,
|
||||
metadata: args.source_range.into(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let mut new_sketch = sketch.clone();
|
||||
if let Some(tag) = &tag {
|
||||
new_sketch.add_tag(tag, ¤t_path, exec_state);
|
||||
}
|
||||
|
||||
new_sketch.paths.push(current_path);
|
||||
|
||||
Ok(new_sketch)
|
||||
|
||||
}
|
||||
|
||||
/// Draw a conic section
|
||||
pub async fn conic(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
|
||||
let start_tangent: [TyF64; 2] = args.get_kw_arg_typed("startTangent", &RuntimeType::point2d(), exec_state)?;
|
||||
let start_tangent: Option<[TyF64; 2]> = args.get_kw_arg_opt_typed("startTangent", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_tangent: [TyF64; 2] = args.get_kw_arg_typed("endTangent", &RuntimeType::point2d(), exec_state)?;
|
||||
let end: [TyF64; 2] = args.get_kw_arg_typed("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let interior: [TyF64; 2] = args.get_kw_arg_typed("interior", &RuntimeType::point2d(), exec_state)?;
|
||||
@ -2570,6 +2766,7 @@ pub async fn conic(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn(XZ)
|
||||
/// |> startProfile(at = [0, 0])
|
||||
@ -2596,15 +2793,22 @@ pub async fn conic(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
tags = ["sketch"]
|
||||
}]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn inner_conic(sketch: Sketch, start_tangent: [TyF64; 2], end: [TyF64; 2], end_tangent: [TyF64; 2], interior: [TyF64; 2], tag: Option<TagNode>, exec_state: &mut ExecState, args: Args
|
||||
pub(crate) async fn inner_conic(sketch: Sketch, start_tangent: Option<[TyF64; 2]>, end: [TyF64; 2], end_tangent: [TyF64; 2], interior: [TyF64; 2], tag: Option<TagNode>, exec_state: &mut ExecState, args: Args
|
||||
) -> Result<Sketch, KclError> {
|
||||
let from: Point2d = sketch.current_pen_position()?;
|
||||
let id = exec_state.next_uuid();
|
||||
let (start_tangent, _) = untype_point(start_tangent);
|
||||
let (end_tangent, _) = untype_point(end_tangent);
|
||||
let (end, _) = untype_point(end);
|
||||
let (interior, _) = untype_point(interior);
|
||||
|
||||
let (start_tangent, _) = if let Some(start_tangent) = start_tangent {
|
||||
untype_point(start_tangent)
|
||||
} else {
|
||||
let previous_point = sketch.get_tangential_info_from_paths().tan_previous_point(from.ignore_units());
|
||||
let from = from.ignore_units();
|
||||
([from[0] - previous_point[0], from[1] - previous_point[1]], NumericType::Any)
|
||||
};
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
id,
|
||||
ModelingCmd::from(mcmd::ExtendPath {
|
||||
|
Reference in New Issue
Block a user