Remove trig functions from prelude and change their unit handling (BREAKING) (#6565)
Remove trig functions from prelude and change their unit handling Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -116,6 +116,17 @@ impl TyF64 {
|
||||
angle.adjust_to(self.n, UnitAngle::Degrees).0
|
||||
}
|
||||
|
||||
pub fn to_radians(&self) -> f64 {
|
||||
let angle = match self.ty {
|
||||
NumericType::Default { angle, .. } => angle,
|
||||
NumericType::Known(UnitType::Angle(angle)) => angle,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert_ne!(angle, UnitAngle::Unknown);
|
||||
|
||||
angle.adjust_to(self.n, UnitAngle::Radians).0
|
||||
}
|
||||
pub fn count(n: f64) -> Self {
|
||||
Self {
|
||||
n,
|
||||
|
@ -140,19 +140,19 @@ pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
/// // Declare a function that sketches a decagon.
|
||||
/// fn decagon(radius) {
|
||||
/// // Each side of the decagon is turned this many radians from the previous angle.
|
||||
/// stepAngle = (1/10) * TAU
|
||||
/// stepAngle = ((1/10) * TAU): number(rad)
|
||||
///
|
||||
/// // Start the decagon sketch at this point.
|
||||
/// startOfDecagonSketch = startSketchOn('XY')
|
||||
/// |> startProfile(at = [(cos(0)*radius), (sin(0) * radius)])
|
||||
/// startOfDecagonSketch = startSketchOn(XY)
|
||||
/// |> startProfile(at = [(math::cos(0)*radius), (math::sin(0) * radius)])
|
||||
///
|
||||
/// // Use a `reduce` to draw the remaining decagon sides.
|
||||
/// // For each number in the array 1..10, run the given function,
|
||||
/// // which takes a partially-sketched decagon and adds one more edge to it.
|
||||
/// fullDecagon = reduce([1..10], initial = startOfDecagonSketch, f = fn(i, partialDecagon) {
|
||||
/// // Draw one edge of the decagon.
|
||||
/// x = cos(stepAngle * i) * radius
|
||||
/// y = sin(stepAngle * i) * radius
|
||||
/// x = math::cos(stepAngle * i) * radius
|
||||
/// y = math::sin(stepAngle * i) * radius
|
||||
/// return line(partialDecagon, end = [x, y])
|
||||
/// })
|
||||
///
|
||||
@ -163,15 +163,15 @@ pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
/// /*
|
||||
/// The `decagon` above is basically like this pseudo-code:
|
||||
/// fn decagon(radius):
|
||||
/// stepAngle = (1/10) * TAU
|
||||
/// plane = startSketchOn('XY')
|
||||
/// startOfDecagonSketch = startProfile(plane, at = [(cos(0)*radius), (sin(0) * radius)])
|
||||
/// stepAngle = ((1/10) * TAU): number(rad)
|
||||
/// plane = startSketchOn(XY)
|
||||
/// startOfDecagonSketch = startProfile(plane, at = [(math::cos(0)*radius), (math::sin(0) * radius)])
|
||||
///
|
||||
/// // Here's the reduce part.
|
||||
/// partialDecagon = startOfDecagonSketch
|
||||
/// for i in [1..10]:
|
||||
/// x = cos(stepAngle * i) * radius
|
||||
/// y = sin(stepAngle * i) * radius
|
||||
/// x = math::cos(stepAngle * i) * radius
|
||||
/// y = math::sin(stepAngle * i) * radius
|
||||
/// partialDecagon = line(partialDecagon, end = [x, y])
|
||||
/// fullDecagon = partialDecagon // it's now full
|
||||
/// return fullDecagon
|
||||
|
@ -6,7 +6,7 @@ use kcl_derive_docs::stdlib;
|
||||
use crate::{
|
||||
errors::KclError,
|
||||
execution::{
|
||||
types::{ArrayLen, NumericType, RuntimeType, UnitAngle, UnitType},
|
||||
types::{ArrayLen, NumericType, RuntimeType},
|
||||
ExecState, KclValue,
|
||||
},
|
||||
std::args::{Args, TyF64},
|
||||
@ -21,7 +21,7 @@ pub async fn rem(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
let (n, d, ty) = NumericType::combine_div(n, d);
|
||||
if ty == NumericType::Unknown {
|
||||
exec_state.warn(CompilationError::err(
|
||||
exec_state.err(CompilationError::err(
|
||||
args.source_range,
|
||||
"Calling `rem` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`"
|
||||
));
|
||||
@ -59,61 +59,21 @@ fn inner_rem(num: f64, divisor: f64) -> f64 {
|
||||
/// Compute the cosine of a number (in radians).
|
||||
pub async fn cos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
|
||||
let num = match num.ty {
|
||||
NumericType::Default {
|
||||
angle: UnitAngle::Degrees,
|
||||
..
|
||||
} => {
|
||||
exec_state.warn(CompilationError::err(
|
||||
args.source_range,
|
||||
"`cos` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `units::toRadians` to convert from degrees to radians",
|
||||
));
|
||||
num.n
|
||||
}
|
||||
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => num.n.to_radians(),
|
||||
_ => num.n,
|
||||
};
|
||||
|
||||
let num = num.to_radians();
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.cos())))
|
||||
}
|
||||
|
||||
/// Compute the sine of a number (in radians).
|
||||
pub async fn sin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
|
||||
let num = match num.ty {
|
||||
NumericType::Default {
|
||||
angle: UnitAngle::Degrees,
|
||||
..
|
||||
} => {
|
||||
exec_state.warn(CompilationError::err(
|
||||
args.source_range,
|
||||
"`sin` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `units::toRadians` to convert from degrees to radians",
|
||||
));
|
||||
num.n
|
||||
}
|
||||
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => num.n.to_radians(),
|
||||
_ => num.n,
|
||||
};
|
||||
let num = num.to_radians();
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.sin())))
|
||||
}
|
||||
|
||||
/// Compute the tangent of a number (in radians).
|
||||
pub async fn tan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
|
||||
let num = match num.ty {
|
||||
NumericType::Default {
|
||||
angle: UnitAngle::Degrees,
|
||||
..
|
||||
} => {
|
||||
exec_state.warn(CompilationError::err(
|
||||
args.source_range,
|
||||
"`tan` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `units::toRadians` to convert from degrees to radians",
|
||||
));
|
||||
num.n
|
||||
}
|
||||
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => num.n.to_radians(),
|
||||
_ => num.n,
|
||||
};
|
||||
let num = num.to_radians();
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.tan())))
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
|
||||
/// // Defines how to modify each layer of the vase.
|
||||
/// // Each replica is shifted up the Z axis, and has a smoothly-varying radius
|
||||
/// fn transform(replicaId) {
|
||||
/// scale = r * abs(1 - (t * replicaId)) * (5 + cos((replicaId / 8): number(rad)))
|
||||
/// scale = r * abs(1 - (t * replicaId)) * (5 + math::cos((replicaId / 8): number(rad)))
|
||||
/// return {
|
||||
/// translate = [0, 0, replicaId * 10],
|
||||
/// scale = [scale, scale, 0],
|
||||
|
Reference in New Issue
Block a user