add Equal angle constraint + more cases for existing constraints (#69)

* add more setLength and horz vert distance constraints

* rename equal to equalLength

* Add equalAngle constraint
This commit is contained in:
Kurt Hutten
2023-03-17 21:15:46 +11:00
committed by GitHub
parent f7c78db92b
commit 0995780abb
9 changed files with 286 additions and 73 deletions

View File

@ -2,7 +2,8 @@ import { useStore, toolTips } from './useStore'
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst' import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
import { getNodePathFromSourceRange } from './lang/queryAst' import { getNodePathFromSourceRange } from './lang/queryAst'
import { HorzVert } from './components/Toolbar/HorzVert' import { HorzVert } from './components/Toolbar/HorzVert'
import { Equal } from './components/Toolbar/Equal' import { EqualLength } from './components/Toolbar/EqualLength'
import { EqualAngle } from './components/Toolbar/EqualAngle'
import { SetHorzDistance } from './components/Toolbar/SetHorzDistance' import { SetHorzDistance } from './components/Toolbar/SetHorzDistance'
import { SetAngleLength } from './components/Toolbar/SetAngleLength' import { SetAngleLength } from './components/Toolbar/SetAngleLength'
@ -157,7 +158,8 @@ export const Toolbar = () => {
<br></br> <br></br>
<HorzVert horOrVert="horizontal" /> <HorzVert horOrVert="horizontal" />
<HorzVert horOrVert="vertical" /> <HorzVert horOrVert="vertical" />
<Equal /> <EqualLength />
<EqualAngle />
<SetHorzDistance horOrVert="setHorzDistance" /> <SetHorzDistance horOrVert="setHorzDistance" />
<SetHorzDistance horOrVert="setVertDistance" /> <SetHorzDistance horOrVert="setVertDistance" />
<SetAngleLength angleOrLength="setAngle" /> <SetAngleLength angleOrLength="setAngle" />

View File

@ -0,0 +1,93 @@
import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore'
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTree'
import {
getNodePathFromSourceRange,
getNodeFromPath,
} from '../../lang/queryAst'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import {
TransformInfo,
transformSecondarySketchLinesTagFirst,
getTransformInfos,
} from '../../lang/std/sketchcombos'
export const EqualAngle = () => {
const { guiMode, selectionRanges, ast, programMemory, updateAst } = useStore(
(s) => ({
guiMode: s.guiMode,
ast: s.ast,
updateAst: s.updateAst,
selectionRanges: s.selectionRanges,
programMemory: s.programMemory,
})
)
const [enableEqual, setEnableEqual] = useState(false)
const [transformInfos, setTransformInfos] = useState<TransformInfo[]>()
useEffect(() => {
if (!ast) return
const paths = selectionRanges.map((selectionRange) =>
getNodePathFromSourceRange(ast, selectionRange)
)
const nodes = paths.map(
(pathToNode) => getNodeFromPath<Value>(ast, pathToNode).node
)
const varDecs = paths.map(
(pathToNode) =>
getNodeFromPath<VariableDeclarator>(
ast,
pathToNode,
'VariableDeclarator'
)?.node
)
const primaryLine = varDecs[0]
const secondaryVarDecs = varDecs.slice(1)
const isOthersLinkedToPrimary = secondaryVarDecs.every((secondary) =>
isSketchVariablesLinked(secondary, primaryLine, ast)
)
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
toolTips.includes(node.callee.name as any)
)
const theTransforms = getTransformInfos(
selectionRanges.slice(1),
ast,
'equalAngle'
)
setTransformInfos(theTransforms)
const _enableEqual =
!!secondaryVarDecs.length &&
isAllTooltips &&
isOthersLinkedToPrimary &&
theTransforms.every(Boolean)
setEnableEqual(_enableEqual)
}, [guiMode, selectionRanges])
if (guiMode.mode !== 'sketch') return null
return (
<button
onClick={() =>
transformInfos &&
ast &&
updateAst(
transformSecondarySketchLinesTagFirst({
ast,
selectionRanges,
transformInfos,
programMemory,
})?.modifiedAst
)
}
className={`border m-1 px-1 rounded text-xs ${
enableEqual ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400'
}`}
disabled={!enableEqual}
title="yo dawg"
>
EqualAngle
</button>
)
}

View File

@ -12,7 +12,7 @@ import {
getTransformInfos, getTransformInfos,
} from '../../lang/std/sketchcombos' } from '../../lang/std/sketchcombos'
export const Equal = () => { export const EqualLength = () => {
const { guiMode, selectionRanges, ast, programMemory, updateAst } = useStore( const { guiMode, selectionRanges, ast, programMemory, updateAst } = useStore(
(s) => ({ (s) => ({
guiMode: s.guiMode, guiMode: s.guiMode,
@ -87,7 +87,7 @@ export const Equal = () => {
disabled={!enableEqual} disabled={!enableEqual}
title="yo dawg" title="yo dawg"
> >
Equal EqualLength
</button> </button>
) )
} }

View File

@ -265,6 +265,7 @@ export const line: SketchLineHelper = {
to, to,
from, from,
replaceExisting, replaceExisting,
referencedSegment,
createCallback, createCallback,
}) => { }) => {
const _node = { ...node } const _node = { ...node }
@ -285,19 +286,25 @@ export const line: SketchLineHelper = {
const newXVal = createLiteral(roundOff(to[0] - from[0], 2)) const newXVal = createLiteral(roundOff(to[0] - from[0], 2))
const newYVal = createLiteral(roundOff(to[1] - from[1], 2)) const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
const newLine = createCallback if (replaceExisting && createCallback) {
? createCallback([newXVal, newYVal]).callExp const callIndex = getLastIndex(pathToNode)
: createCallExpression('line', [ const { callExp, valueUsedInTransform } = createCallback(
createArrayExpression([newXVal, newYVal]), [newXVal, newYVal],
createPipeSubstitution(), referencedSegment
]) )
const callIndex = getLastIndex(pathToNode) pipe.body[callIndex] = callExp
if (replaceExisting) { return {
pipe.body[callIndex] = newLine modifiedAst: _node,
} else { pathToNode,
pipe.body = [...pipe.body, newLine] valueUsedInTransform,
}
} }
const callExp = createCallExpression('line', [
createArrayExpression([newXVal, newYVal]),
createPipeSubstitution(),
])
pipe.body = [...pipe.body, callExp]
return { return {
modifiedAst: _node, modifiedAst: _node,
pathToNode, pathToNode,
@ -369,16 +376,22 @@ export const xLineTo: SketchLineHelper = {
const { node: pipe } = getNode<PipeExpression>('PipeExpression') const { node: pipe } = getNode<PipeExpression>('PipeExpression')
const newVal = createLiteral(roundOff(to[0], 2)) const newVal = createLiteral(roundOff(to[0], 2))
const newLine = createCallback
? createCallback([newVal, newVal]).callExp
: createCallExpression('xLineTo', [newVal, createPipeSubstitution()])
const callIndex = getLastIndex(pathToNode) if (replaceExisting && createCallback) {
if (replaceExisting) { const callIndex = getLastIndex(pathToNode)
pipe.body[callIndex] = newLine const { callExp, valueUsedInTransform } = createCallback([newVal, newVal])
} else { pipe.body[callIndex] = callExp
pipe.body = [...pipe.body, newLine] return {
modifiedAst: _node,
pathToNode,
valueUsedInTransform,
}
} }
const callExp = createCallExpression('xLineTo', [
newVal,
createPipeSubstitution(),
])
pipe.body = [...pipe.body, callExp]
return { return {
modifiedAst: _node, modifiedAst: _node,
pathToNode, pathToNode,
@ -430,15 +443,22 @@ export const yLineTo: SketchLineHelper = {
const { node: pipe } = getNode<PipeExpression>('PipeExpression') const { node: pipe } = getNode<PipeExpression>('PipeExpression')
const newVal = createLiteral(roundOff(to[1], 2)) const newVal = createLiteral(roundOff(to[1], 2))
const newLine = createCallback
? createCallback([newVal, newVal]).callExp if (replaceExisting && createCallback) {
: createCallExpression('yLineTo', [newVal, createPipeSubstitution()]) const callIndex = getLastIndex(pathToNode)
const callIndex = getLastIndex(pathToNode) const { callExp, valueUsedInTransform } = createCallback([newVal, newVal])
if (replaceExisting) { pipe.body[callIndex] = callExp
pipe.body[callIndex] = newLine return {
} else { modifiedAst: _node,
pipe.body = [...pipe.body, newLine] pathToNode,
valueUsedInTransform,
}
} }
const callExp = createCallExpression('yLineTo', [
newVal,
createPipeSubstitution(),
])
pipe.body = [...pipe.body, callExp]
return { return {
modifiedAst: _node, modifiedAst: _node,
pathToNode, pathToNode,
@ -640,7 +660,15 @@ export const angledLine: SketchLineHelper = {
value: [...sketchGroup.value, currentPath], value: [...sketchGroup.value, currentPath],
} }
}, },
add: ({ node, pathToNode, to, from, createCallback, replaceExisting }) => { add: ({
node,
pathToNode,
to,
from,
createCallback,
replaceExisting,
referencedSegment,
}) => {
const _node = { ...node } const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode) const getNode = getNodeFromPathCurry(_node, pathToNode)
const { node: pipe } = getNode<PipeExpression>('PipeExpression') const { node: pipe } = getNode<PipeExpression>('PipeExpression')
@ -652,12 +680,12 @@ export const angledLine: SketchLineHelper = {
createPipeSubstitution(), createPipeSubstitution(),
]) ])
const callIndex = getLastIndex(pathToNode)
if (replaceExisting && createCallback) { if (replaceExisting && createCallback) {
const { callExp, valueUsedInTransform } = createCallback([ const callIndex = getLastIndex(pathToNode)
newAngleVal, const { callExp, valueUsedInTransform } = createCallback(
newLengthVal, [newAngleVal, newLengthVal],
]) referencedSegment
)
pipe.body[callIndex] = callExp pipe.body[callIndex] = callExp
return { return {
modifiedAst: _node, modifiedAst: _node,

View File

@ -1,3 +1,4 @@
import { getAngle } from '../../lib/utils'
import { Range, TooTip, toolTips } from '../../useStore' import { Range, TooTip, toolTips } from '../../useStore'
import { import {
Program, Program,
@ -33,6 +34,17 @@ export const segLen: InternalFn = (
) )
} }
export const segAng: InternalFn = (
_,
segName: string,
sketchGroup: SketchGroup
): number => {
const line = sketchGroup?.value.find((seg) => seg.name === segName)
// maybe this should throw, but the language doesn't have a way to handle errors yet
if (!line) return 0
return getAngle(line.from, line.to)
}
function segEndFactory(which: 'x' | 'y'): InternalFn { function segEndFactory(which: 'x' | 'y'): InternalFn {
return (_, segName: string, sketchGroup: SketchGroup): number => { return (_, segName: string, sketchGroup: SketchGroup): number => {
const line = const line =

View File

@ -366,10 +366,10 @@ show(part001)`
'setVertDistance' 'setVertDistance'
) )
expect(expectedHorizontalCode).toContain( expect(expectedHorizontalCode).toContain(
`lineTo([segEndX('seg01', %) + 1.21, 4.59], %) // free` `lineTo([segEndX('seg01', %) + 0.9, 4.59], %) // free`
) )
expect(expectedVerticalCode).toContain( expect(expectedVerticalCode).toContain(
`lineTo([1.21, segEndY('seg01', %) + 4.59], %) // free` `lineTo([1.21, segEndY('seg01', %) + 2.92], %) // free`
) )
}) })
it('testing for xRelative to vertical distance', () => { it('testing for xRelative to vertical distance', () => {
@ -380,7 +380,7 @@ show(part001)`
) )
expect(expectedCode).toContain(`|> lineTo([ expect(expectedCode).toContain(`|> lineTo([
lastSegX(%) + myVar, lastSegX(%) + myVar,
segEndY('seg01', %) + 4.6 segEndY('seg01', %) + 2.93
], %) // xRelative`) ], %) // xRelative`)
}) })
it('testing for yRelative to horizontal distance', () => { it('testing for yRelative to horizontal distance', () => {
@ -390,7 +390,7 @@ show(part001)`
'setHorzDistance' 'setHorzDistance'
) )
expect(expectedCode).toContain(`|> lineTo([ expect(expectedCode).toContain(`|> lineTo([
segEndX('seg01', %) + 2.91, segEndX('seg01', %) + 2.6,
lastSegY(%) + myVar lastSegY(%) + myVar
], %) // yRelative`) ], %) // yRelative`)
}) })

View File

@ -1,5 +1,5 @@
import { TransformCallback } from './stdTypes' import { TransformCallback } from './stdTypes'
import { Ranges, toolTips, TooTip } from '../../useStore' import { Ranges, toolTips, TooTip, Range } from '../../useStore'
import { import {
BinaryPart, BinaryPart,
CallExpression, CallExpression,
@ -24,7 +24,7 @@ import {
import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch' import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch'
import { ProgramMemory } from '../executor' import { ProgramMemory } from '../executor'
import { getSketchSegmentIndexFromSourceRange } from './sketchConstraints' import { getSketchSegmentIndexFromSourceRange } from './sketchConstraints'
import { roundOff } from '../../lib/utils' import { getAngle, roundOff } from '../../lib/utils'
type LineInputsType = type LineInputsType =
| 'xAbsolute' | 'xAbsolute'
@ -38,7 +38,7 @@ export type ConstraintType =
| 'equalLength' | 'equalLength'
| 'vertical' | 'vertical'
| 'horizontal' | 'horizontal'
| 'equalangle' | 'equalAngle'
| 'setHorzDistance' | 'setHorzDistance'
| 'setVertDistance' | 'setVertDistance'
| 'setAngle' | 'setAngle'
@ -85,7 +85,6 @@ const xyLineSetLength =
): TransformInfo['createNode'] => ): TransformInfo['createNode'] =>
({ referenceSegName, tag, forceValueUsedInTransform }) => ({ referenceSegName, tag, forceValueUsedInTransform }) =>
(args) => { (args) => {
console.log('args', args)
const segRef = createSegLen(referenceSegName) const segRef = createSegLen(referenceSegName)
const lineVal = forceValueUsedInTransform const lineVal = forceValueUsedInTransform
? forceValueUsedInTransform ? forceValueUsedInTransform
@ -102,12 +101,17 @@ const basicAngledLineCreateNode =
varValToUse: 'ang' | 'len' | 'none' = 'none' varValToUse: 'ang' | 'len' | 'none' = 'none'
): TransformInfo['createNode'] => ): TransformInfo['createNode'] =>
({ referenceSegName, tag, forceValueUsedInTransform, varValA, varValB }) => ({ referenceSegName, tag, forceValueUsedInTransform, varValA, varValB }) =>
(args) => { (args, path) => {
const refAng = path ? getAngle(path?.from, path?.to) : 0
const nonForcedAng = const nonForcedAng =
varValToUse === 'ang' varValToUse === 'ang'
? varValA ? varValA
: referenceSeg === 'ang' : referenceSeg === 'ang'
? createSegAngle(referenceSegName) ? getClosesAngleDirection(
args[0],
refAng,
createSegAngle(referenceSegName) as BinaryPart
)
: args[0] : args[0]
const nonForcedLen = const nonForcedLen =
varValToUse === 'len' varValToUse === 'len'
@ -186,6 +190,19 @@ const getAngleLengthSign = (arg: Value, legAngleVal: BinaryPart) => {
return normalisedAngle > 90 ? createUnaryExpression(legAngleVal) : legAngleVal return normalisedAngle > 90 ? createUnaryExpression(legAngleVal) : legAngleVal
} }
function getClosesAngleDirection(
arg: Value,
refAngle: number,
angleVal: BinaryPart
) {
const currentAng = (arg.type === 'Literal' && Number(arg.value)) || 0
const angDiff = Math.abs(currentAng - refAngle)
const normalisedAngle = ((angDiff % 360) + 360) % 360 // between 0 and 180
return normalisedAngle > 90
? createBinaryExpression([angleVal, '+', createLiteral(180)])
: angleVal
}
const setHorzVertDistanceCreateNode = const setHorzVertDistanceCreateNode =
( (
xOrY: 'x' | 'y', xOrY: 'x' | 'y',
@ -211,6 +228,55 @@ const setHorzVertDistanceCreateNode =
) )
} }
} }
const setHorzVertDistanceForAngleLineCreateNode =
(
xOrY: 'x' | 'y',
index = xOrY === 'x' ? 0 : 1
): TransformInfo['createNode'] =>
({ referenceSegName, tag, forceValueUsedInTransform, varValA }) => {
return (args, referencedSegment) => {
const valueUsedInTransform = roundOff(
getArgLiteralVal(args?.[1]) - (referencedSegment?.to?.[index] || 0),
2
)
const makeBinExp = createBinaryExpression([
createSegEnd(referenceSegName, !index),
'+',
(forceValueUsedInTransform as BinaryPart) ||
createLiteral(valueUsedInTransform),
])
return createCallWrapper(
xOrY === 'x' ? 'angledLineToX' : 'angledLineToY',
[varValA, makeBinExp],
tag,
valueUsedInTransform
)
}
}
const setHorVertDistanceForXYLines =
(xOrY: 'x' | 'y'): TransformInfo['createNode'] =>
({ referenceSegName, tag, forceValueUsedInTransform }) => {
return (args, referencedSegment) => {
const index = xOrY === 'x' ? 0 : 1
const valueUsedInTransform = roundOff(
getArgLiteralVal(args?.[index]) - (referencedSegment?.to?.[index] || 0),
2
)
const makeBinExp = createBinaryExpression([
createSegEnd(referenceSegName, xOrY === 'x'),
'+',
(forceValueUsedInTransform as BinaryPart) ||
createLiteral(valueUsedInTransform),
])
return createCallWrapper(
xOrY === 'x' ? 'xLineTo' : 'yLineTo',
makeBinExp,
tag,
valueUsedInTransform
)
}
}
const setHorzVertDistanceConstraintLineCreateNode = const setHorzVertDistanceConstraintLineCreateNode =
(isX: boolean): TransformInfo['createNode'] => (isX: boolean): TransformInfo['createNode'] =>
@ -334,6 +400,10 @@ const transformMap: TransformMap = {
tooltip: 'angledLine', tooltip: 'angledLine',
createNode: basicAngledLineCreateNode('none', 'len'), createNode: basicAngledLineCreateNode('none', 'len'),
}, },
equalAngle: {
tooltip: 'angledLine',
createNode: basicAngledLineCreateNode('ang'),
},
}, },
}, },
lineTo: { lineTo: {
@ -419,7 +489,6 @@ const transformMap: TransformMap = {
createNode: createNode:
({ varValB, tag, forceValueUsedInTransform }) => ({ varValB, tag, forceValueUsedInTransform }) =>
(args) => { (args) => {
console.log(getArgLiteralVal(args[0]))
return createCallWrapper( return createCallWrapper(
'angledLineToY', 'angledLineToY',
[forceValueUsedInTransform || args[0], varValB], [forceValueUsedInTransform || args[0], varValB],
@ -447,6 +516,14 @@ const transformMap: TransformMap = {
tooltip: 'angledLine', tooltip: 'angledLine',
createNode: basicAngledLineCreateNode('none', 'len', 'ang'), createNode: basicAngledLineCreateNode('none', 'len', 'ang'),
}, },
setVertDistance: {
tooltip: 'angledLineToY',
createNode: setHorzVertDistanceForAngleLineCreateNode('y'),
},
setHorzDistance: {
tooltip: 'angledLineToX',
createNode: setHorzVertDistanceForAngleLineCreateNode('x'),
},
}, },
free: { free: {
equalLength: { equalLength: {
@ -715,27 +792,7 @@ const transformMap: TransformMap = {
}, },
setHorzDistance: { setHorzDistance: {
tooltip: 'xLineTo', tooltip: 'xLineTo',
createNode: ({ referenceSegName, tag, forceValueUsedInTransform }) => { createNode: setHorVertDistanceForXYLines('x'),
return (args, referencedSegment) => {
console.log('args', args)
const valueUsedInTransform = roundOff(
getArgLiteralVal(args?.[0]) - (referencedSegment?.to?.[0] || 0),
2
)
const makeBinExp = createBinaryExpression([
createSegEnd(referenceSegName, true),
'+',
(forceValueUsedInTransform as BinaryPart) ||
createLiteral(valueUsedInTransform),
])
return createCallWrapper(
'xLineTo',
makeBinExp,
tag,
valueUsedInTransform
)
}
},
}, },
setLength: { setLength: {
tooltip: 'xLine', tooltip: 'xLine',
@ -756,6 +813,10 @@ const transformMap: TransformMap = {
tooltip: 'yLine', tooltip: 'yLine',
createNode: xyLineSetLength('yLine'), createNode: xyLineSetLength('yLine'),
}, },
setVertDistance: {
tooltip: 'yLineTo',
createNode: setHorVertDistanceForXYLines('y'),
},
}, },
}, },
xLineTo: { xLineTo: {
@ -767,6 +828,10 @@ const transformMap: TransformMap = {
() => () =>
createCallWrapper('xLine', createSegLen(referenceSegName), tag), createCallWrapper('xLine', createSegLen(referenceSegName), tag),
}, },
setLength: {
tooltip: 'xLine',
createNode: xyLineSetLength('xLine'),
},
}, },
}, },
yLineTo: { yLineTo: {
@ -778,6 +843,10 @@ const transformMap: TransformMap = {
() => () =>
createCallWrapper('yLine', createSegLen(referenceSegName), tag), createCallWrapper('yLine', createSegLen(referenceSegName), tag),
}, },
setLength: {
tooltip: 'yLine',
createNode: xyLineSetLength('yLine'),
},
}, },
}, },
} }
@ -946,6 +1015,7 @@ export function transformSecondarySketchLinesTagFirst({
...transformAstSketchLines({ ...transformAstSketchLines({
ast: modifiedAst, ast: modifiedAst,
selectionRanges: selectionRanges.slice(1), selectionRanges: selectionRanges.slice(1),
referencedSegmentRange: primarySelection,
transformInfos, transformInfos,
programMemory, programMemory,
referenceSegName: tag, referenceSegName: tag,
@ -965,6 +1035,7 @@ export function transformAstSketchLines({
programMemory, programMemory,
referenceSegName, referenceSegName,
forceValueUsedInTransform, forceValueUsedInTransform,
referencedSegmentRange,
}: { }: {
ast: Program ast: Program
selectionRanges: Ranges selectionRanges: Ranges
@ -972,6 +1043,7 @@ export function transformAstSketchLines({
programMemory: ProgramMemory programMemory: ProgramMemory
referenceSegName: string referenceSegName: string
forceValueUsedInTransform?: Value forceValueUsedInTransform?: Value
referencedSegmentRange?: Range
}): { modifiedAst: Program; valueUsedInTransform?: number } { }): { modifiedAst: Program; valueUsedInTransform?: number } {
// deep clone since we are mutating in a loop, of which any could fail // deep clone since we are mutating in a loop, of which any could fail
let node = JSON.parse(JSON.stringify(ast)) let node = JSON.parse(JSON.stringify(ast))
@ -998,9 +1070,12 @@ export function transformAstSketchLines({
if (!sketchGroup || sketchGroup.type !== 'sketchGroup') if (!sketchGroup || sketchGroup.type !== 'sketchGroup')
throw new Error('not a sketch group') throw new Error('not a sketch group')
const seg = getSketchSegmentIndexFromSourceRange(sketchGroup, range) const seg = getSketchSegmentIndexFromSourceRange(sketchGroup, range)
const referencedSegment = sketchGroup.value.find( const referencedSegment = referencedSegmentRange
(path) => path.name === referenceSegName ? getSketchSegmentIndexFromSourceRange(
) sketchGroup,
referencedSegmentRange
)
: sketchGroup.value.find((path) => path.name === referenceSegName)
const { to, from } = seg const { to, from } = seg
const { modifiedAst, valueUsedInTransform } = replaceSketchLine({ const { modifiedAst, valueUsedInTransform } = replaceSketchLine({
node: node, node: node,
@ -1035,7 +1110,7 @@ function createSegLen(referenceSegName: string): Value {
} }
function createSegAngle(referenceSegName: string): Value { function createSegAngle(referenceSegName: string): Value {
return createCallExpression('segAngle', [ return createCallExpression('segAng', [
createLiteral(referenceSegName), createLiteral(referenceSegName),
createPipeSubstitution(), createPipeSubstitution(),
]) ])

View File

@ -16,6 +16,7 @@ import {
} from './sketch' } from './sketch'
import { import {
segLen, segLen,
segAng,
angleToMatchLengthX, angleToMatchLengthX,
angleToMatchLengthY, angleToMatchLengthY,
segEndX, segEndX,
@ -143,6 +144,7 @@ export const internalFns: { [key in InternalFnNames]: InternalFn } = {
lastSegX, lastSegX,
lastSegY, lastSegY,
segLen, segLen,
segAng,
angleToMatchLengthX, angleToMatchLengthX,
angleToMatchLengthY, angleToMatchLengthY,
lineTo: lineTo.fn, lineTo: lineTo.fn,

View File

@ -29,6 +29,7 @@ export type InternalFnNames =
| 'lastSegX' | 'lastSegX'
| 'lastSegY' | 'lastSegY'
| 'segLen' | 'segLen'
| 'segAng'
| 'angleToMatchLengthX' | 'angleToMatchLengthX'
| 'angleToMatchLengthY' | 'angleToMatchLengthY'
| 'rx' | 'rx'