Generate angle suffixes in the frontend
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
		
							
								
								
									
										1
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -2495,6 +2495,7 @@ | ||||
|     }, | ||||
|     "node_modules/@clack/prompts/node_modules/is-unicode-supported": { | ||||
|       "version": "1.3.0", | ||||
|       "extraneous": true, | ||||
|       "inBundle": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|  | ||||
| @ -231,10 +231,9 @@ impl Program { | ||||
|     pub fn change_default_units( | ||||
|         &self, | ||||
|         length_units: Option<execution::types::UnitLen>, | ||||
|         angle_units: Option<execution::types::UnitAngle>, | ||||
|     ) -> Result<Self, KclError> { | ||||
|         Ok(Self { | ||||
|             ast: self.ast.change_default_units(length_units, angle_units)?, | ||||
|             ast: self.ast.change_default_units(length_units)?, | ||||
|             original_file_contents: self.original_file_contents.clone(), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @ -28,7 +28,7 @@ use crate::{ | ||||
|     errors::KclError, | ||||
|     execution::{ | ||||
|         annotations, | ||||
|         types::{ArrayLen, UnitAngle, UnitLen}, | ||||
|         types::{ArrayLen, UnitLen}, | ||||
|         KclValue, Metadata, TagIdentifier, | ||||
|     }, | ||||
|     parsing::{ast::digest::Digest, token::NumericSuffix, PIPE_OPERATOR}, | ||||
| @ -360,7 +360,6 @@ impl Node<Program> { | ||||
|     pub fn change_default_units( | ||||
|         &self, | ||||
|         length_units: Option<UnitLen>, | ||||
|         angle_units: Option<UnitAngle>, | ||||
|     ) -> Result<Self, KclError> { | ||||
|         let mut new_program = self.clone(); | ||||
|         let mut found = false; | ||||
| @ -372,13 +371,6 @@ impl Node<Program> { | ||||
|                         Expr::Name(Box::new(Name::new(&len.to_string()))), | ||||
|                     ); | ||||
|                 } | ||||
|                 if let Some(angle) = angle_units { | ||||
|                     node.inner.add_or_update( | ||||
|                         annotations::SETTINGS_UNIT_ANGLE, | ||||
|                         Expr::Name(Box::new(Name::new(&angle.to_string()))), | ||||
|                     ); | ||||
|                 } | ||||
|  | ||||
|                 // Previous source range no longer makes sense, but we want to | ||||
|                 // preserve other things like comments. | ||||
|                 node.reset_source(); | ||||
| @ -395,12 +387,6 @@ impl Node<Program> { | ||||
|                     Expr::Name(Box::new(Name::new(&len.to_string()))), | ||||
|                 ); | ||||
|             } | ||||
|             if let Some(angle) = angle_units { | ||||
|                 settings.inner.add_or_update( | ||||
|                     annotations::SETTINGS_UNIT_ANGLE, | ||||
|                     Expr::Name(Box::new(Name::new(&angle.to_string()))), | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             new_program.inner_attrs.push(settings); | ||||
|         } | ||||
| @ -4256,7 +4242,7 @@ startSketchOn(XY)"#; | ||||
|  | ||||
|         // Edit the ast. | ||||
|         let new_program = program | ||||
|             .change_default_units(Some(crate::execution::types::UnitLen::Mm), None) | ||||
|             .change_default_units(Some(crate::execution::types::UnitLen::Mm)) | ||||
|             .unwrap(); | ||||
|  | ||||
|         let result = new_program.meta_settings().unwrap(); | ||||
| @ -4285,7 +4271,7 @@ startSketchOn(XY) | ||||
|  | ||||
|         // Edit the ast. | ||||
|         let new_program = program | ||||
|             .change_default_units(Some(crate::execution::types::UnitLen::Mm), None) | ||||
|             .change_default_units(Some(crate::execution::types::UnitLen::Mm)) | ||||
|             .unwrap(); | ||||
|  | ||||
|         let result = new_program.meta_settings().unwrap(); | ||||
| @ -4320,7 +4306,7 @@ startSketchOn(XY) | ||||
|         let program = crate::parsing::top_level_parse(code).unwrap(); | ||||
|  | ||||
|         let new_program = program | ||||
|             .change_default_units(Some(crate::execution::types::UnitLen::Cm), None) | ||||
|             .change_default_units(Some(crate::execution::types::UnitLen::Cm)) | ||||
|             .unwrap(); | ||||
|  | ||||
|         let result = new_program.meta_settings().unwrap(); | ||||
|  | ||||
| @ -289,14 +289,13 @@ pub fn kcl_settings(program_json: &str) -> Result<JsValue, String> { | ||||
|  | ||||
| /// Takes a kcl string and Meta settings and changes the meta settings in the kcl string. | ||||
| #[wasm_bindgen] | ||||
| pub fn change_default_units(code: &str, len_str: &str, angle_str: &str) -> Result<String, String> { | ||||
| pub fn change_default_units(code: &str, len_str: &str) -> Result<String, String> { | ||||
|     console_error_panic_hook::set_once(); | ||||
|  | ||||
|     let len: Option<kcl_lib::UnitLen> = serde_json::from_str(len_str).map_err(|e| e.to_string())?; | ||||
|     let angle: Option<kcl_lib::UnitAngle> = serde_json::from_str(angle_str).map_err(|e| e.to_string())?; | ||||
|     let program = Program::parse_no_errs(code).map_err(|e| e.to_string())?; | ||||
|  | ||||
|     let new_program = program.change_default_units(len, angle).map_err(|e| e.to_string())?; | ||||
|     let new_program = program.change_default_units(len).map_err(|e| e.to_string())?; | ||||
|  | ||||
|     let formatted = new_program.recast(); | ||||
|  | ||||
|  | ||||
| @ -22,7 +22,7 @@ type ModalResolve = { | ||||
| type ModalReject = boolean | ||||
|  | ||||
| type SetAngleLengthModalProps = InstanceProps<ModalResolve, ModalReject> & { | ||||
|   value: number | ||||
|   value: string | ||||
|   valueName: string | ||||
|   shouldCreateVariable?: boolean | ||||
| } | ||||
| @ -41,8 +41,10 @@ export const SetAngleLengthModal = ({ | ||||
|   valueName, | ||||
|   shouldCreateVariable: initialShouldCreateVariable = false, | ||||
| }: SetAngleLengthModalProps) => { | ||||
|   const [sign, setSign] = useState(Math.sign(Number(initialValue))) | ||||
|   const [value, setValue] = useState(String(initialValue * sign)) | ||||
|   const [sign, setSign] = useState(initialValue.startsWith('-') ? -1 : 1) | ||||
|   const [value, setValue] = useState( | ||||
|     initialValue.startsWith('-') ? initialValue.substring(1) : initialValue | ||||
|   ) | ||||
|   const [shouldCreateVariable, setShouldCreateVariable] = useState( | ||||
|     initialShouldCreateVariable | ||||
|   ) | ||||
|  | ||||
| @ -25,7 +25,7 @@ type ModalReject = boolean | ||||
| type GetInfoModalProps = InstanceProps<ModalResolve, ModalReject> & { | ||||
|   segName: string | ||||
|   isSegNameEditable: boolean | ||||
|   value?: number | ||||
|   value?: string | ||||
|   initialVariableName: string | ||||
| } | ||||
|  | ||||
| @ -44,10 +44,12 @@ export const GetInfoModal = ({ | ||||
|   value: initialValue, | ||||
|   initialVariableName, | ||||
| }: GetInfoModalProps) => { | ||||
|   const [sign, setSign] = useState(Math.sign(Number(initialValue))) | ||||
|   const [sign, setSign] = useState(initialValue?.startsWith('-') ? -1 : 1) | ||||
|   const [segName, setSegName] = useState(initialSegName) | ||||
|   const [value, setValue] = useState( | ||||
|     initialValue === undefined ? '' : String(Math.abs(initialValue)) | ||||
|     initialValue?.startsWith('-') | ||||
|       ? initialValue.substring(1) | ||||
|       : initialValue || '' | ||||
|   ) | ||||
|   const [shouldCreateVariable, setShouldCreateVariable] = useState(false) | ||||
|  | ||||
|  | ||||
| @ -171,7 +171,7 @@ export async function applyConstraintIntersect({ | ||||
|   if ( | ||||
|     !variableName && | ||||
|     segName === tagInfo?.tag && | ||||
|     Number(value) === valueUsedInTransform | ||||
|     value === valueUsedInTransform | ||||
|   ) { | ||||
|     return { | ||||
|       modifiedAst, | ||||
|  | ||||
| @ -108,7 +108,7 @@ export async function applyConstraintAbsDistance({ | ||||
|   if (err(transform1)) return Promise.reject(transform1) | ||||
|   const { valueUsedInTransform } = transform1 | ||||
|  | ||||
|   let forceVal = valueUsedInTransform || 0 | ||||
|   let forceVal = valueUsedInTransform || '' | ||||
|   const { valueNode, variableName, newVariableInsertIndex, sign } = | ||||
|     await getModalInfo({ | ||||
|       value: forceVal, | ||||
|  | ||||
| @ -120,7 +120,7 @@ export async function applyConstraintAngleBetween({ | ||||
|   } as any) | ||||
|   if ( | ||||
|     segName === tagInfo?.tag && | ||||
|     Number(value) === valueUsedInTransform && | ||||
|     value === valueUsedInTransform && | ||||
|     !variableName | ||||
|   ) { | ||||
|     return { | ||||
|  | ||||
| @ -127,7 +127,7 @@ export async function applyConstraintHorzVertDistance({ | ||||
|   if ( | ||||
|     !variableName && | ||||
|     segName === tagInfo?.tag && | ||||
|     Number(value) === valueUsedInTransform | ||||
|     value === valueUsedInTransform | ||||
|   ) { | ||||
|     return { | ||||
|       modifiedAst, | ||||
|  | ||||
| @ -122,25 +122,36 @@ export async function applyConstraintAngleLength({ | ||||
|   const isReferencingXAxisAngle = | ||||
|     isReferencingXAxis && angleOrLength === 'setAngle' | ||||
|  | ||||
|   let forceVal = valueUsedInTransform || 0 | ||||
|   let forceVal = valueUsedInTransform || '' | ||||
|   // TODO it would be better to preserve the units, but its an edge case for now. | ||||
|   let degrees | ||||
|   if (forceVal.endsWith('rad')) { | ||||
|     degrees = | ||||
|       Number(forceVal.substring(0, forceVal.length - 3)) * (180 / Math.PI) | ||||
|   } else { | ||||
|     if (forceVal.endsWith('deg')) { | ||||
|       forceVal = forceVal.substring(0, forceVal.length - 3) | ||||
|     } | ||||
|     degrees = Number(forceVal) | ||||
|   } | ||||
|  | ||||
|   let calcIdentifier = createName(['turns'], 'ZERO') | ||||
|   if (isReferencingYAxisAngle) { | ||||
|     calcIdentifier = createName( | ||||
|       ['turns'], | ||||
|       forceVal < 0 ? 'THREE_QUARTER_TURN' : 'QUARTER_TURN' | ||||
|       degrees < 0 ? 'THREE_QUARTER_TURN' : 'QUARTER_TURN' | ||||
|     ) | ||||
|     forceVal = normaliseAngle(forceVal + (forceVal < 0 ? 90 : -90)) | ||||
|     degrees = normaliseAngle(degrees + (degrees < 0 ? 90 : -90)) | ||||
|   } else if (isReferencingXAxisAngle) { | ||||
|     calcIdentifier = createName( | ||||
|       ['turns'], | ||||
|       Math.abs(forceVal) > 90 ? 'HALF_TURN' : 'ZERO' | ||||
|       Math.abs(degrees) > 90 ? 'HALF_TURN' : 'ZERO' | ||||
|     ) | ||||
|     forceVal = | ||||
|       Math.abs(forceVal) > 90 ? normaliseAngle(forceVal - 180) : forceVal | ||||
|     degrees = Math.abs(degrees) > 90 ? normaliseAngle(degrees - 180) : forceVal | ||||
|   } | ||||
|   const { valueNode, variableName, newVariableInsertIndex, sign } = | ||||
|     await getModalInfo({ | ||||
|       value: forceVal, | ||||
|       value: String(degrees) + 'deg', | ||||
|       valueName: angleOrLength === 'setAngle' ? 'angle' : 'length', | ||||
|       shouldCreateVariable: true, | ||||
|     }) | ||||
|  | ||||
| @ -2,11 +2,7 @@ import { Popover } from '@headlessui/react' | ||||
| import { useEffect, useState } from 'react' | ||||
| import toast from 'react-hot-toast' | ||||
|  | ||||
| import { | ||||
|   changeDefaultUnits, | ||||
|   unitAngleToUnitAng, | ||||
|   unitLengthToUnitLen, | ||||
| } from '@src/lang/wasm' | ||||
| import { changeDefaultUnits, unitLengthToUnitLen } from '@src/lang/wasm' | ||||
| import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants' | ||||
| import { baseUnitLabels, baseUnitsUnion } from '@src/lib/settings/settingsTypes' | ||||
| import { codeManager, kclManager } from '@src/lib/singletons' | ||||
| @ -48,8 +44,7 @@ export function UnitsMenu() { | ||||
|                     onClick={() => { | ||||
|                       const newCode = changeDefaultUnits( | ||||
|                         codeManager.code, | ||||
|                         unitLengthToUnitLen(unit), | ||||
|                         unitAngleToUnitAng(undefined) | ||||
|                         unitLengthToUnitLen(unit) | ||||
|                       ) | ||||
|                       if (err(newCode)) { | ||||
|                         toast.error( | ||||
|  | ||||
| @ -20,7 +20,7 @@ import type { | ||||
|   Identifier, | ||||
|   LabeledArg, | ||||
|   Literal, | ||||
|   LiteralValue, | ||||
|   NumericSuffix, | ||||
|   ObjectExpression, | ||||
|   PathToNode, | ||||
|   PipeExpression, | ||||
| @ -31,60 +31,77 @@ import type { | ||||
|   VariableDeclaration, | ||||
|   VariableDeclarator, | ||||
| } from '@src/lang/wasm' | ||||
| import { formatNumberLiteral } from '@src/lang/wasm' | ||||
| import { err } from '@src/lib/trap' | ||||
|  | ||||
| export function createLiteral(value: number | string | boolean): Node<Literal> { | ||||
| export function createLiteral( | ||||
|   value: number | string | boolean, | ||||
|   suffix?: NumericSuffix | ||||
| ): Node<Literal> { | ||||
|   // TODO: Should we handle string escape sequences? | ||||
|   return { | ||||
|     type: 'Literal', | ||||
|     start: 0, | ||||
|     end: 0, | ||||
|     moduleId: 0, | ||||
|     value: typeof value === 'number' ? { value, suffix: 'None' } : value, | ||||
|     raw: `${value}`, | ||||
|     value: | ||||
|       typeof value === 'number' | ||||
|         ? { value, suffix: suffix ? suffix : 'None' } | ||||
|         : value, | ||||
|     raw: createRawStr(value, suffix), | ||||
|     outerAttrs: [], | ||||
|     preComments: [], | ||||
|     commentStart: 0, | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Note: This depends on WASM, but it's not async.  Callers are responsible for | ||||
|  * awaiting init of the WASM module. | ||||
|  */ | ||||
| export function createLiteralMaybeSuffix( | ||||
|   value: LiteralValue | ||||
| ): Node<Literal> | Error { | ||||
|   if (typeof value === 'string' || typeof value === 'boolean') { | ||||
|     return createLiteral(value) | ||||
| function createRawStr( | ||||
|   value: number | string | boolean, | ||||
|   suffix?: NumericSuffix | ||||
| ): string { | ||||
|   if (typeof value !== 'number' || !suffix) { | ||||
|     return `${value}` | ||||
|   } | ||||
|  | ||||
|   let raw: string | ||||
|   if (typeof value.value === 'number' && value.suffix === 'None') { | ||||
|     // Fast path for numbers when there are no units. | ||||
|     raw = `${value.value}` | ||||
|   } else { | ||||
|     const formatted = formatNumberLiteral(value.value, value.suffix) | ||||
|     if (err(formatted)) { | ||||
|       return new Error( | ||||
|         `Invalid number literal: value=${value.value}, suffix=${value.suffix}`, | ||||
|         { cause: formatted } | ||||
|       ) | ||||
|     } | ||||
|     raw = formatted | ||||
|   } | ||||
|   return { | ||||
|     type: 'Literal', | ||||
|     start: 0, | ||||
|     end: 0, | ||||
|     moduleId: 0, | ||||
|     value, | ||||
|     raw, | ||||
|     outerAttrs: [], | ||||
|     preComments: [], | ||||
|     commentStart: 0, | ||||
|   let sufStr | ||||
|   switch (suffix) { | ||||
|     case 'None': | ||||
|     case 'Length': | ||||
|     case 'Angle': | ||||
|       sufStr = '' | ||||
|       break | ||||
|     case 'Count': | ||||
|       sufStr = '_' | ||||
|       break | ||||
|     case 'Mm': | ||||
|       sufStr = 'mm' | ||||
|       break | ||||
|     case 'Cm': | ||||
|       sufStr = 'cm' | ||||
|       break | ||||
|     case 'M': | ||||
|       sufStr = 'm' | ||||
|       break | ||||
|     case 'Inch': | ||||
|       sufStr = 'in' | ||||
|       break | ||||
|     case 'Ft': | ||||
|       sufStr = 'ft' | ||||
|       break | ||||
|     case 'Yd': | ||||
|       sufStr = 'yd' | ||||
|       break | ||||
|     case 'Deg': | ||||
|       sufStr = 'deg' | ||||
|       break | ||||
|     case 'Rad': | ||||
|       sufStr = 'rad' | ||||
|       break | ||||
|     case 'Unknown': | ||||
|       sufStr = '_?' | ||||
|       break | ||||
|   } | ||||
|  | ||||
|   return `${value}${sufStr}` | ||||
| } | ||||
|  | ||||
| export function createTagDeclarator(value: string): Node<TagDeclarator> { | ||||
|  | ||||
| @ -4,7 +4,6 @@ import { | ||||
|   createArrayExpression, | ||||
|   createIdentifier, | ||||
|   createLiteral, | ||||
|   createLiteralMaybeSuffix, | ||||
|   createObjectExpression, | ||||
|   createPipeExpression, | ||||
|   createPipeSubstitution, | ||||
| @ -24,13 +23,12 @@ import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils' | ||||
| import type { Artifact } from '@src/lang/std/artifactGraph' | ||||
| import { codeRefFromRange } from '@src/lang/std/artifactGraph' | ||||
| import { topLevelRange } from '@src/lang/util' | ||||
| import type { Identifier, Literal, LiteralValue } from '@src/lang/wasm' | ||||
| import type { Identifier, Literal } from '@src/lang/wasm' | ||||
| import { assertParse, recast } from '@src/lang/wasm' | ||||
| import { initPromise } from '@src/lang/wasmUtils' | ||||
| import { enginelessExecutor } from '@src/lib/testHelpers' | ||||
| import { err } from '@src/lib/trap' | ||||
| import { deleteFromSelection } from '@src/lang/modifyAst/deleteFromSelection' | ||||
| import { assertNotErr } from '@src/unitTestUtils' | ||||
|  | ||||
| beforeAll(async () => { | ||||
|   await initPromise | ||||
| @ -45,9 +43,7 @@ describe('Testing createLiteral', () => { | ||||
|     expect((result as Literal).raw).toBe('5') | ||||
|   }) | ||||
|   it('should create a literal number with units', () => { | ||||
|     const lit: LiteralValue = { value: 5, suffix: 'Mm' } | ||||
|     const result = createLiteralMaybeSuffix(lit) | ||||
|     assertNotErr(result) | ||||
|     const result = createLiteral(5, 'Mm') | ||||
|     expect(result.type).toBe('Literal') | ||||
|     expect((result as any).value.value).toBe(5) | ||||
|     expect((result as any).value.suffix).toBe('Mm') | ||||
| @ -305,24 +301,24 @@ describe('Testing moveValueIntoNewVariable', () => { | ||||
| ` | ||||
|   const code = `${fn('def')}${fn('jkl')}${fn('hmm')} | ||||
| fn ghi(@x) { | ||||
|     return 2 | ||||
|     return 2deg | ||||
| } | ||||
| abc = 3 | ||||
| abc = 3deg | ||||
| identifierGuy = 5 | ||||
| yo = 5 + 6 | ||||
| yo = 5deg + 6deg | ||||
| part001 = startSketchOn(XY) | ||||
| |> startProfile(at = [-1.2, 4.83]) | ||||
| |> line(end = [2.8, 0]) | ||||
| |> angledLine(angle = 100 + 100, length = 3.09) | ||||
| |> angledLine(angle = 100deg + 100deg, length = 3.09) | ||||
| |> angledLine(angle = abc, length = 3.09) | ||||
| |> angledLine(angle = def(yo), length = 3.09) | ||||
| |> angledLine(angle = ghi(%), length = 3.09) | ||||
| |> angledLine(angle = jkl(yo) + 2, length = 3.09) | ||||
| |> angledLine(angle = jkl(yo) + 2deg, length = 3.09) | ||||
| yo2 = hmm([identifierGuy + 5])` | ||||
|   it('should move a binary expression into a new variable', async () => { | ||||
|     const ast = assertParse(code) | ||||
|     const execState = await enginelessExecutor(ast) | ||||
|     const startIndex = code.indexOf('100 + 100') + 1 | ||||
|     const startIndex = code.indexOf('100deg + 100deg') + 1 | ||||
|     const { modifiedAst } = moveValueIntoNewVariable( | ||||
|       ast, | ||||
|       execState.variables, | ||||
| @ -330,7 +326,7 @@ yo2 = hmm([identifierGuy + 5])` | ||||
|       'newVar' | ||||
|     ) | ||||
|     const newCode = recast(modifiedAst) | ||||
|     expect(newCode).toContain(`newVar = 100 + 100`) | ||||
|     expect(newCode).toContain(`newVar = 100deg + 100deg`) | ||||
|     expect(newCode).toContain(`angledLine(angle = newVar, length = 3.09)`) | ||||
|   }) | ||||
|   it('should move a value into a new variable', async () => { | ||||
| @ -372,7 +368,7 @@ yo2 = hmm([identifierGuy + 5])` | ||||
|       'newVar' | ||||
|     ) | ||||
|     const newCode = recast(modifiedAst) | ||||
|     expect(newCode).toContain(`newVar = jkl(yo) + 2`) | ||||
|     expect(newCode).toContain(`newVar = jkl(yo) + 2deg`) | ||||
|     expect(newCode).toContain(`angledLine(angle = newVar, length = 3.09)`) | ||||
|   }) | ||||
|   it('should move a identifier into a new variable', async () => { | ||||
| @ -587,7 +583,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => { | ||||
|     ) => `part001 = startSketchOn(-XZ) | ||||
|   |> startProfile(at = [54.78, -95.91]) | ||||
|   |> line(end = [306.21, 198.82], tag = $b) | ||||
| ${!replace1 ? `  |> ${line}\n` : ''}  |> angledLine(angle = -65, length = ${ | ||||
| ${!replace1 ? `  |> ${line}\n` : ''}  |> angledLine(angle = -65deg, length = ${ | ||||
|       !replace1 ? 'segLen(a)' : replace1 | ||||
|     }) | ||||
|   |> line(end = [306.21, 198.87]) | ||||
| @ -595,45 +591,49 @@ ${!replace1 ? `  |> ${line}\n` : ''}  |> angledLine(angle = -65, length = ${ | ||||
|   |> line(end = [-963.39, -154.67]) | ||||
| ` | ||||
|     test.each([ | ||||
|       ['line', 'line(end = [306.21, 198.85], tag = $a)', ['365.11', '33']], | ||||
|       ['line', 'line(end = [306.21, 198.85], tag = $a)', ['365.11', '33deg']], | ||||
|       [ | ||||
|         'lineTo', | ||||
|         'line(endAbsolute = [306.21, 198.85], tag = $a)', | ||||
|         ['110.48', '120'], | ||||
|         ['110.48', '120deg'], | ||||
|       ], | ||||
|       ['yLine', 'yLine(length = 198.85, tag = $a)', ['198.85', '90']], | ||||
|       ['xLine', 'xLine(length = 198.85, tag = $a)', ['198.85', '0']], | ||||
|       ['yLineTo', 'yLine(endAbsolute = 198.85, tag = $a)', ['95.94', '90']], | ||||
|       ['xLineTo', 'xLine(endAbsolute = 198.85, tag = $a)', ['162.14', '180']], | ||||
|       ['yLine', 'yLine(length = 198.85, tag = $a)', ['198.85', '90deg']], | ||||
|       ['xLine', 'xLine(length = 198.85, tag = $a)', ['198.85', '0deg']], | ||||
|       ['yLineTo', 'yLine(endAbsolute = 198.85, tag = $a)', ['95.94', '90deg']], | ||||
|       [ | ||||
|         'angledLine', | ||||
|         'angledLine(angle = 45.5, length = 198.85, tag = $a)', | ||||
|         ['198.85', '46'], | ||||
|         'xLineTo', | ||||
|         'xLine(endAbsolute = 198.85, tag = $a)', | ||||
|         ['162.14', '180deg'], | ||||
|       ], | ||||
|       [ | ||||
|         'angledLine', | ||||
|         'angledLine(angle = 45.5, lengthX = 198.85, tag = $a)', | ||||
|         ['283.7', '46'], | ||||
|         'angledLine(angle = 45.5deg, length = 198.85, tag = $a)', | ||||
|         ['198.85', '46deg'], | ||||
|       ], | ||||
|       [ | ||||
|         'angledLine', | ||||
|         'angledLine(angle = 45.5, lengthY = 198.85, tag = $a)', | ||||
|         ['278.79', '46'], | ||||
|         'angledLine(angle = 45.5deg, lengthX = 198.85, tag = $a)', | ||||
|         ['283.7', '46deg'], | ||||
|       ], | ||||
|       [ | ||||
|         'angledLine', | ||||
|         'angledLine(angle = 45.5, endAbsoluteX = 198.85, tag = $a)', | ||||
|         ['231.33', '-134'], | ||||
|         'angledLine(angle = 45.5deg, lengthY = 198.85, tag = $a)', | ||||
|         ['278.79', '46deg'], | ||||
|       ], | ||||
|       [ | ||||
|         'angledLine', | ||||
|         'angledLine(angle = 45.5, endAbsoluteY = 198.85, tag = $a)', | ||||
|         ['134.51', '46'], | ||||
|         'angledLine(angle = 45.5deg, endAbsoluteX = 198.85, tag = $a)', | ||||
|         ['231.33', '-134deg'], | ||||
|       ], | ||||
|       [ | ||||
|         'angledLine', | ||||
|         'angledLine(angle = 45.5deg, endAbsoluteY = 198.85, tag = $a)', | ||||
|         ['134.51', '46deg'], | ||||
|       ], | ||||
|       [ | ||||
|         'angledLineThatIntersects', | ||||
|         `angledLineThatIntersects(angle = 45.5, intersectTag = b, offset = 198.85, tag = $a)`, | ||||
|         ['918.4', '46'], | ||||
|         `angledLineThatIntersects(angle = 45.5deg, intersectTag = b, offset = 198.85, tag = $a)`, | ||||
|         ['918.4', '46deg'], | ||||
|       ], | ||||
|     ])(`%s`, async (_, line, [replace1, replace2]) => { | ||||
|       const code = makeCode(line) | ||||
| @ -724,7 +724,7 @@ sketch003 = startSketchOn(XZ) | ||||
|     //   |> startProfile(at = [-12.55, 2.89]) | ||||
|     //   |> line(end = [3.02, 1.9]) | ||||
|     //   |> line(end = [1.82, -1.49], tag = $seg02) | ||||
|     //   |> angledLine(angle = -86, length = segLen(seg02)) | ||||
|     //   |> angledLine(angle = -86deg, length = segLen(seg02)) | ||||
|     //   |> line(end = [-3.97, -0.53]) | ||||
|     //   |> line(end = [0.3, 0.84]) | ||||
|     //   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
| @ -749,7 +749,7 @@ sketch003 = startSketchOn(XZ) | ||||
|     //   |> startProfile(at = [-12.55, 2.89]) | ||||
|     //   |> line(end = [3.02, 1.9]) | ||||
|     //   |> line(end = [1.82, -1.49], tag = $seg02) | ||||
|     //   |> angledLine(angle = -86, length = segLen(seg02)) | ||||
|     //   |> angledLine(angle = -86deg, length = segLen(seg02)) | ||||
|     //   |> line(end = [-3.97, -0.53]) | ||||
|     //   |> line(end = [0.3, 0.84]) | ||||
|     //   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
| @ -778,7 +778,7 @@ sketch003 = startSketchOn(XZ) | ||||
|     //   |> startProfile(at = [-12.55, 2.89]) | ||||
|     //   |> line(end = [3.02, 1.9]) | ||||
|     //   |> line(end = [1.82, -1.49], tag = $seg02) | ||||
|     //   |> angledLine(angle = -86, length = segLen(seg02)) | ||||
|     //   |> angledLine(angle = -86deg, length = segLen(seg02)) | ||||
|     //   |> line(end = [-3.97, -0.53]) | ||||
|     //   |> line(end = [0.3, 0.84]) | ||||
|     //   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
| @ -803,7 +803,7 @@ sketch003 = startSketchOn(XZ) | ||||
|     //   |> startProfile(at = [-12.55, 2.89]) | ||||
|     //   |> line(end = [3.02, 1.9]) | ||||
|     //   |> line(end = [1.82, -1.49], tag = $seg02) | ||||
|     //   |> angledLine(angle = -86, length = segLen(seg02)) | ||||
|     //   |> angledLine(angle = -86deg, length = segLen(seg02)) | ||||
|     //   |> line(end = [-3.97, -0.53]) | ||||
|     //   |> line(end = [0.3, 0.84]) | ||||
|     //   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|  | ||||
| @ -1,10 +1,6 @@ | ||||
| import type { UnitLength } from '@rust/kcl-lib/bindings/ModelingCmd' | ||||
|  | ||||
| import { | ||||
|   changeDefaultUnits, | ||||
|   unitAngleToUnitAng, | ||||
|   unitLengthToUnitLen, | ||||
| } from '@src/lang/wasm' | ||||
| import { changeDefaultUnits, unitLengthToUnitLen } from '@src/lang/wasm' | ||||
| import { DEFAULT_DEFAULT_LENGTH_UNIT } from '@src/lib/constants' | ||||
|  | ||||
| /** | ||||
| @ -26,9 +22,5 @@ export function newKclFile( | ||||
|     return '' | ||||
|   } | ||||
|  | ||||
|   return changeDefaultUnits( | ||||
|     '', | ||||
|     unitLengthToUnitLen(defaultLengthUnit), | ||||
|     unitAngleToUnitAng(undefined) | ||||
|   ) | ||||
|   return changeDefaultUnits('', unitLengthToUnitLen(defaultLengthUnit)) | ||||
| } | ||||
|  | ||||
| @ -204,7 +204,7 @@ describe('testing addTagForSketchOnFace', () => { | ||||
|       const genCode = (insertCode: string) => `sketch001 = startSketchOn(XZ) | ||||
|   |> startProfile(at = [75.8, 317.2]) // [$startCapTag, $EndCapTag] | ||||
|   |> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 217.26, tag = $seg01) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) - 90deg, length = 217.26, tag = $seg01) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001)) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02) | ||||
|   |> close() | ||||
| @ -281,18 +281,18 @@ describe('testing getConstraintInfo', () => { | ||||
|     const code = `part001 = startSketchOn(-XZ) | ||||
|   |> startProfile(at = [0,0]) | ||||
|   |> line(end = [3, 4]) | ||||
|   |> angledLine(angle = 3.14, length = 3.14) | ||||
|   |> angledLine(angle = 3.14deg, length = 3.14) | ||||
|   |> line(endAbsolute = [6.14, 3.14]) | ||||
|   |> xLine(endAbsolute = 8) | ||||
|   |> yLine(endAbsolute = 5) | ||||
|   |> yLine(length = 3.14, tag = $a) | ||||
|   |> xLine(length = 3.14) | ||||
|   |> angledLine(angle = 3.14, lengthX = 3.14) | ||||
|   |> angledLine(angle = 30, lengthY = 3) | ||||
|   |> angledLine(angle = 12.14, endAbsoluteX = 12) | ||||
|   |> angledLine(angle = 30, endAbsoluteY = 10.14) | ||||
|   |> angledLine(angle = 3.14deg, lengthX = 3.14) | ||||
|   |> angledLine(angle = 30deg, lengthY = 3) | ||||
|   |> angledLine(angle = 12.14deg, endAbsoluteX = 12) | ||||
|   |> angledLine(angle = 30deg, endAbsoluteY = 10.14) | ||||
|   |> angledLineThatIntersects( | ||||
|     angle = 3.14, | ||||
|     angle = 3.14deg, | ||||
|     intersectTag = a, | ||||
|     offset = 0, | ||||
|   ) | ||||
| @ -327,7 +327,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '3.14', | ||||
|             value: '3.14deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -473,7 +473,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '3.14', | ||||
|             value: '3.14deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -496,7 +496,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '30', | ||||
|             value: '30deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -519,7 +519,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '12.14', | ||||
|             value: '12.14deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -542,7 +542,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '30', | ||||
|             value: '30deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -565,7 +565,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '3.14', | ||||
|             value: '3.14deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -658,18 +658,18 @@ describe('testing getConstraintInfo', () => { | ||||
|     const code = `part001 = startSketchOn(-XZ) | ||||
|     |> startProfile(at = [0, 0]) | ||||
|     |> line(end = [3, 4]) | ||||
|     |> angledLine(angle = 3.14, length = 3.14) | ||||
|     |> angledLine(angle = 3.14deg, length = 3.14) | ||||
|     |> line(endAbsolute = [6.14, 3.14]) | ||||
|     |> xLine(endAbsolute = 8) | ||||
|     |> yLine(endAbsolute = 5) | ||||
|     |> yLine(length = 3.14, tag = $a) | ||||
|     |> xLine(length = 3.14) | ||||
|     |> angledLine(angle = 3.14, lengthX = 3.14) | ||||
|     |> angledLine(angle = 30, lengthY = 3) | ||||
|     |> angledLine(angle = 12, endAbsoluteX = 12) | ||||
|     |> angledLine(angle = 30, endAbsoluteY = 10) | ||||
|     |> angledLine(angle = 3.14deg, lengthX = 3.14) | ||||
|     |> angledLine(angle = 30deg, lengthY = 3) | ||||
|     |> angledLine(angle = 12deg, endAbsoluteX = 12) | ||||
|     |> angledLine(angle = 30deg, endAbsoluteY = 10) | ||||
|     |> angledLineThatIntersects( | ||||
|          angle = 3.14, | ||||
|          angle = 3.14deg, | ||||
|          intersectTag = a, | ||||
|          offset = 0, | ||||
|        ) | ||||
| @ -681,7 +681,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '3.14', | ||||
|             value: '3.14deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -704,7 +704,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '3.14', | ||||
|             value: '3.14deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -727,7 +727,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '30', | ||||
|             value: '30deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -750,7 +750,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '12', | ||||
|             value: '12deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -773,7 +773,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: false, | ||||
|             value: '30', | ||||
|             value: '30deg', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -814,18 +814,18 @@ describe('testing getConstraintInfo', () => { | ||||
|     const code = `part001 = startSketchOn(-XZ) | ||||
|     |> startProfile(at = [0, 0]) | ||||
|     |> line(end = [3 + 0, 4 + 0]) | ||||
|     |> angledLine(angle = 3.14 + 0, length = 3.14 + 0 ) | ||||
|     |> angledLine(angle = 3.14deg + 0, length = 3.14 + 0 ) | ||||
|     |> line(endAbsolute = [6.14 + 0, 3.14 + 0]) | ||||
|     |> xLine(endAbsolute = 8 + 0) | ||||
|     |> yLine(endAbsolute = 5 + 0) | ||||
|     |> yLine(length = 3.14 + 0, tag = $a) | ||||
|     |> xLine(length = 3.14 + 0) | ||||
|     |> angledLine(angle = 3.14 + 0, lengthX = 3.14 + 0) | ||||
|     |> angledLine(angle = 30 + 0, lengthY = 3 + 0) | ||||
|     |> angledLine(angle = 12.14 + 0, endAbsoluteX =  12 + 0) | ||||
|     |> angledLine(angle = 30 + 0, endAbsoluteY =  10.14 + 0) | ||||
|     |> angledLine(angle = 3.14deg + 0, lengthX = 3.14 + 0) | ||||
|     |> angledLine(angle = 30deg + 0, lengthY = 3 + 0) | ||||
|     |> angledLine(angle = 12.14deg + 0, endAbsoluteX =  12 + 0) | ||||
|     |> angledLine(angle = 30deg + 0, endAbsoluteY =  10.14 + 0) | ||||
|     |> angledLineThatIntersects( | ||||
|          angle = 3.14 + 0, | ||||
|          angle = 3.14deg + 0, | ||||
|          intersectTag = a, | ||||
|          offset = 0 + 0, | ||||
|        ) | ||||
| @ -860,7 +860,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: true, | ||||
|             value: '3.14 + 0', | ||||
|             value: '3.14deg + 0', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -1006,7 +1006,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: true, | ||||
|             value: '3.14 + 0', | ||||
|             value: '3.14deg + 0', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -1029,7 +1029,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: true, | ||||
|             value: '30 + 0', | ||||
|             value: '30deg + 0', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -1052,7 +1052,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: true, | ||||
|             value: '12.14 + 0', | ||||
|             value: '12.14deg + 0', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -1075,7 +1075,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: true, | ||||
|             value: '30 + 0', | ||||
|             value: '30deg + 0', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
| @ -1098,7 +1098,7 @@ describe('testing getConstraintInfo', () => { | ||||
|           { | ||||
|             type: 'angle', | ||||
|             isConstrained: true, | ||||
|             value: '3.14 + 0', | ||||
|             value: '3.14deg + 0', | ||||
|             sourceRange: [expect.any(Number), expect.any(Number), 0], | ||||
|             argPosition: { type: 'labeledArg', key: 'angle' }, | ||||
|             pathToNode: expect.any(Array), | ||||
|  | ||||
| @ -1570,9 +1570,12 @@ export const arc: SketchLineHelperKw = { | ||||
|       createLabeledArg('radius', createLiteral(roundOff(radius))), | ||||
|       createLabeledArg( | ||||
|         'angleStart', | ||||
|         createLiteral(roundOff(startAngleDegrees)) | ||||
|         createLiteral(roundOff(startAngleDegrees), 'Deg') | ||||
|       ), | ||||
|       createLabeledArg( | ||||
|         'angleEnd', | ||||
|         createLiteral(roundOff(endAngleDegrees), 'Deg') | ||||
|       ), | ||||
|       createLabeledArg('angleEnd', createLiteral(roundOff(endAngleDegrees))), | ||||
|     ]) | ||||
|  | ||||
|     if ( | ||||
| @ -1623,13 +1626,13 @@ export const arc: SketchLineHelperKw = { | ||||
|           type: 'objectProperty', | ||||
|           key: 'angle', | ||||
|           argType: 'angle', | ||||
|           expr: createLiteral(roundOff(startAngleDegrees)), | ||||
|           expr: createLiteral(roundOff(startAngleDegrees), 'Deg'), | ||||
|         }, | ||||
|         { | ||||
|           type: 'objectProperty', | ||||
|           key: 'angle', | ||||
|           argType: 'angle', | ||||
|           expr: createLiteral(roundOff(endAngleDegrees)), | ||||
|           expr: createLiteral(roundOff(endAngleDegrees), 'Deg'), | ||||
|         }, | ||||
|       ]) | ||||
|       if (err(result)) return result | ||||
| @ -1689,8 +1692,8 @@ export const arc: SketchLineHelperKw = { | ||||
|     const endAngleDegrees = (endAngle * 180) / Math.PI | ||||
|  | ||||
|     const newRadius = createLiteral(roundOff(radius)) | ||||
|     const newAngleStart = createLiteral(roundOff(startAngleDegrees)) | ||||
|     const newAngleEnd = createLiteral(roundOff(endAngleDegrees)) | ||||
|     const newAngleStart = createLiteral(roundOff(startAngleDegrees), 'Deg') | ||||
|     const newAngleEnd = createLiteral(roundOff(endAngleDegrees), 'Deg') | ||||
|     mutateKwArg('radius', callExpression, newRadius) | ||||
|     mutateKwArg('angleStart', callExpression, newAngleStart) | ||||
|     mutateKwArg('angleEnd', callExpression, newAngleEnd) | ||||
| @ -2409,7 +2412,7 @@ export const angledLine: SketchLineHelperKw = { | ||||
|             createLocalName(snaps?.previousArcTag), | ||||
|             [] | ||||
|           ) | ||||
|       : createLiteral(roundOff(getAngle(from, to), 0)) | ||||
|       : createLiteral(roundOff(getAngle(from, to), 0), 'Deg') | ||||
|     const newLengthVal = createLiteral(roundOff(getLength(from, to), 2)) | ||||
|     const newLine = createCallExpressionStdLibKw('angledLine', null, [ | ||||
|       createLabeledArg(ARG_ANGLE, newAngleVal), | ||||
| @ -2463,7 +2466,7 @@ export const angledLine: SketchLineHelperKw = { | ||||
|     const angle = roundOff(getAngle(from, to), 0) | ||||
|     const lineLength = roundOff(getLength(from, to), 2) | ||||
|  | ||||
|     const angleLit = createLiteral(angle) | ||||
|     const angleLit = createLiteral(angle, 'Deg') | ||||
|     const lengthLit = createLiteral(lineLength) | ||||
|  | ||||
|     mutateKwArg(ARG_ANGLE, callExpression, angleLit) | ||||
| @ -2520,7 +2523,7 @@ export const angledLineOfXLength: SketchLineHelperKw = { | ||||
|     if (err(sketch)) { | ||||
|       return sketch | ||||
|     } | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0)) | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0), 'Deg') | ||||
|     const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1) | ||||
|     let newLine: Expr | ||||
|     if (replaceExistingCallback) { | ||||
| @ -2579,7 +2582,7 @@ export const angledLineOfXLength: SketchLineHelperKw = { | ||||
|       ? Math.abs(xLength) | ||||
|       : xLength // todo make work for variable angle > 180 | ||||
|  | ||||
|     const angleLit = createLiteral(angle) | ||||
|     const angleLit = createLiteral(angle, 'Deg') | ||||
|     const lengthLit = createLiteral(adjustedXLength) | ||||
|  | ||||
|     removeDeterminingArgs(callExpression) | ||||
| @ -2632,7 +2635,7 @@ export const angledLineOfYLength: SketchLineHelperKw = { | ||||
|     const sketch = sketchFromKclValue(variables[variableName], variableName) | ||||
|     if (err(sketch)) return sketch | ||||
|  | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0)) | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0), 'Deg') | ||||
|     const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1) | ||||
|     let newLine: Expr | ||||
|     if (replaceExistingCallback) { | ||||
| @ -2691,7 +2694,7 @@ export const angledLineOfYLength: SketchLineHelperKw = { | ||||
|       ? Math.abs(yLength) | ||||
|       : yLength // todo make work for variable angle > 180 | ||||
|  | ||||
|     const angleLit = createLiteral(angle) | ||||
|     const angleLit = createLiteral(angle, 'Deg') | ||||
|     const lengthLit = createLiteral(adjustedYLength) | ||||
|  | ||||
|     removeDeterminingArgs(callExpression) | ||||
| @ -2728,7 +2731,7 @@ export const angledLineToX: SketchLineHelperKw = { | ||||
|     if (err(nodeMeta)) return nodeMeta | ||||
|  | ||||
|     const { node: pipe } = nodeMeta | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0)) | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0), 'Deg') | ||||
|     const xArg = createLiteral(roundOff(to[0], 2)) | ||||
|     if (replaceExistingCallback) { | ||||
|       const result = replaceExistingCallback([ | ||||
| @ -2779,7 +2782,7 @@ export const angledLineToX: SketchLineHelperKw = { | ||||
|  | ||||
|     const adjustedXLength = xLength | ||||
|  | ||||
|     const angleLit = createLiteral(angle) | ||||
|     const angleLit = createLiteral(angle, 'Deg') | ||||
|     const lengthLit = createLiteral(adjustedXLength) | ||||
|  | ||||
|     removeDeterminingArgs(callExpression) | ||||
| @ -2816,7 +2819,7 @@ export const angledLineToY: SketchLineHelperKw = { | ||||
|  | ||||
|     const { node: pipe } = nodeMeta | ||||
|  | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0)) | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0), 'Deg') | ||||
|     const yArg = createLiteral(roundOff(to[1], 2)) | ||||
|  | ||||
|     if (replaceExistingCallback) { | ||||
| @ -2868,7 +2871,7 @@ export const angledLineToY: SketchLineHelperKw = { | ||||
|  | ||||
|     const adjustedXLength = xLength | ||||
|  | ||||
|     const angleLit = createLiteral(angle) | ||||
|     const angleLit = createLiteral(angle, 'Deg') | ||||
|     const lengthLit = createLiteral(adjustedXLength) | ||||
|  | ||||
|     removeDeterminingArgs(callExpression) | ||||
| @ -2911,7 +2914,7 @@ export const angledLineThatIntersects: SketchLineHelperKw = { | ||||
|  | ||||
|     const { node: pipe } = nodeMeta | ||||
|  | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0)) | ||||
|     const angle = createLiteral(roundOff(getAngle(from, to), 0), 'Deg') | ||||
|     if (!referencedSegment) { | ||||
|       return new Error('referencedSegment must be provided') | ||||
|     } | ||||
| @ -2994,7 +2997,7 @@ export const angledLineThatIntersects: SketchLineHelperKw = { | ||||
|       ) | ||||
|     } | ||||
|  | ||||
|     mutateKwArg(ARG_ANGLE, callExpression, createLiteral(angle)) | ||||
|     mutateKwArg(ARG_ANGLE, callExpression, createLiteral(angle, 'Deg')) | ||||
|     mutateKwArg(ARG_OFFSET, callExpression, createLiteral(offset)) | ||||
|     return { | ||||
|       modifiedAst: _node, | ||||
| @ -3504,7 +3507,7 @@ export function replaceSketchLine({ | ||||
| }): | ||||
|   | { | ||||
|       modifiedAst: Node<Program> | ||||
|       valueUsedInTransform?: number | ||||
|       valueUsedInTransform?: string | ||||
|       pathToNode: PathToNode | ||||
|     } | ||||
|   | Error { | ||||
|  | ||||
| @ -72,22 +72,22 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|     `  |> startProfile(at = [0, 0])`, | ||||
|     `  |> line(endAbsolute = [1, 1], tag = $abc1)`, | ||||
|     `  |> line(end = [-2.04, -0.7], tag = $abc2)`, | ||||
|     `  |> angledLine(angle = 157, length = 1.69, tag = $abc3)`, | ||||
|     `  |> angledLine(angle = 217, lengthX = 0.86, tag = $abc4)`, | ||||
|     `  |> angledLine(angle = 104, lengthY = 1.58, tag = $abc5)`, | ||||
|     `  |> angledLine(angle = 55, endAbsoluteX = -2.89, tag = $abc6)`, | ||||
|     `  |> angledLine(angle = 330, endAbsoluteY = 2.53, tag = $abc7)`, | ||||
|     `  |> angledLine(angle = 157deg, length = 1.69, tag = $abc3)`, | ||||
|     `  |> angledLine(angle = 217deg, lengthX = 0.86, tag = $abc4)`, | ||||
|     `  |> angledLine(angle = 104deg, lengthY = 1.58, tag = $abc5)`, | ||||
|     `  |> angledLine(angle = 55deg, endAbsoluteX = -2.89, tag = $abc6)`, | ||||
|     `  |> angledLine(angle = 330deg, endAbsoluteY = 2.53, tag = $abc7)`, | ||||
|     `  |> xLine(length = 1.47, tag = $abc8)`, | ||||
|     `  |> yLine(length = 1.57, tag = $abc9)`, | ||||
|     `  |> xLine(endAbsolute = 1.49, tag = $abc10)`, | ||||
|     `  |> yLine(endAbsolute = 2.64, tag = $abc11)`, | ||||
|     `  |> line(endAbsolute = [2.55, 3.58]) // lineTo`, | ||||
|     `  |> line(end = [0.73, -0.75])`, | ||||
|     `  |> angledLine(angle = 63, length = 1.38) // angledLine`, | ||||
|     `  |> angledLine(angle = 319, lengthX = 1.15) // angledLineOfXLength`, | ||||
|     `  |> angledLine(angle = 50, lengthY = 1.35) // angledLineOfYLength`, | ||||
|     `  |> angledLine(angle = 291, endAbsoluteX = 6.66) // angledLineToX`, | ||||
|     `  |> angledLine(angle = 228, endAbsoluteY = 2.14) // angledLineToY`, | ||||
|     `  |> angledLine(angle = 63deg, length = 1.38) // angledLine`, | ||||
|     `  |> angledLine(angle = 319deg, lengthX = 1.15) // angledLineOfXLength`, | ||||
|     `  |> angledLine(angle = 50deg, lengthY = 1.35) // angledLineOfYLength`, | ||||
|     `  |> angledLine(angle = 291deg, endAbsoluteX = 6.66) // angledLineToX`, | ||||
|     `  |> angledLine(angle = 228deg, endAbsoluteY = 2.14) // angledLineToY`, | ||||
|     `  |> xLine(length = -1.33)`, | ||||
|     `  |> yLine(length = -1.07)`, | ||||
|     `  |> xLine(endAbsolute = 3.27)`, | ||||
| @ -143,7 +143,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLine with tag converts to xLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 157, length = 1.69, tag = $abc3)', | ||||
|       callToSwap: 'angledLine(angle = 157deg, length = 1.69, tag = $abc3)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(length = -1.56, tag = $abc3)' | ||||
| @ -154,7 +154,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLine w/o tag converts to xLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 63, length = 1.38)', | ||||
|       callToSwap: 'angledLine(angle = 63deg, length = 1.38)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(length = 0.63) // angledLine' | ||||
| @ -165,7 +165,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineOfXLength with tag converts to xLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 217, lengthX = 0.86, tag = $abc4)', | ||||
|       callToSwap: 'angledLine(angle = 217deg, lengthX = 0.86, tag = $abc4)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(length = -0.86, tag = $abc4)' | ||||
| @ -177,7 +177,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineOfXLength w/o tag converts to xLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 319, lengthX = 1.15)', | ||||
|       callToSwap: 'angledLine(angle = 319deg, lengthX = 1.15)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(length = 1.15) // angledLineOfXLength' | ||||
| @ -188,7 +188,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineOfYLength with tag converts to yLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 104, lengthY = 1.58, tag = $abc5)', | ||||
|       callToSwap: 'angledLine(angle = 104deg, lengthY = 1.58, tag = $abc5)', | ||||
|       constraintType: 'vertical', | ||||
|     }) | ||||
|     const expectedLine = 'yLine(length = 1.58, tag = $abc5)' | ||||
| @ -199,7 +199,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineOfYLength w/o tag converts to yLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 50, lengthY = 1.35)', | ||||
|       callToSwap: 'angledLine(angle = 50deg, lengthY = 1.35)', | ||||
|       constraintType: 'vertical', | ||||
|     }) | ||||
|     const expectedLine = 'yLine(length = 1.35) // angledLineOfYLength' | ||||
| @ -210,7 +210,8 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineToX with tag converts to xLineTo', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 55, endAbsoluteX = -2.89, tag = $abc6)', | ||||
|       callToSwap: | ||||
|         'angledLine(angle = 55deg, endAbsoluteX = -2.89, tag = $abc6)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(endAbsolute = -2.89, tag = $abc6)' | ||||
| @ -221,7 +222,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineToX w/o tag converts to xLineTo', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 291, endAbsoluteX = 6.66)', | ||||
|       callToSwap: 'angledLine(angle = 291deg, endAbsoluteX = 6.66)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(endAbsolute = 6.66) // angledLineToX' | ||||
| @ -232,7 +233,8 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineToY with tag converts to yLineTo', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 330, endAbsoluteY = 2.53, tag = $abc7)', | ||||
|       callToSwap: | ||||
|         'angledLine(angle = 330deg, endAbsoluteY = 2.53, tag = $abc7)', | ||||
|       constraintType: 'vertical', | ||||
|     }) | ||||
|     const expectedLine = 'yLine(endAbsolute = 2.53, tag = $abc7)' | ||||
| @ -243,7 +245,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo', () => { | ||||
|   it('angledLineToY w/o tag converts to yLineTo', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: bigExample, | ||||
|       callToSwap: 'angledLine(angle = 228, endAbsoluteY = 2.14)', | ||||
|       callToSwap: 'angledLine(angle = 228deg, endAbsoluteY = 2.14)', | ||||
|       constraintType: 'vertical', | ||||
|     }) | ||||
|     const expectedLine = 'yLine(endAbsolute = 2.14) // angledLineToY' | ||||
| @ -258,7 +260,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|   const variablesExampleArr = [ | ||||
|     `lineX = -1`, | ||||
|     `lineToX = -1.3`, | ||||
|     `angledLineAngle = 207`, | ||||
|     `angledLineAngle = 207deg`, | ||||
|     `angledLineOfXLengthX = 0.8`, | ||||
|     `angledLineOfYLengthY = 0.89`, | ||||
|     `angledLineToXx = -1.86`, | ||||
| @ -270,10 +272,10 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|     `  |> line(end = [lineX, 2.13])`, | ||||
|     `  |> line(endAbsolute = [lineToX, 2.85])`, | ||||
|     `  |> angledLine(angle = angledLineAngle, length = 1.64)`, | ||||
|     `  |> angledLine(angle = 329, lengthX = angledLineOfXLengthX)`, | ||||
|     `  |> angledLine(angle = 222, lengthY = angledLineOfYLengthY)`, | ||||
|     `  |> angledLine(angle = 330, endAbsoluteX = angledLineToXx)`, | ||||
|     `  |> angledLine(angle = 217, endAbsoluteY = angledLineToYy)`, | ||||
|     `  |> angledLine(angle = 329deg, lengthX = angledLineOfXLengthX)`, | ||||
|     `  |> angledLine(angle = 222deg, lengthY = angledLineOfYLengthY)`, | ||||
|     `  |> angledLine(angle = 330deg, endAbsoluteX = angledLineToXx)`, | ||||
|     `  |> angledLine(angle = 217deg, endAbsoluteY = angledLineToYy)`, | ||||
|     `  |> line(end = [0.89, -0.1])`, | ||||
|   ] | ||||
|   const varExample = variablesExampleArr.join('\n') | ||||
| @ -302,7 +304,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|   it('angledLineOfXLength keeps variable when converted to xLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: varExample, | ||||
|       callToSwap: 'angledLine(angle = 329, lengthX = angledLineOfXLengthX)', | ||||
|       callToSwap: 'angledLine(angle = 329deg, lengthX = angledLineOfXLengthX)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(length = angledLineOfXLengthX)' | ||||
| @ -313,7 +315,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|   it('angledLineOfYLength keeps variable when converted to yLine', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: varExample, | ||||
|       callToSwap: 'angledLine(angle = 222, lengthY = angledLineOfYLengthY)', | ||||
|       callToSwap: 'angledLine(angle = 222deg, lengthY = angledLineOfYLengthY)', | ||||
|       constraintType: 'vertical', | ||||
|     }) | ||||
|     const expectedLine = 'yLine(length = -angledLineOfYLengthY)' | ||||
| @ -324,7 +326,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|   it('angledLineToX keeps variable when converted to xLineTo', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: varExample, | ||||
|       callToSwap: 'angledLine(angle = 330, endAbsoluteX = angledLineToXx)', | ||||
|       callToSwap: 'angledLine(angle = 330deg, endAbsoluteX = angledLineToXx)', | ||||
|       constraintType: 'horizontal', | ||||
|     }) | ||||
|     const expectedLine = 'xLine(endAbsolute = angledLineToXx)' | ||||
| @ -335,7 +337,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|   it('angledLineToY keeps variable when converted to yLineTo', async () => { | ||||
|     const { newCode, originalRange } = await testingSwapSketchFnCall({ | ||||
|       inputCode: varExample, | ||||
|       callToSwap: 'angledLine(angle = 217, endAbsoluteY = angledLineToYy)', | ||||
|       callToSwap: 'angledLine(angle = 217deg, endAbsoluteY = angledLineToYy)', | ||||
|       constraintType: 'vertical', | ||||
|     }) | ||||
|     const expectedLine = 'yLine(endAbsolute = angledLineToYy)' | ||||
| @ -348,7 +350,7 @@ describe('testing swapping out sketch calls with xLine/xLineTo while keeping var | ||||
|     const illegalConvert = () => | ||||
|       testingSwapSketchFnCall({ | ||||
|         inputCode: varExample, | ||||
|         callToSwap: 'angledLine(angle = 217, endAbsoluteY = angledLineToYy)', | ||||
|         callToSwap: 'angledLine(angle = 217deg, endAbsoluteY = angledLineToYy)', | ||||
|         constraintType: 'horizontal', | ||||
|       }) | ||||
|     await expect(illegalConvert).rejects.toThrowError('no callback helper') | ||||
|  | ||||
| @ -99,7 +99,7 @@ export function isSketchVariablesLinked( | ||||
|     |> line(end = [myVar, 0.38]) // ❗ <- cursor in this fn call (the primary) | ||||
|     |> line(end = [0.41, baz]) | ||||
|     |> xLine(length = 0.91) | ||||
|     |> angledLine(angle = 37, length = 2) | ||||
|     |> angledLine(angle = 37deg, length = 2) | ||||
|   const yo = line(end = [myVar, 0.38], tag = part001) | ||||
|     |> line(end = [1, 1]) | ||||
|   const yo2 = line(end = [myVar, 0.38], tag = yo) | ||||
|  | ||||
| @ -42,25 +42,29 @@ describe('testing getConstraintType', () => { | ||||
|     expect(helper(`line(endAbsolute = [myVar, 5])`)).toBe('xAbsolute') | ||||
|   }) | ||||
|   it('testing angledLine', () => { | ||||
|     expect(helper(`angledLine(angle = 5, length = myVar)`)).toBe('length') | ||||
|     expect(helper(`angledLine(angle = 5deg, length = myVar)`)).toBe('length') | ||||
|     expect(helper(`angledLine(angle = myVar, length = 5)`)).toBe('angle') | ||||
|   }) | ||||
|   it('testing angledLineOfXLength', () => { | ||||
|     expect(helper(`angledLine(angle = 5, lengthX = myVar)`)).toBe('xRelative') | ||||
|     expect(helper(`angledLine(angle = 5deg, lengthX = myVar)`)).toBe( | ||||
|       'xRelative' | ||||
|     ) | ||||
|     expect(helper(`angledLine(angle = myVar, lengthX = 5)`)).toBe('angle') | ||||
|   }) | ||||
|   it('testing angledLineToX', () => { | ||||
|     expect(helper(`angledLine(angle = 5, endAbsoluteX = myVar)`)).toBe( | ||||
|     expect(helper(`angledLine(angle = 5deg, endAbsoluteX = myVar)`)).toBe( | ||||
|       'xAbsolute' | ||||
|     ) | ||||
|     expect(helper(`angledLine(angle = myVar, endAbsoluteX = 5)`)).toBe('angle') | ||||
|   }) | ||||
|   it('testing angledLineOfYLength', () => { | ||||
|     expect(helper(`angledLine(angle = 5, lengthY = myVar)`)).toBe('yRelative') | ||||
|     expect(helper(`angledLine(angle = 5deg, lengthY = myVar)`)).toBe( | ||||
|       'yRelative' | ||||
|     ) | ||||
|     expect(helper(`angledLine(angle = myVar, lengthY = 5)`)).toBe('angle') | ||||
|   }) | ||||
|   it('testing angledLineToY', () => { | ||||
|     expect(helper(`angledLine(angle = 5, endAbsoluteY = myVar)`)).toBe( | ||||
|     expect(helper(`angledLine(angle = 5deg, endAbsoluteY = myVar)`)).toBe( | ||||
|       'yAbsolute' | ||||
|     ) | ||||
|     expect(helper(`angledLine(angle = myVar, endAbsoluteY = 5)`)).toBe('angle') | ||||
| @ -172,7 +176,7 @@ describe('testing transformAstForSketchLines for equal length constraint', () => | ||||
|     const expectedModifiedScript = `sketch001 = startSketchOn(XZ) | ||||
|   |> startProfile(at = [0, 0]) | ||||
|   |> line(end = [5, 5], tag = $seg01) | ||||
|   |> angledLine(angle = 112, length = segLen(seg01)) | ||||
|   |> angledLine(angle = 112deg, length = segLen(seg01)) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> close() | ||||
| ` | ||||
| @ -248,30 +252,30 @@ describe('testing transformAstForSketchLines for equal length constraint', () => | ||||
|   const inputScript = `myVar = 3 | ||||
| myVar2 = 5 | ||||
| myVar3 = 6 | ||||
| myAng = 40 | ||||
| myAng2 = 134 | ||||
| myAng = 40deg | ||||
| myAng2 = 134deg | ||||
| part001 = startSketchOn(XY) | ||||
|   |> startProfile(at = [0, 0]) | ||||
|   |> line(end = [1, 3.82]) // ln-should-get-tag | ||||
|   |> line(endAbsolute = [2, 4]) // ln-lineTo-free should become angledLine | ||||
|   |> angledLine(angle = 45, endAbsoluteX = 2.5) // ln-angledLineToX-free should become angledLine | ||||
|   |> angledLine(angle = 45deg, endAbsoluteX = 2.5) // ln-angledLineToX-free should become angledLine | ||||
|   |> angledLine(angle = myAng, endAbsoluteX = 3) // ln-angledLineToX-angle should become angledLine | ||||
|   |> angledLine(angle = 135, endAbsoluteY = 5) // ln-angledLineToY-free should become angledLine | ||||
|   |> angledLine(angle = 135deg, endAbsoluteY = 5) // ln-angledLineToY-free should become angledLine | ||||
|   |> angledLine(angle = myAng2, endAbsoluteY = 4) // ln-angledLineToY-angle should become angledLine | ||||
|   |> line(end = [myVar, 1]) // ln-should use legLen for y | ||||
|   |> line(end = [myVar, -1]) // ln-legLen but negative | ||||
|   |> line(end = [-0.62, -1.54]) // ln-should become angledLine | ||||
|   |> angledLine(angle = myVar, length = 1.04) // ln-use segLen for second arg | ||||
|   |> angledLine(angle = 45, length = 1.04) // ln-segLen again | ||||
|   |> angledLine(angle = 54, lengthX = 2.35) // ln-should be transformed to angledLine | ||||
|   |> angledLine(angle = 50, lengthX = myVar) // ln-should use legAngX to calculate angle | ||||
|   |> angledLine(angle = 209, lengthX = myVar) // ln-same as above but should have + 180 to match original quadrant | ||||
|   |> angledLine(angle = 45deg, length = 1.04) // ln-segLen again | ||||
|   |> angledLine(angle = 54deg, lengthX = 2.35) // ln-should be transformed to angledLine | ||||
|   |> angledLine(angle = 50deg, lengthX = myVar) // ln-should use legAngX to calculate angle | ||||
|   |> angledLine(angle = 209deg, lengthX = myVar) // ln-same as above but should have + 180 to match original quadrant | ||||
|   |> line(end = [1, myVar]) // ln-legLen again but yRelative | ||||
|   |> line(end = [-1, myVar]) // ln-negative legLen yRelative | ||||
|   |> angledLine(angle = 58, lengthY = 0.7) // ln-angledLineOfYLength-free should become angledLine | ||||
|   |> angledLine(angle = 58deg, lengthY = 0.7) // ln-angledLineOfYLength-free should become angledLine | ||||
|   |> angledLine(angle = myAng, lengthY = 0.7) // ln-angledLineOfYLength-angle should become angledLine | ||||
|   |> angledLine(angle = 35, lengthY = myVar) // ln-angledLineOfYLength-yRelative use legAngY | ||||
|   |> angledLine(angle = 305, lengthY = myVar) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp | ||||
|   |> angledLine(angle = 35deg, lengthY = myVar) // ln-angledLineOfYLength-yRelative use legAngY | ||||
|   |> angledLine(angle = 305deg, lengthY = myVar) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp | ||||
|   |> xLine(length = 1.03) // ln-xLine-free should sub in segLen | ||||
|   |> yLine(length = 1.04) // ln-yLine-free should sub in segLen | ||||
|   |> xLine(endAbsolute = 30) // ln-xLineTo-free should convert to xLine | ||||
| @ -280,15 +284,15 @@ part001 = startSketchOn(XY) | ||||
|   const expectModifiedScript = `myVar = 3 | ||||
| myVar2 = 5 | ||||
| myVar3 = 6 | ||||
| myAng = 40 | ||||
| myAng2 = 134 | ||||
| myAng = 40deg | ||||
| myAng2 = 134deg | ||||
| part001 = startSketchOn(XY) | ||||
|   |> startProfile(at = [0, 0]) | ||||
|   |> line(end = [1, 3.82], tag = $seg01) // ln-should-get-tag | ||||
|   |> angledLine(angle = 10, length = segLen(seg01)) // ln-lineTo-free should become angledLine | ||||
|   |> angledLine(angle = 45, length = segLen(seg01)) // ln-angledLineToX-free should become angledLine | ||||
|   |> angledLine(angle = 10deg, length = segLen(seg01)) // ln-lineTo-free should become angledLine | ||||
|   |> angledLine(angle = 45deg, length = segLen(seg01)) // ln-angledLineToX-free should become angledLine | ||||
|   |> angledLine(angle = myAng, length = segLen(seg01)) // ln-angledLineToX-angle should become angledLine | ||||
|   |> angledLine(angle = 135, length = segLen(seg01)) // ln-angledLineToY-free should become angledLine | ||||
|   |> angledLine(angle = 135deg, length = segLen(seg01)) // ln-angledLineToY-free should become angledLine | ||||
|   |> angledLine(angle = myAng2, length = segLen(seg01)) // ln-angledLineToY-angle should become angledLine | ||||
|   |> line(end = [ | ||||
|        min([segLen(seg01), myVar]), | ||||
| @ -298,12 +302,12 @@ part001 = startSketchOn(XY) | ||||
|        min([segLen(seg01), myVar]), | ||||
|        -legLen(hypotenuse = segLen(seg01), leg = myVar) | ||||
|      ]) // ln-legLen but negative | ||||
|   |> angledLine(angle = -112, length = segLen(seg01)) // ln-should become angledLine | ||||
|   |> angledLine(angle = -112deg, length = segLen(seg01)) // ln-should become angledLine | ||||
|   |> angledLine(angle = myVar, length = segLen(seg01)) // ln-use segLen for second arg | ||||
|   |> angledLine(angle = 45, length = segLen(seg01)) // ln-segLen again | ||||
|   |> angledLine(angle = 54, length = segLen(seg01)) // ln-should be transformed to angledLine | ||||
|   |> angledLine(angle = 45deg, length = segLen(seg01)) // ln-segLen again | ||||
|   |> angledLine(angle = 54deg, length = segLen(seg01)) // ln-should be transformed to angledLine | ||||
|   |> angledLine(angle = legAngX(hypotenuse = segLen(seg01), leg = myVar), lengthX = min([segLen(seg01), myVar])) // ln-should use legAngX to calculate angle | ||||
|   |> angledLine(angle = 180 + legAngX(hypotenuse = segLen(seg01), leg = myVar), lengthX = min([segLen(seg01), myVar])) // ln-same as above but should have + 180 to match original quadrant | ||||
|   |> angledLine(angle = 180deg + legAngX(hypotenuse = segLen(seg01), leg = myVar), lengthX = min([segLen(seg01), myVar])) // ln-same as above but should have + 180 to match original quadrant | ||||
|   |> line(end = [ | ||||
|        legLen(hypotenuse = segLen(seg01), leg = myVar), | ||||
|        min([segLen(seg01), myVar]) | ||||
| @ -312,10 +316,10 @@ part001 = startSketchOn(XY) | ||||
|        -legLen(hypotenuse = segLen(seg01), leg = myVar), | ||||
|        min([segLen(seg01), myVar]) | ||||
|      ]) // ln-negative legLen yRelative | ||||
|   |> angledLine(angle = 58, length = segLen(seg01)) // ln-angledLineOfYLength-free should become angledLine | ||||
|   |> angledLine(angle = 58deg, length = segLen(seg01)) // ln-angledLineOfYLength-free should become angledLine | ||||
|   |> angledLine(angle = myAng, length = segLen(seg01)) // ln-angledLineOfYLength-angle should become angledLine | ||||
|   |> angledLine(angle = legAngY(hypotenuse = segLen(seg01), leg = myVar), lengthX = min([segLen(seg01), myVar])) // ln-angledLineOfYLength-yRelative use legAngY | ||||
|   |> angledLine(angle = 270 + legAngY(hypotenuse = segLen(seg01), leg = myVar), lengthX = min([segLen(seg01), myVar])) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp | ||||
|   |> angledLine(angle = 270deg + legAngY(hypotenuse = segLen(seg01), leg = myVar), lengthX = min([segLen(seg01), myVar])) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp | ||||
|   |> xLine(length = segLen(seg01)) // ln-xLine-free should sub in segLen | ||||
|   |> yLine(length = segLen(seg01)) // ln-yLine-free should sub in segLen | ||||
|   |> xLine(length = segLen(seg01)) // ln-xLineTo-free should convert to xLine | ||||
| @ -370,18 +374,18 @@ part001 = startSketchOn(XY) | ||||
|   |> line(endAbsolute = [3, 11]) // select for vertical constraint 3 | ||||
|   |> line(endAbsolute = [myVar2, 12.63]) // select for horizontal constraint 4 | ||||
|   |> line(endAbsolute = [4.08, myVar2]) // select for vertical constraint 4 | ||||
|   |> angledLine(angle = 156, length = 1.34) // select for horizontal constraint 5 | ||||
|   |> angledLine(angle = 103, length = 1.44) // select for vertical constraint 5 | ||||
|   |> angledLine(angle = -178, length = myVar) // select for horizontal constraint 6 | ||||
|   |> angledLine(angle = 129, length = myVar) // select for vertical constraint 6 | ||||
|   |> angledLine(angle = 237, lengthX = 1.05) // select for horizontal constraint 7 | ||||
|   |> angledLine(angle = 196, lengthY = 1.11) // select for vertical constraint 7 | ||||
|   |> angledLine(angle = 194, lengthX = myVar) // select for horizontal constraint 8 | ||||
|   |> angledLine(angle = 248, lengthY = myVar) // select for vertical constraint 8 | ||||
|   |> angledLine(angle = 202, endAbsoluteX = -10.92) // select for horizontal constraint 9 | ||||
|   |> angledLine(angle = 223, endAbsoluteY = 7.68) // select for vertical constraint 9 | ||||
|   |> angledLine(angle = 333, endAbsoluteX = myVar3) // select for horizontal constraint 10 | ||||
|   |> angledLine(angle = 301, endAbsoluteY = myVar) // select for vertical constraint 10 | ||||
|   |> angledLine(angle = 156deg, length = 1.34) // select for horizontal constraint 5 | ||||
|   |> angledLine(angle = 103deg, length = 1.44) // select for vertical constraint 5 | ||||
|   |> angledLine(angle = -178deg, length = myVar) // select for horizontal constraint 6 | ||||
|   |> angledLine(angle = 129deg, length = myVar) // select for vertical constraint 6 | ||||
|   |> angledLine(angle = 237deg, lengthX = 1.05) // select for horizontal constraint 7 | ||||
|   |> angledLine(angle = 196deg, lengthY = 1.11) // select for vertical constraint 7 | ||||
|   |> angledLine(angle = 194deg, lengthX = myVar) // select for horizontal constraint 8 | ||||
|   |> angledLine(angle = 248deg, lengthY = myVar) // select for vertical constraint 8 | ||||
|   |> angledLine(angle = 202deg, endAbsoluteX = -10.92) // select for horizontal constraint 9 | ||||
|   |> angledLine(angle = 223deg, endAbsoluteY = 7.68) // select for vertical constraint 9 | ||||
|   |> angledLine(angle = 333deg, endAbsoluteX = myVar3) // select for horizontal constraint 10 | ||||
|   |> angledLine(angle = 301deg, endAbsoluteY = myVar) // select for vertical constraint 10 | ||||
| ` | ||||
|   it('should transform horizontal lines the ast', async () => { | ||||
|     const expectModifiedScript = `myVar = 2 | ||||
| @ -399,17 +403,17 @@ part001 = startSketchOn(XY) | ||||
|   |> xLine(endAbsolute = myVar2) // select for horizontal constraint 4 | ||||
|   |> line(endAbsolute = [4.08, myVar2]) // select for vertical constraint 4 | ||||
|   |> xLine(length = -1.22) // select for horizontal constraint 5 | ||||
|   |> angledLine(angle = 103, length = 1.44) // select for vertical constraint 5 | ||||
|   |> angledLine(angle = 103deg, length = 1.44) // select for vertical constraint 5 | ||||
|   |> xLine(length = -myVar) // select for horizontal constraint 6 | ||||
|   |> angledLine(angle = 129, length = myVar) // select for vertical constraint 6 | ||||
|   |> angledLine(angle = 129deg, length = myVar) // select for vertical constraint 6 | ||||
|   |> xLine(length = -1.05) // select for horizontal constraint 7 | ||||
|   |> angledLine(angle = 196, lengthY = 1.11) // select for vertical constraint 7 | ||||
|   |> angledLine(angle = 196deg, lengthY = 1.11) // select for vertical constraint 7 | ||||
|   |> xLine(length = -myVar) // select for horizontal constraint 8 | ||||
|   |> angledLine(angle = 248, lengthY = myVar) // select for vertical constraint 8 | ||||
|   |> angledLine(angle = 248deg, lengthY = myVar) // select for vertical constraint 8 | ||||
|   |> xLine(endAbsolute = -10.92) // select for horizontal constraint 9 | ||||
|   |> angledLine(angle = 223, endAbsoluteY = 7.68) // select for vertical constraint 9 | ||||
|   |> angledLine(angle = 223deg, endAbsoluteY = 7.68) // select for vertical constraint 9 | ||||
|   |> xLine(endAbsolute = myVar3) // select for horizontal constraint 10 | ||||
|   |> angledLine(angle = 301, endAbsoluteY = myVar) // select for vertical constraint 10 | ||||
|   |> angledLine(angle = 301deg, endAbsoluteY = myVar) // select for vertical constraint 10 | ||||
| ` | ||||
|     const ast = assertParse(inputScript) | ||||
|  | ||||
| @ -458,17 +462,17 @@ part001 = startSketchOn(XY) | ||||
|   |> yLine(endAbsolute = 11) // select for vertical constraint 3 | ||||
|   |> line(endAbsolute = [myVar2, 12.63]) // select for horizontal constraint 4 | ||||
|   |> yLine(endAbsolute = myVar2) // select for vertical constraint 4 | ||||
|   |> angledLine(angle = 156, length = 1.34) // select for horizontal constraint 5 | ||||
|   |> angledLine(angle = 156deg, length = 1.34) // select for horizontal constraint 5 | ||||
|   |> yLine(length = 1.4) // select for vertical constraint 5 | ||||
|   |> angledLine(angle = -178, length = myVar) // select for horizontal constraint 6 | ||||
|   |> angledLine(angle = -178deg, length = myVar) // select for horizontal constraint 6 | ||||
|   |> yLine(length = myVar) // select for vertical constraint 6 | ||||
|   |> angledLine(angle = 237, lengthX = 1.05) // select for horizontal constraint 7 | ||||
|   |> angledLine(angle = 237deg, lengthX = 1.05) // select for horizontal constraint 7 | ||||
|   |> yLine(length = -1.11) // select for vertical constraint 7 | ||||
|   |> angledLine(angle = 194, lengthX = myVar) // select for horizontal constraint 8 | ||||
|   |> angledLine(angle = 194deg, lengthX = myVar) // select for horizontal constraint 8 | ||||
|   |> yLine(length = -myVar) // select for vertical constraint 8 | ||||
|   |> angledLine(angle = 202, endAbsoluteX = -10.92) // select for horizontal constraint 9 | ||||
|   |> angledLine(angle = 202deg, endAbsoluteX = -10.92) // select for horizontal constraint 9 | ||||
|   |> yLine(endAbsolute = 7.68) // select for vertical constraint 9 | ||||
|   |> angledLine(angle = 333, endAbsoluteX = myVar3) // select for horizontal constraint 10 | ||||
|   |> angledLine(angle = 333deg, endAbsoluteX = myVar3) // select for horizontal constraint 10 | ||||
|   |> yLine(endAbsolute = myVar) // select for vertical constraint 10 | ||||
| ` | ||||
|     const ast = assertParse(inputScript) | ||||
| @ -606,7 +610,7 @@ describe('testing getConstraintLevelFromSourceRange', () => { | ||||
| baseThick = 1 | ||||
| armThick = 0.5 | ||||
| totalHeight = 4 | ||||
| armAngle = 60 | ||||
| armAngle = 60deg | ||||
| totalLength = 9.74 | ||||
| yDatum = 0 | ||||
|  | ||||
| @ -622,12 +626,12 @@ part001 = startSketchOn(XY) | ||||
|   |> xLine(length = 4.4) // partial | ||||
|   |> yLine(length = -1) // partial | ||||
|   |> xLine(length = -4.2 + 0) // full | ||||
|   |> angledLine(angle = segAng(seg01bing) + 180, length = 1.79) // partial | ||||
|   |> angledLine(angle = segAng(seg01bing) + 180deg, length = 1.79) // partial | ||||
|   |> line(end = [1.44, -0.74]) // free | ||||
|   |> xLine(length = 3.36) // partial | ||||
|   |> line(end = [1.49, 1.06]) // free | ||||
|   |> xLine(length = -3.43 + 0) // full | ||||
|   |> angledLine(angle = 243 + 0, lengthX = 1.2 + 0) // full` | ||||
|   |> angledLine(angle = 243deg + 0, lengthX = 1.2 + 0) // full` | ||||
|     const ast = assertParse(code) | ||||
|     const constraintLevels: ConstraintLevel[] = ['full', 'partial', 'free'] | ||||
|     constraintLevels.forEach((constraintLevel) => { | ||||
|  | ||||
| @ -144,7 +144,7 @@ function createCallWrapper( | ||||
|   tooltip: ToolTip, | ||||
|   val: [Expr, Expr] | Expr, | ||||
|   tag?: Expr, | ||||
|   valueUsedInTransform?: number | ||||
|   valueUsedInTransform?: string | ||||
| ): CreatedSketchExprResult | Error { | ||||
|   if (isArray(val)) { | ||||
|     if (tooltip === 'line') { | ||||
| @ -237,7 +237,7 @@ function createCallWrapper( | ||||
|         console.error(fnName) | ||||
|         return { | ||||
|           callExp: createCallExpressionStdLibKw('', null, []), | ||||
|           valueUsedInTransform: 0, | ||||
|           valueUsedInTransform: '', | ||||
|         } | ||||
|       } | ||||
|       return { | ||||
| @ -270,7 +270,7 @@ function createStdlibCallExpressionKw( | ||||
|   tool: ToolTip, | ||||
|   labeled: LabeledArg[], | ||||
|   tag?: Expr, | ||||
|   valueUsedInTransform?: number, | ||||
|   valueUsedInTransform?: string, | ||||
|   unlabeled?: Expr, | ||||
|   noncode?: NonCodeMeta | ||||
| ): CreatedSketchExprResult { | ||||
| @ -302,7 +302,7 @@ function intersectCallWrapper({ | ||||
|   offsetVal: Expr | ||||
|   intersectTag: Expr | ||||
|   tag?: Expr | ||||
|   valueUsedInTransform?: number | ||||
|   valueUsedInTransform?: string | ||||
| }): CreatedSketchExprResult { | ||||
|   const args: LabeledArg[] = [ | ||||
|     createLabeledArg(ARG_ANGLE, angleVal), | ||||
| @ -335,9 +335,8 @@ const xyLineSetLength = | ||||
|       : referenceSeg | ||||
|         ? segRef | ||||
|         : args[0].expr | ||||
|     const literalArg = asNum(args[0].expr.value) | ||||
|     if (err(literalArg)) return literalArg | ||||
|     return createCallWrapper(xOrY, lineVal, tag, literalArg) | ||||
|  | ||||
|     return createCallWrapper(xOrY, lineVal, tag, args[0].expr.raw) | ||||
|   } | ||||
|  | ||||
| type AngLenNone = 'ang' | 'len' | 'none' | ||||
| @ -376,10 +375,9 @@ const basicAngledLineCreateNode = | ||||
|           : args[1].expr | ||||
|     const shouldForceAng = valToForce === 'ang' && forceValueUsedInTransform | ||||
|     const shouldForceLen = valToForce === 'len' && forceValueUsedInTransform | ||||
|     const literalArg = asNum( | ||||
|       valToForce === 'ang' ? args[0].expr.value : args[1].expr.value | ||||
|     ) | ||||
|     if (err(literalArg)) return literalArg | ||||
|     const literalArg = | ||||
|       valToForce === 'ang' ? args[0].expr.raw : args[1].expr.raw | ||||
|  | ||||
|     return createCallWrapper( | ||||
|       'angledLine', | ||||
|       [ | ||||
| @ -443,7 +441,7 @@ const getLegAng = (ang: number, legAngleVal: BinaryPart) => { | ||||
|   const normalisedAngle = ((ang % 360) + 360) % 360 // between 0 and 360 | ||||
|   const truncatedTo90 = Math.floor(normalisedAngle / 90) * 90 | ||||
|   const binExp = createBinaryExpressionWithUnary([ | ||||
|     createLiteral(truncatedTo90), | ||||
|     createLiteral(truncatedTo90, 'Deg'), | ||||
|     legAngleVal, | ||||
|   ]) | ||||
|   return truncatedTo90 === 0 ? legAngleVal : binExp | ||||
| @ -457,7 +455,7 @@ function getClosesAngleDirection( | ||||
|   const angDiff = Math.abs(currentAng - refAngle) | ||||
|   const normalisedAngle = ((angDiff % 360) + 360) % 360 // between 0 and 180 | ||||
|   return normalisedAngle > 90 | ||||
|     ? createBinaryExpressionWithUnary([angleVal, createLiteral(180)]) | ||||
|     ? createBinaryExpressionWithUnary([angleVal, createLiteral(180, 'Deg')]) | ||||
|     : angleVal | ||||
| } | ||||
|  | ||||
| @ -486,7 +484,7 @@ const setHorzVertDistanceCreateNode = | ||||
|       'lineTo', | ||||
|       !index ? [finalValue, args[1].expr] : [args[0].expr, finalValue], | ||||
|       tag, | ||||
|       valueUsedInTransform | ||||
|       String(valueUsedInTransform) | ||||
|     ) | ||||
|   } | ||||
| const setHorzVertDistanceForAngleLineCreateNode = | ||||
| @ -511,7 +509,7 @@ const setHorzVertDistanceForAngleLineCreateNode = | ||||
|       xOrY === 'x' ? 'angledLineToX' : 'angledLineToY', | ||||
|       [inputs[0].expr, binExp], | ||||
|       tag, | ||||
|       valueUsedInTransform | ||||
|       String(valueUsedInTransform) | ||||
|     ) | ||||
|   } | ||||
|  | ||||
| @ -531,14 +529,14 @@ const setAbsDistanceCreateNode = | ||||
|         xOrY === 'x' ? 'xLineTo' : 'yLineTo', | ||||
|         val, | ||||
|         tag, | ||||
|         valueUsedInTransform | ||||
|         String(valueUsedInTransform) | ||||
|       ) | ||||
|     } | ||||
|     return createCallWrapper( | ||||
|       'lineTo', | ||||
|       !index ? [val, args[1].expr] : [args[0].expr, val], | ||||
|       tag, | ||||
|       valueUsedInTransform | ||||
|       String(valueUsedInTransform) | ||||
|     ) | ||||
|   } | ||||
| const setAbsDistanceForAngleLineCreateNode = | ||||
| @ -552,7 +550,7 @@ const setAbsDistanceForAngleLineCreateNode = | ||||
|       xOrY === 'x' ? 'angledLineToX' : 'angledLineToY', | ||||
|       [inputs[0].expr, val], | ||||
|       tag, | ||||
|       valueUsedInTransform | ||||
|       String(valueUsedInTransform) | ||||
|     ) | ||||
|   } | ||||
|  | ||||
| @ -578,7 +576,7 @@ const setHorVertDistanceForXYLines = | ||||
|       xOrY === 'x' ? 'xLineTo' : 'yLineTo', | ||||
|       makeBinExp, | ||||
|       tag, | ||||
|       valueUsedInTransform | ||||
|       String(valueUsedInTransform) | ||||
|     ) | ||||
|   } | ||||
|  | ||||
| @ -628,14 +626,14 @@ const setAngledIntersectLineForLines: CreateStdLibSketchCallExpr = ({ | ||||
|   } | ||||
|   const angleVal = [0, 90, 180, 270].includes(angle) | ||||
|     ? createName(['turns'], varNameMap[angle]) | ||||
|     : createLiteral(angle) | ||||
|     : createLiteral(angle, 'Deg') | ||||
|   return intersectCallWrapper({ | ||||
|     fnName: 'angledLineThatIntersects', | ||||
|     angleVal, | ||||
|     offsetVal: forceValueUsedInTransform || createLiteral(valueUsedInTransform), | ||||
|     intersectTag: createLocalName(referenceSegName), | ||||
|     tag, | ||||
|     valueUsedInTransform, | ||||
|     valueUsedInTransform: String(valueUsedInTransform), | ||||
|   }) | ||||
| } | ||||
|  | ||||
| @ -655,7 +653,7 @@ const setAngledIntersectForAngledLines: CreateStdLibSketchCallExpr = ({ | ||||
|     offsetVal: forceValueUsedInTransform || createLiteral(valueUsedInTransform), | ||||
|     intersectTag: createLocalName(referenceSegName), | ||||
|     tag, | ||||
|     valueUsedInTransform, | ||||
|     valueUsedInTransform: String(valueUsedInTransform), | ||||
|   }) | ||||
| } | ||||
|  | ||||
| @ -686,7 +684,7 @@ const setAngleBetweenCreateNode = | ||||
|     } | ||||
|     const binExp = createBinaryExpressionWithUnary([ | ||||
|       firstHalfValue, | ||||
|       forceValueUsedInTransform || createLiteral(valueUsedInTransform), | ||||
|       forceValueUsedInTransform || createLiteral(valueUsedInTransform, 'Deg'), | ||||
|     ]) | ||||
|     return createCallWrapper( | ||||
|       transformToType === 'none' | ||||
| @ -700,7 +698,7 @@ const setAngleBetweenCreateNode = | ||||
|           ? [binExp, inputs[0].expr] | ||||
|           : [binExp, inputs[1].expr], | ||||
|       tag, | ||||
|       valueUsedInTransform | ||||
|       String(valueUsedInTransform) + 'deg' | ||||
|     ) | ||||
|   } | ||||
|  | ||||
| @ -883,7 +881,7 @@ const transformMap: TransformMap = { | ||||
|             'angledLineToY', | ||||
|             [forceValueUsedInTransform || args[0].expr, inputs[1].expr], | ||||
|             tag, | ||||
|             val | ||||
|             String(val) | ||||
|           ) | ||||
|         }, | ||||
|       }, | ||||
| @ -1155,16 +1153,17 @@ const transformMap: TransformMap = { | ||||
|           const argVal = asNum(args[0].expr.value) | ||||
|           if (err(argVal)) return argVal | ||||
|           const segLen = createSegLen(referenceSegName) | ||||
|           if (argVal > 0) return createCallWrapper('xLine', segLen, tag, argVal) | ||||
|           if (argVal > 0) | ||||
|             return createCallWrapper('xLine', segLen, tag, String(argVal)) | ||||
|           if (isExprBinaryPart(segLen)) | ||||
|             return createCallWrapper( | ||||
|               'xLine', | ||||
|               createUnaryExpression(segLen), | ||||
|               tag, | ||||
|               argVal | ||||
|               String(argVal) | ||||
|             ) | ||||
|           // should probably return error here instead | ||||
|           return createCallWrapper('xLine', segLen, tag, argVal) | ||||
|           return createCallWrapper('xLine', segLen, tag, String(argVal)) | ||||
|         }, | ||||
|       }, | ||||
|       setHorzDistance: { | ||||
| @ -1194,7 +1193,7 @@ const transformMap: TransformMap = { | ||||
|           if (err(argVal)) return argVal | ||||
|           let segLen = createSegLen(referenceSegName) | ||||
|           if (argVal < 0) segLen = createUnaryExpression(segLen) | ||||
|           return createCallWrapper('yLine', segLen, tag, argVal) | ||||
|           return createCallWrapper('yLine', segLen, tag, String(argVal)) | ||||
|         }, | ||||
|       }, | ||||
|       setLength: { | ||||
| @ -1825,7 +1824,7 @@ export function transformSecondarySketchLinesTagFirst({ | ||||
| }): | ||||
|   | { | ||||
|       modifiedAst: Node<Program> | ||||
|       valueUsedInTransform?: number | ||||
|       valueUsedInTransform?: string | ||||
|       pathToNodeMap: PathToNodeMap | ||||
|       tagInfo: { | ||||
|         tag: string | ||||
| @ -1904,7 +1903,7 @@ export function transformAstSketchLines({ | ||||
| }): | ||||
|   | { | ||||
|       modifiedAst: Node<Program> | ||||
|       valueUsedInTransform?: number | ||||
|       valueUsedInTransform?: string | ||||
|       pathToNodeMap: PathToNodeMap | ||||
|     } | ||||
|   | Error { | ||||
| @ -2090,7 +2089,7 @@ export function transformAstSketchLines({ | ||||
|     const { modifiedAst, valueUsedInTransform, pathToNode } = replacedSketchLine | ||||
|     node = modifiedAst | ||||
|     pathToNodeMap[index] = pathToNode | ||||
|     if (typeof valueUsedInTransform === 'number') { | ||||
|     if (typeof valueUsedInTransform === 'string') { | ||||
|       _valueUsedInTransform = valueUsedInTransform | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @ -13,7 +13,7 @@ describe('testing angledLineThatIntersects', () => { | ||||
|   |> line(endAbsolute = [2, 2], tag = $yo) | ||||
|   |> line(endAbsolute = [3, 1]) | ||||
|   |> angledLineThatIntersects( | ||||
|        angle = 180, | ||||
|        angle = 180deg, | ||||
|        intersectTag = yo, | ||||
|        offset = ${offset}, | ||||
|        tag = $yo2, | ||||
|  | ||||
| @ -250,7 +250,7 @@ export type SimplifiedArgDetails = | ||||
|  */ | ||||
| export interface CreatedSketchExprResult { | ||||
|   callExp: Expr | ||||
|   valueUsedInTransform?: number | ||||
|   valueUsedInTransform?: string | ||||
| } | ||||
|  | ||||
| export type CreateStdLibSketchCallExpr = (args: { | ||||
| @ -288,7 +288,7 @@ export interface SketchLineHelperKw { | ||||
|     | { | ||||
|         modifiedAst: Node<Program> | ||||
|         pathToNode: PathToNode | ||||
|         valueUsedInTransform?: number | ||||
|         valueUsedInTransform?: string | ||||
|       } | ||||
|     | Error | ||||
|   updateArgs: (a: updateArgs) => | ||||
|  | ||||
| @ -764,11 +764,10 @@ export function kclSettings( | ||||
|  */ | ||||
| export function changeDefaultUnits( | ||||
|   kcl: string, | ||||
|   len: UnitLen | null, | ||||
|   angle: UnitAng | null | ||||
|   len: UnitLen | null | ||||
| ): string | Error { | ||||
|   try { | ||||
|     return change_default_units(kcl, JSON.stringify(len), JSON.stringify(angle)) | ||||
|     return change_default_units(kcl, JSON.stringify(len)) | ||||
|   } catch (e) { | ||||
|     console.error('Caught error changing kcl settings', e) | ||||
|     return new Error('Caught error changing kcl settings', { cause: e }) | ||||
|  | ||||
| @ -61,7 +61,7 @@ export const KCL_DEFAULT_LENGTH = `5` | ||||
| export const KCL_DEFAULT_TRANSFORM = `0` | ||||
|  | ||||
| /** The default KCL degree expression */ | ||||
| export const KCL_DEFAULT_DEGREE = `360` | ||||
| export const KCL_DEFAULT_DEGREE = `360deg` | ||||
|  | ||||
| /** The default KCL color expression */ | ||||
| export const KCL_DEFAULT_COLOR = `#3c73ff` | ||||
|  | ||||
| @ -70,7 +70,7 @@ import * from "parameters.kcl" | ||||
| bottomFaceSketch = startSketchOn(XY) | ||||
|   |> startProfile(at = [-fanSize / 2, -fanSize / 2]) | ||||
|   |> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = fanSize, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90deg, length = fanSize, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001) | ||||
|   |> close() | ||||
| @ -108,19 +108,19 @@ bottomFaceSketch = startSketchOn(XY) | ||||
| // Add large openings to the bottom face to allow airflow through the fan | ||||
| airflowPattern = startSketchOn(bottomFaceSketch, face = END) | ||||
|   |> startProfile(at = [fanSize * 7 / 25, -fanSize * 9 / 25]) | ||||
|   |> angledLine(angle = 140, length = fanSize * 12 / 25, tag = $seg01) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90) | ||||
|   |> angledLine(angle = -130, length = fanSize * 8 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90) | ||||
|   |> angledLine(angle = segAng(seg01) + 180, length = fanSize * 2 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 8 / 25, angle = 40) | ||||
|   |> angledLine(angle = 140deg, length = fanSize * 12 / 25, tag = $seg01) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90deg) | ||||
|   |> angledLine(angle = -130deg, length = fanSize * 8 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90deg) | ||||
|   |> angledLine(angle = segAng(seg01) + 180deg, length = fanSize * 2 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 8 / 25, angle = 40deg) | ||||
|   |> xLine(length = fanSize * 3 / 25) | ||||
|   |> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> close() | ||||
|   |> patternCircular2d( | ||||
|        instances = 4, | ||||
|        center = [0, 0], | ||||
|        arcDegrees = 360, | ||||
|        arcDegrees = 360deg, | ||||
|        rotateDuplicates = true, | ||||
|      ) | ||||
|   |> extrude(length = -4) | ||||
| @ -133,13 +133,13 @@ bodyMiddle = startSketchOn(bottomFaceSketch, face = END) | ||||
|        housingMiddleLength / 2, | ||||
|        -housingMiddleLength / 2 - housingMiddleRadius | ||||
|      ]) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> yLine(length = housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> xLine(length = -housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> yLine(length = -housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> extrude(length = fanHeight - 4 - 4) | ||||
|  | ||||
| @ -152,7 +152,7 @@ bodyFanHole = startSketchOn(bodyMiddle, face = END) | ||||
| topFaceSketch = startSketchOn(bodyMiddle, face = END) | ||||
| topHoles = startProfile(topFaceSketch, at = [-fanSize / 2, -fanSize / 2]) | ||||
|   |> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002) + 90, length = fanSize, tag = $rectangleSegmentB002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002) + 90deg, length = fanSize, tag = $rectangleSegmentB002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002), tag = $rectangleSegmentC002) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002) | ||||
|   |> close() | ||||
| @ -229,7 +229,7 @@ export mountingHoleSize = 4.5 | ||||
| bottomFaceSketch = startSketchOn(XY) | ||||
|   |> startProfile(at = [-fanSize / 2, -fanSize / 2]) | ||||
|   |> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = fanSize, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90deg, length = fanSize, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001) | ||||
|   |> close() | ||||
| @ -267,19 +267,19 @@ bottomFaceSketch = startSketchOn(XY) | ||||
| // Add large openings to the bottom face to allow airflow through the fan | ||||
| airflowPattern = startSketchOn(bottomFaceSketch, face = END) | ||||
|   |> startProfile(at = [fanSize * 7 / 25, -fanSize * 9 / 25]) | ||||
|   |> angledLine(angle = 140, length = fanSize * 12 / 25, tag = $seg01) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90) | ||||
|   |> angledLine(angle = -130, length = fanSize * 8 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90) | ||||
|   |> angledLine(angle = segAng(seg01) + 180, length = fanSize * 2 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 8 / 25, angle = 40) | ||||
|   |> angledLine(angle = 140deg, length = fanSize * 12 / 25, tag = $seg01) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90deg) | ||||
|   |> angledLine(angle = -130deg, length = fanSize * 8 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90deg) | ||||
|   |> angledLine(angle = segAng(seg01) + 180deg, length = fanSize * 2 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 8 / 25, angle = 40deg) | ||||
|   |> xLine(length = fanSize * 3 / 25) | ||||
|   |> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> close() | ||||
|   |> patternCircular2d( | ||||
|        instances = 4, | ||||
|        center = [0, 0], | ||||
|        arcDegrees = 360, | ||||
|        arcDegrees = 360deg, | ||||
|        rotateDuplicates = true, | ||||
|      ) | ||||
|   |> extrude(length = -4) | ||||
| @ -292,13 +292,13 @@ bodyMiddle = startSketchOn(bottomFaceSketch, face = END) | ||||
|        housingMiddleLength / 2, | ||||
|        -housingMiddleLength / 2 - housingMiddleRadius | ||||
|      ]) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> yLine(length = housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> xLine(length = -housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> yLine(length = -housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> extrude(length = fanHeight - 4 - 4) | ||||
|  | ||||
| @ -311,7 +311,7 @@ bodyFanHole = startSketchOn(bodyMiddle, face = END) | ||||
| topFaceSketch = startSketchOn(bodyMiddle, face = END) | ||||
| topHoles = startProfile(topFaceSketch, at = [-fanSize / 2, -fanSize / 2]) | ||||
|   |> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002) + 90, length = fanSize, tag = $rectangleSegmentB002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002) + 90deg, length = fanSize, tag = $rectangleSegmentB002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002), tag = $rectangleSegmentC002) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002) | ||||
|   |> close() | ||||
| @ -387,7 +387,7 @@ export mountingHoleSize = 4.5 | ||||
| bottomFaceSketch = startSketchOn(XY) | ||||
|   |> startProfile(at = [-fanSize / 2, -fanSize / 2]) | ||||
|   |> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = fanSize, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90deg, length = fanSize, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001) | ||||
|   |> close() | ||||
| @ -425,19 +425,19 @@ bottomFaceSketch = startSketchOn(XY) | ||||
| // Add large openings to the bottom face to allow airflow through the fan | ||||
| airflowPattern = startSketchOn(bottomFaceSketch, face = END) | ||||
|   |> startProfile(at = [fanSize * 7 / 25, -fanSize * 9 / 25]) | ||||
|   |> angledLine(angle = 140, length = fanSize * 12 / 25, tag = $seg01) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90) | ||||
|   |> angledLine(angle = -130, length = fanSize * 8 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90) | ||||
|   |> angledLine(angle = segAng(seg01) + 180, length = fanSize * 2 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 8 / 25, angle = 40) | ||||
|   |> angledLine(angle = 140deg, length = fanSize * 12 / 25, tag = $seg01) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90deg) | ||||
|   |> angledLine(angle = -130deg, length = fanSize * 8 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 1 / 50, angle = 90deg) | ||||
|   |> angledLine(angle = segAng(seg01) + 180deg, length = fanSize * 2 / 25) | ||||
|   |> tangentialArc(radius = fanSize * 8 / 25, angle = 40deg) | ||||
|   |> xLine(length = fanSize * 3 / 25) | ||||
|   |> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> close() | ||||
|   |> patternCircular2d( | ||||
|        instances = 4, | ||||
|        center = [0, 0], | ||||
|        arcDegrees = 360, | ||||
|        arcDegrees = 360deg, | ||||
|        rotateDuplicates = true, | ||||
|      ) | ||||
|   |> extrude(length = -4) | ||||
| @ -450,13 +450,13 @@ bodyMiddle = startSketchOn(bottomFaceSketch, face = END) | ||||
|        housingMiddleLength / 2, | ||||
|        -housingMiddleLength / 2 - housingMiddleRadius | ||||
|      ]) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> yLine(length = housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> xLine(length = -housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> yLine(length = -housingMiddleLength) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90) | ||||
|   |> tangentialArc(radius = housingMiddleRadius, angle = 90deg) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> extrude(length = fanHeight - 4 - 4) | ||||
|  | ||||
| @ -469,7 +469,7 @@ bodyFanHole = startSketchOn(bodyMiddle, face = END) | ||||
| topFaceSketch = startSketchOn(bodyMiddle, face = END) | ||||
| topHoles = startProfile(topFaceSketch, at = [-fanSize / 2, -fanSize / 2]) | ||||
|   |> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002) + 90, length = fanSize, tag = $rectangleSegmentB002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002) + 90deg, length = fanSize, tag = $rectangleSegmentB002) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002), tag = $rectangleSegmentC002) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002) | ||||
|   |> close() | ||||
| @ -543,11 +543,11 @@ ${fanHousingBrowser} | ||||
| fanCenter = startSketchOn(XZ) | ||||
|   |> startProfile(at = [-0.0001, fanHeight]) | ||||
|   |> xLine(endAbsolute = -15 + 1.5) | ||||
|   |> tangentialArc(radius = 1.5, angle = 90) | ||||
|   |> tangentialArc(radius = 1.5, angle = 90deg) | ||||
|   |> yLine(endAbsolute = 4.5) | ||||
|   |> xLine(endAbsolute = -13) | ||||
|   |> yLine(endAbsolute = profileStartY(%) - 5) | ||||
|   |> tangentialArc(radius = 1, angle = -90) | ||||
|   |> tangentialArc(radius = 1, angle = -90deg) | ||||
|   |> xLine(endAbsolute = -1) | ||||
|   |> yLine(length = 2) | ||||
|   |> xLine(length = -0.15) | ||||
| @ -571,32 +571,32 @@ fn fanBlade(offsetHeight, startAngle: number(deg)) { | ||||
|          15 * cos(startAngle), | ||||
|          15 * sin(startAngle) | ||||
|        ]) | ||||
|     |> arc(angleStart = startAngle, angleEnd = startAngle + 14, radius = 15) | ||||
|     |> arc(angleStart = startAngle, angleEnd = startAngle + 14deg, radius = 15) | ||||
|     |> arc( | ||||
|          endAbsolute = [ | ||||
|            fanSize * 22 / 50 * cos(startAngle - 20), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 20) | ||||
|            fanSize * 22 / 50 * cos(startAngle - 20deg), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 20deg) | ||||
|          ], | ||||
|          interiorAbsolute = [ | ||||
|            fanSize * 11 / 50 * cos(startAngle + 3), | ||||
|            fanSize * 11 / 50 * sin(startAngle + 3) | ||||
|            fanSize * 11 / 50 * cos(startAngle + 3deg), | ||||
|            fanSize * 11 / 50 * sin(startAngle + 3deg) | ||||
|          ], | ||||
|        ) | ||||
|     |> arc( | ||||
|          endAbsolute = [ | ||||
|            fanSize * 22 / 50 * cos(startAngle - 24), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 24) | ||||
|            fanSize * 22 / 50 * cos(startAngle - 24deg), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 24deg) | ||||
|          ], | ||||
|          interiorAbsolute = [ | ||||
|            fanSize * 22 / 50 * cos(startAngle - 22), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 22) | ||||
|            fanSize * 22 / 50 * cos(startAngle - 22deg), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 22deg) | ||||
|          ], | ||||
|        ) | ||||
|     |> arc( | ||||
|          endAbsolute = [profileStartX(%), profileStartY(%)], | ||||
|          interiorAbsolute = [ | ||||
|            fanSize * 11 / 50 * cos(startAngle - 5), | ||||
|            fanSize * 11 / 50 * sin(startAngle - 5) | ||||
|            fanSize * 11 / 50 * cos(startAngle - 5deg), | ||||
|            fanSize * 11 / 50 * sin(startAngle - 5deg) | ||||
|          ], | ||||
|        ) | ||||
|     |> close() | ||||
| @ -605,8 +605,8 @@ fn fanBlade(offsetHeight, startAngle: number(deg)) { | ||||
|  | ||||
| // Loft the fan blade cross sections into a single blade, then pattern them about the fan center | ||||
| crossSections = [ | ||||
|   fanBlade(offsetHeight = 4.5, startAngle = 50), | ||||
|   fanBlade(offsetHeight = (fanHeight - 2 - 4) / 2, startAngle = 30), | ||||
|   fanBlade(offsetHeight = 4.5, startAngle = 50deg), | ||||
|   fanBlade(offsetHeight = (fanHeight - 2 - 4) / 2, startAngle = 30deg), | ||||
|   fanBlade(offsetHeight = fanHeight - 2, startAngle = 0) | ||||
| ] | ||||
| loft(crossSections) | ||||
| @ -615,7 +615,7 @@ loft(crossSections) | ||||
|        instances = 9, | ||||
|        axis = [0, 0, 1], | ||||
|        center = [0, 0, 0], | ||||
|        arcDegrees = 360, | ||||
|        arcDegrees = 360deg, | ||||
|        rotateDuplicates = true, | ||||
|      ) | ||||
|  | ||||
| @ -650,11 +650,11 @@ ${modifiedFanHousingBrowser} | ||||
| fanCenter = startSketchOn(XZ) | ||||
|   |> startProfile(at = [-0.0001, fanHeight]) | ||||
|   |> xLine(endAbsolute = -15 + 1.5) | ||||
|   |> tangentialArc(radius = 1.5, angle = 90) | ||||
|   |> tangentialArc(radius = 1.5, angle = 90deg) | ||||
|   |> yLine(endAbsolute = 4.5) | ||||
|   |> xLine(endAbsolute = -13) | ||||
|   |> yLine(endAbsolute = profileStartY(%) - 5) | ||||
|   |> tangentialArc(radius = 1, angle = -90) | ||||
|   |> tangentialArc(radius = 1, angle = -90deg) | ||||
|   |> xLine(endAbsolute = -1) | ||||
|   |> yLine(length = 2) | ||||
|   |> xLine(length = -0.15) | ||||
| @ -678,32 +678,32 @@ fn fanBlade(offsetHeight, startAngle: number(deg)) { | ||||
|          15 * cos(startAngle), | ||||
|          15 * sin(startAngle) | ||||
|        ]) | ||||
|     |> arc(angleStart = startAngle, angleEnd = startAngle + 14, radius = 15) | ||||
|     |> arc(angleStart = startAngle, angleEnd = startAngle + 14deg, radius = 15) | ||||
|     |> arc( | ||||
|          endAbsolute = [ | ||||
|            fanSize * 22 / 50 * cos(startAngle - 20), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 20) | ||||
|            fanSize * 22 / 50 * cos(startAngle - 20deg), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 20deg) | ||||
|          ], | ||||
|          interiorAbsolute = [ | ||||
|            fanSize * 11 / 50 * cos(startAngle + 3), | ||||
|            fanSize * 11 / 50 * sin(startAngle + 3) | ||||
|            fanSize * 11 / 50 * cos(startAngle + 3deg), | ||||
|            fanSize * 11 / 50 * sin(startAngle + 3deg) | ||||
|          ], | ||||
|        ) | ||||
|     |> arc( | ||||
|          endAbsolute = [ | ||||
|            fanSize * 22 / 50 * cos(startAngle - 24), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 24) | ||||
|            fanSize * 22 / 50 * cos(startAngle - 24deg), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 24deg) | ||||
|          ], | ||||
|          interiorAbsolute = [ | ||||
|            fanSize * 22 / 50 * cos(startAngle - 22), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 22) | ||||
|            fanSize * 22 / 50 * cos(startAngle - 22deg), | ||||
|            fanSize * 22 / 50 * sin(startAngle - 22deg) | ||||
|          ], | ||||
|        ) | ||||
|     |> arc( | ||||
|          endAbsolute = [profileStartX(%), profileStartY(%)], | ||||
|          interiorAbsolute = [ | ||||
|            fanSize * 11 / 50 * cos(startAngle - 5), | ||||
|            fanSize * 11 / 50 * sin(startAngle - 5) | ||||
|            fanSize * 11 / 50 * cos(startAngle - 5deg), | ||||
|            fanSize * 11 / 50 * sin(startAngle - 5deg) | ||||
|          ], | ||||
|        ) | ||||
|     |> close() | ||||
| @ -712,8 +712,8 @@ fn fanBlade(offsetHeight, startAngle: number(deg)) { | ||||
|  | ||||
| // Loft the fan blade cross sections into a single blade, then pattern them about the fan center | ||||
| crossSections = [ | ||||
|   fanBlade(offsetHeight = 4.5, startAngle = 50), | ||||
|   fanBlade(offsetHeight = (fanHeight - 2 - 4) / 2, startAngle = 30), | ||||
|   fanBlade(offsetHeight = 4.5, startAngle = 50deg), | ||||
|   fanBlade(offsetHeight = (fanHeight - 2 - 4) / 2, startAngle = 30deg), | ||||
|   fanBlade(offsetHeight = fanHeight - 2, startAngle = 0) | ||||
| ] | ||||
| loft(crossSections) | ||||
| @ -722,7 +722,7 @@ loft(crossSections) | ||||
|        instances = 9, | ||||
|        axis = [0, 0, 1], | ||||
|        center = [0, 0, 0], | ||||
|        arcDegrees = 360, | ||||
|        arcDegrees = 360deg, | ||||
|        rotateDuplicates = true, | ||||
|      ) | ||||
|  | ||||
|  | ||||
| @ -3,11 +3,7 @@ import toast from 'react-hot-toast' | ||||
|  | ||||
| import { updateModelingState } from '@src/lang/modelingWorkflows' | ||||
| import { addModuleImport } from '@src/lang/modifyAst' | ||||
| import { | ||||
|   changeDefaultUnits, | ||||
|   unitAngleToUnitAng, | ||||
|   unitLengthToUnitLen, | ||||
| } from '@src/lang/wasm' | ||||
| import { changeDefaultUnits, unitLengthToUnitLen } from '@src/lang/wasm' | ||||
| import type { Command, CommandArgumentOption } from '@src/lib/commandTypes' | ||||
| import { | ||||
|   DEFAULT_DEFAULT_LENGTH_UNIT, | ||||
| @ -69,8 +65,7 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] { | ||||
|         if (typeof data === 'object' && 'unit' in data) { | ||||
|           const newCode = changeDefaultUnits( | ||||
|             codeManager.code, | ||||
|             unitLengthToUnitLen(data.unit), | ||||
|             unitAngleToUnitAng(undefined) | ||||
|             unitLengthToUnitLen(data.unit) | ||||
|           ) | ||||
|           if (err(newCode)) { | ||||
|             toast.error(`Failed to set per-file units: ${newCode.message}`) | ||||
|  | ||||
| @ -21,7 +21,7 @@ describe('library rectangleTool helper functions', () => { | ||||
|       const sourceCode = `sketch001 = startSketchOn(XZ) | ||||
| profile001 = startProfile(at = [120.37, 162.76]) | ||||
| |> angledLine(angle = 0, length = 0, tag = $rectangleSegmentA001) | ||||
| |> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = 0, tag = $rectangleSegmentB001) | ||||
| |> angledLine(angle = segAng(rectangleSegmentA001) + 90deg, length = 0, tag = $rectangleSegmentB001) | ||||
| |> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001) | ||||
| |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
| |> close() | ||||
| @ -71,7 +71,7 @@ profile001 = startProfile(at = [120.37, 162.76]) | ||||
|       const expectedSourceCode = `sketch001 = startSketchOn(XZ) | ||||
| profile001 = startProfile(at = [80, 120]) | ||||
|   |> angledLine(angle = 0, length = 80, tag = $rectangleSegmentA001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = 120, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001) + 90deg, length = 120, tag = $rectangleSegmentB001) | ||||
|   |> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001) | ||||
|   |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) | ||||
|   |> close() | ||||
|  | ||||
| @ -54,7 +54,7 @@ function angledLine( | ||||
| export const getRectangleCallExpressions = (tag: string) => { | ||||
|   return [ | ||||
|     angledLine( | ||||
|       createLiteral(0), // 0 deg | ||||
|       createLiteral(0, 'Deg'), // 0 deg | ||||
|       createLiteral(0), // This will be the width of the rectangle | ||||
|       tag | ||||
|     ), | ||||
| @ -62,7 +62,7 @@ export const getRectangleCallExpressions = (tag: string) => { | ||||
|       createBinaryExpression([ | ||||
|         createCallExpressionStdLibKw('segAng', createLocalName(tag), []), | ||||
|         '+', | ||||
|         createLiteral(90), | ||||
|         createLiteral(90, 'Deg'), | ||||
|       ]), // 90 offset from the previous line | ||||
|       createLiteral(0) // This will be the height of the rectangle | ||||
|     ), | ||||
| @ -108,7 +108,7 @@ export function updateRectangleSketch( | ||||
|   tag: string | ||||
| ) { | ||||
|   const firstEdge = pipeExpression.body[1] as CallExpressionKw | ||||
|   mutateKwArgOnly('angle', firstEdge, createLiteral(x >= 0 ? 0 : 180)) | ||||
|   mutateKwArgOnly('angle', firstEdge, createLiteral(x >= 0 ? 0 : 180, 'Deg')) | ||||
|   mutateKwArgOnly('length', firstEdge, createLiteral(Math.abs(x))) | ||||
|   const secondEdge = pipeExpression.body[2] as CallExpressionKw | ||||
|   // 90 offset from the previous line | ||||
| @ -118,7 +118,7 @@ export function updateRectangleSketch( | ||||
|     createBinaryExpression([ | ||||
|       createCallExpressionStdLibKw('segAng', createLocalName(tag), []), | ||||
|       Math.sign(y) === Math.sign(x) ? '+' : '-', | ||||
|       createLiteral(90), | ||||
|       createLiteral(90, 'Deg'), | ||||
|     ]) | ||||
|   ) | ||||
|   // This will be the height of the rectangle | ||||
| @ -196,7 +196,7 @@ export function updateCenterRectangleSketch( | ||||
|     const newAngle = createBinaryExpression([ | ||||
|       createCallExpressionStdLibKw('segAng', createLocalName(tag), []), | ||||
|       oldAngleOperator, | ||||
|       createLiteral(90), | ||||
|       createLiteral(90, 'Deg'), | ||||
|     ]) | ||||
|  | ||||
|     // Calculate new height. | ||||
|  | ||||
		Reference in New Issue
	
	Block a user