Add sketch on extrude face functionality
This commit is contained in:
@ -84,7 +84,6 @@ function MovingSphere({
|
|||||||
let theNewPoints: [number, number] = [x, y]
|
let theNewPoints: [number, number] = [x, y]
|
||||||
const { modifiedAst } = changeArguments(ast, thePath, theNewPoints)
|
const { modifiedAst } = changeArguments(ast, thePath, theNewPoints)
|
||||||
updateAst(modifiedAst)
|
updateAst(modifiedAst)
|
||||||
console.log('reset position')
|
|
||||||
ref.current.position.set(...position)
|
ref.current.position.set(...position)
|
||||||
}
|
}
|
||||||
setIsMouseDown(false)
|
setIsMouseDown(false)
|
||||||
|
@ -199,6 +199,23 @@ function makeArguments(
|
|||||||
expression,
|
expression,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
argumentToken.token.type === 'brace' &&
|
||||||
|
argumentToken.token.value === '{'
|
||||||
|
) {
|
||||||
|
const { expression, lastIndex } = makeObjectExpression(
|
||||||
|
tokens,
|
||||||
|
argumentToken.index
|
||||||
|
)
|
||||||
|
const nextCommarOrBraceTokenIndex = nextMeaningfulToken(
|
||||||
|
tokens,
|
||||||
|
lastIndex
|
||||||
|
).index
|
||||||
|
return makeArguments(tokens, nextCommarOrBraceTokenIndex, [
|
||||||
|
...previousArgs,
|
||||||
|
expression,
|
||||||
|
])
|
||||||
|
}
|
||||||
if (!isIdentifierOrLiteral) {
|
if (!isIdentifierOrLiteral) {
|
||||||
const { expression, lastIndex } = makeBinaryExpression(tokens, index)
|
const { expression, lastIndex } = makeBinaryExpression(tokens, index)
|
||||||
return makeArguments(tokens, lastIndex, [...previousArgs, expression])
|
return makeArguments(tokens, lastIndex, [...previousArgs, expression])
|
||||||
@ -217,6 +234,25 @@ function makeArguments(
|
|||||||
value,
|
value,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
argumentToken.token.type === 'word' &&
|
||||||
|
nextBraceOrCommaToken.token.type === 'brace' &&
|
||||||
|
nextBraceOrCommaToken.token.value === '('
|
||||||
|
) {
|
||||||
|
const { expression, lastIndex } = makeCallExpression(
|
||||||
|
tokens,
|
||||||
|
argumentToken.index
|
||||||
|
)
|
||||||
|
const nextCommarOrBraceTokenIndex = nextMeaningfulToken(
|
||||||
|
tokens,
|
||||||
|
lastIndex
|
||||||
|
).index
|
||||||
|
return makeArguments(tokens, nextCommarOrBraceTokenIndex, [
|
||||||
|
...previousArgs,
|
||||||
|
expression,
|
||||||
|
])
|
||||||
|
}
|
||||||
if (argumentToken.token.type === 'word') {
|
if (argumentToken.token.type === 'word') {
|
||||||
const identifier = makeIdentifier(tokens, argumentToken.index)
|
const identifier = makeIdentifier(tokens, argumentToken.index)
|
||||||
return makeArguments(tokens, nextBraceOrCommaToken.index, [
|
return makeArguments(tokens, nextBraceOrCommaToken.index, [
|
||||||
|
@ -76,8 +76,13 @@ show(mySketch001)`
|
|||||||
value: [
|
value: [
|
||||||
{
|
{
|
||||||
type: 'extrudePlane',
|
type: 'extrudePlane',
|
||||||
position: [0, 0, 0],
|
position: [
|
||||||
rotation: [0.3826834323650898, 0, 0, 0.9238795325112867],
|
-0.5650000000000001, -2.602152954766495, -2.602152954766495,
|
||||||
|
],
|
||||||
|
rotation: [
|
||||||
|
0.20394238048109659, 0.7817509623502217, -0.3238118510036805,
|
||||||
|
0.4923604609001174,
|
||||||
|
],
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
geo: 'PlaneGeometry',
|
geo: 'PlaneGeometry',
|
||||||
sourceRange: [47, 66],
|
sourceRange: [47, 66],
|
||||||
@ -97,6 +102,132 @@ show(mySketch001)`
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
test('sketch extrude and sketch on one of the faces', () => {
|
||||||
|
const code = `
|
||||||
|
sketch sk1 {
|
||||||
|
lineTo(-2.5, 0)
|
||||||
|
path p = lineTo(0, 10)
|
||||||
|
lineTo(2.5, 0)
|
||||||
|
}
|
||||||
|
|> rx(45, %)
|
||||||
|
|> translate([1,0,1], %)
|
||||||
|
|> ry(5, %)
|
||||||
|
const theExtrude = extrude(2, sk1)
|
||||||
|
const theTransf = getExtrudeWallTransform('p', theExtrude)
|
||||||
|
sketch sk2 {
|
||||||
|
lineTo(-2.5, 0)
|
||||||
|
path p = lineTo(0, 3)
|
||||||
|
lineTo(2.5, 0)
|
||||||
|
}
|
||||||
|
|> transform(theTransf, %)
|
||||||
|
|> extrude(2, %)
|
||||||
|
|
||||||
|
|
||||||
|
show(theExtrude, sk2)`
|
||||||
|
const programMemory = executor(abstractSyntaxTree(lexer(code)))
|
||||||
|
const geos = programMemory?.return?.map(
|
||||||
|
(a) => programMemory?.root?.[a.name]
|
||||||
|
)
|
||||||
|
const artifactsWithoutGeos = removeGeo(geos as any)
|
||||||
|
expect(artifactsWithoutGeos).toEqual([
|
||||||
|
{
|
||||||
|
type: 'extrudeGroup',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
type: 'extrudePlane',
|
||||||
|
position: [
|
||||||
|
0.14624915180581843, 3.5355339059327373, 4.540063765792454,
|
||||||
|
],
|
||||||
|
rotation: [
|
||||||
|
-0.24844095888221532, 0.7523143130765927, -0.2910733573455524,
|
||||||
|
-0.5362616571538269,
|
||||||
|
],
|
||||||
|
__geoMeta: {
|
||||||
|
geo: 'PlaneGeometry',
|
||||||
|
sourceRange: [39, 56],
|
||||||
|
pathToNode: [],
|
||||||
|
},
|
||||||
|
name: 'p',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'extrudePlane',
|
||||||
|
position: [
|
||||||
|
2.636735897035183, 3.5355339059327386, 4.322174408923308,
|
||||||
|
],
|
||||||
|
rotation: [
|
||||||
|
0.22212685137378593, 0.7027132469491032, -0.3116187916437232,
|
||||||
|
0.5997895323824204,
|
||||||
|
],
|
||||||
|
__geoMeta: {
|
||||||
|
geo: 'PlaneGeometry',
|
||||||
|
sourceRange: [59, 73],
|
||||||
|
pathToNode: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
height: 2,
|
||||||
|
position: [1.083350440839404, 0, 0.9090389553440874],
|
||||||
|
rotation: [
|
||||||
|
0.38231920253318413, 0.04029905920751535, -0.01669241687462921,
|
||||||
|
0.9230002039112792,
|
||||||
|
],
|
||||||
|
__meta: [
|
||||||
|
{
|
||||||
|
sourceRange: [138, 166],
|
||||||
|
pathToNode: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'extrudeGroup',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
type: 'extrudePlane',
|
||||||
|
position: [
|
||||||
|
0.43055783927228125, 5.453687003425103, 4.311246666755821,
|
||||||
|
],
|
||||||
|
rotation: [
|
||||||
|
0.5307054034531232, -0.4972416536396126, 0.3641462373475848,
|
||||||
|
-0.5818075544860157,
|
||||||
|
],
|
||||||
|
__geoMeta: {
|
||||||
|
geo: 'PlaneGeometry',
|
||||||
|
sourceRange: [264, 280],
|
||||||
|
pathToNode: [],
|
||||||
|
},
|
||||||
|
name: 'p',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'extrudePlane',
|
||||||
|
position: [
|
||||||
|
-0.3229447858093035, 3.7387011520000146, 2.6556327856208117,
|
||||||
|
],
|
||||||
|
rotation: [
|
||||||
|
0.06000443169260189, 0.12863059446321826, 0.6408199244764428,
|
||||||
|
-0.7544557394170275,
|
||||||
|
],
|
||||||
|
__geoMeta: {
|
||||||
|
geo: 'PlaneGeometry',
|
||||||
|
sourceRange: [283, 297],
|
||||||
|
pathToNode: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
height: 2,
|
||||||
|
position: [0.14624915180581843, 3.5355339059327373, 4.540063765792454],
|
||||||
|
rotation: [
|
||||||
|
0.24844095888221532, -0.7523143130765927, 0.2910733573455524,
|
||||||
|
-0.5362616571538269,
|
||||||
|
],
|
||||||
|
__meta: [
|
||||||
|
{
|
||||||
|
sourceRange: [334, 347],
|
||||||
|
pathToNode: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function removeGeo(arts: (SketchGroup | ExtrudeGroup)[]): any {
|
function removeGeo(arts: (SketchGroup | ExtrudeGroup)[]): any {
|
||||||
|
@ -3,7 +3,10 @@ import {
|
|||||||
SphereGeometry,
|
SphereGeometry,
|
||||||
BufferGeometry,
|
BufferGeometry,
|
||||||
PlaneGeometry,
|
PlaneGeometry,
|
||||||
|
Quaternion,
|
||||||
|
Euler,
|
||||||
} from 'three'
|
} from 'three'
|
||||||
|
import { Rotation, Position } from './executor'
|
||||||
|
|
||||||
export function baseGeo({ from }: { from: [number, number, number] }) {
|
export function baseGeo({ from }: { from: [number, number, number] }) {
|
||||||
const baseSphere = new SphereGeometry(0.25)
|
const baseSphere = new SphereGeometry(0.25)
|
||||||
@ -99,9 +102,13 @@ export function extrudeGeo({
|
|||||||
from: [number, number, number]
|
from: [number, number, number]
|
||||||
to: [number, number, number]
|
to: [number, number, number]
|
||||||
length: number
|
length: number
|
||||||
}): BufferGeometry {
|
}): {
|
||||||
|
geo: BufferGeometry
|
||||||
|
position: Position
|
||||||
|
rotation: Rotation
|
||||||
|
} {
|
||||||
const {
|
const {
|
||||||
// centre,
|
centre,
|
||||||
Hypotenuse: Hypotenuse3d,
|
Hypotenuse: Hypotenuse3d,
|
||||||
ry,
|
ry,
|
||||||
rz,
|
rz,
|
||||||
@ -116,5 +123,13 @@ export function extrudeGeo({
|
|||||||
face.rotateZ(rz)
|
face.rotateZ(rz)
|
||||||
face.translate(to[0], to[1], to[2])
|
face.translate(to[0], to[1], to[2])
|
||||||
|
|
||||||
return face
|
const quat = new Quaternion()
|
||||||
|
const euler = new Euler(-Math.PI / 2, ry, rz * sign, 'XYZ')
|
||||||
|
quat.setFromEuler(euler)
|
||||||
|
|
||||||
|
return {
|
||||||
|
geo: face,
|
||||||
|
position: [centre[0], centre[1], centre[2]],
|
||||||
|
rotation: quat.toArray() as Rotation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
ObjectExpression,
|
ObjectExpression,
|
||||||
MemberExpression,
|
MemberExpression,
|
||||||
Identifier,
|
Identifier,
|
||||||
|
CallExpression,
|
||||||
} from './abstractSyntaxTree'
|
} from './abstractSyntaxTree'
|
||||||
import { sketchFns } from './sketch'
|
import { sketchFns } from './sketch'
|
||||||
import { BufferGeometry } from 'three'
|
import { BufferGeometry } from 'three'
|
||||||
@ -71,6 +72,7 @@ interface ExtrudePlane {
|
|||||||
type: 'extrudePlane'
|
type: 'extrudePlane'
|
||||||
position: Position
|
position: Position
|
||||||
rotation: Rotation
|
rotation: Rotation
|
||||||
|
name?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ExtrudeSurface = GeoMeta &
|
export type ExtrudeSurface = GeoMeta &
|
||||||
@ -272,13 +274,19 @@ export const executor = (
|
|||||||
__meta,
|
__meta,
|
||||||
}
|
}
|
||||||
} else if (declaration.init.type === 'CallExpression') {
|
} else if (declaration.init.type === 'CallExpression') {
|
||||||
|
// TODO: use executeCallExpression here instead
|
||||||
const functionName = declaration.init.callee.name
|
const functionName = declaration.init.callee.name
|
||||||
const fnArgs = declaration.init.arguments.map((arg) => {
|
const fnArgs = declaration.init.arguments.map((arg) => {
|
||||||
if (arg.type === 'Literal') {
|
if (arg.type === 'Literal') {
|
||||||
return arg.value
|
return arg.value
|
||||||
} else if (arg.type === 'Identifier') {
|
} else if (arg.type === 'Identifier') {
|
||||||
return _programMemory.root[arg.name].value
|
return _programMemory.root[arg.name].value
|
||||||
|
} else if (arg.type === 'ObjectExpression') {
|
||||||
|
return executeObjectExpression(_programMemory, arg)
|
||||||
}
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Unexpected argument type ${arg.type} in function call`
|
||||||
|
)
|
||||||
})
|
})
|
||||||
if (
|
if (
|
||||||
'lineTo' === functionName ||
|
'lineTo' === functionName ||
|
||||||
@ -331,7 +339,10 @@ export const executor = (
|
|||||||
sketchVal as any // todo memory redo
|
sketchVal as any // todo memory redo
|
||||||
)
|
)
|
||||||
_programMemory.root[variableName] = result as any // todo memory redo
|
_programMemory.root[variableName] = result as any // todo memory redo
|
||||||
} else if (functionName === 'translate') {
|
} else if (
|
||||||
|
functionName === 'translate' ||
|
||||||
|
functionName === 'transform'
|
||||||
|
) {
|
||||||
const sketch = declaration.init.arguments[1]
|
const sketch = declaration.init.arguments[1]
|
||||||
if (sketch.type !== 'Identifier')
|
if (sketch.type !== 'Identifier')
|
||||||
throw new Error('rx must be called with an identifier')
|
throw new Error('rx must be called with an identifier')
|
||||||
@ -343,6 +354,22 @@ export const executor = (
|
|||||||
sketchVal as any // todo memory redo
|
sketchVal as any // todo memory redo
|
||||||
)
|
)
|
||||||
_programMemory.root[variableName] = result as any // todo memory redo
|
_programMemory.root[variableName] = result as any // todo memory redo
|
||||||
|
} else if (functionName === 'getExtrudeWallTransform') {
|
||||||
|
const extrude = declaration.init.arguments[1]
|
||||||
|
if (extrude.type !== 'Identifier')
|
||||||
|
throw new Error('rx must be called with an identifier')
|
||||||
|
const sketchVal = _programMemory.root[extrude.name]
|
||||||
|
const value = sketchFns[functionName](
|
||||||
|
_programMemory,
|
||||||
|
[declaration.start, declaration.end],
|
||||||
|
fnArgs[0],
|
||||||
|
sketchVal as any // todo memory redo
|
||||||
|
)
|
||||||
|
_programMemory.root[variableName] = {
|
||||||
|
type: 'userVal',
|
||||||
|
value,
|
||||||
|
__meta,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_programMemory.root[variableName] = {
|
_programMemory.root[variableName] = {
|
||||||
type: 'userVal',
|
type: 'userVal',
|
||||||
@ -472,85 +499,16 @@ function executePipeBody(
|
|||||||
[...previousResults, result]
|
[...previousResults, result]
|
||||||
)
|
)
|
||||||
} else if (expression.type === 'CallExpression') {
|
} else if (expression.type === 'CallExpression') {
|
||||||
const functionName = expression.callee.name
|
return executeCallExpression(
|
||||||
const fnArgs = expression.arguments.map((arg) => {
|
|
||||||
if (arg.type === 'Literal') {
|
|
||||||
return arg.value
|
|
||||||
} else if (arg.type === 'Identifier') {
|
|
||||||
return programMemory.root[arg.name]
|
|
||||||
} else if (arg.type === 'PipeSubstitution') {
|
|
||||||
return previousResults[expressionIndex - 1]
|
|
||||||
} else if (arg.type === 'ArrayExpression') {
|
|
||||||
return arg.elements.map((el) => {
|
|
||||||
if (el.type === 'Literal') {
|
|
||||||
return el.value
|
|
||||||
} else if (el.type === 'Identifier') {
|
|
||||||
return programMemory.root[el.name]
|
|
||||||
} else if (el.type === 'BinaryExpression') {
|
|
||||||
return getBinaryExpressionResult(el, programMemory)
|
|
||||||
}
|
|
||||||
throw new Error('Invalid argument type')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
throw new Error('Invalid argument type')
|
|
||||||
})
|
|
||||||
if (
|
|
||||||
'rx' === functionName ||
|
|
||||||
'ry' === functionName ||
|
|
||||||
'rz' === functionName
|
|
||||||
) {
|
|
||||||
const result = sketchFns[functionName](
|
|
||||||
programMemory,
|
|
||||||
[expression.start, expression.end],
|
|
||||||
fnArgs[0],
|
|
||||||
fnArgs[1]
|
|
||||||
)
|
|
||||||
return executePipeBody(
|
|
||||||
body,
|
|
||||||
programMemory,
|
programMemory,
|
||||||
|
expression,
|
||||||
previousPathToNode,
|
previousPathToNode,
|
||||||
expressionIndex + 1,
|
{
|
||||||
[...previousResults, result]
|
isInPipe: true,
|
||||||
)
|
previousResults,
|
||||||
}
|
expressionIndex,
|
||||||
if (functionName === 'extrude') {
|
|
||||||
const result = sketchFns[functionName](
|
|
||||||
programMemory,
|
|
||||||
'yo',
|
|
||||||
[expression.start, expression.end],
|
|
||||||
fnArgs[0],
|
|
||||||
fnArgs[1]
|
|
||||||
)
|
|
||||||
return executePipeBody(
|
|
||||||
body,
|
body,
|
||||||
programMemory,
|
|
||||||
previousPathToNode,
|
|
||||||
expressionIndex + 1,
|
|
||||||
[...previousResults, result]
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (functionName === 'translate') {
|
|
||||||
const result = sketchFns[functionName](
|
|
||||||
programMemory,
|
|
||||||
[expression.start, expression.end],
|
|
||||||
fnArgs[0],
|
|
||||||
fnArgs[1]
|
|
||||||
)
|
|
||||||
return executePipeBody(
|
|
||||||
body,
|
|
||||||
programMemory,
|
|
||||||
previousPathToNode,
|
|
||||||
expressionIndex + 1,
|
|
||||||
[...previousResults, result]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
const result = programMemory.root[functionName].value(...fnArgs)
|
|
||||||
return executePipeBody(
|
|
||||||
body,
|
|
||||||
programMemory,
|
|
||||||
previousPathToNode,
|
|
||||||
expressionIndex + 1,
|
|
||||||
[...previousResults, result]
|
|
||||||
)
|
)
|
||||||
} else if (expression.type === 'SketchExpression') {
|
} else if (expression.type === 'SketchExpression') {
|
||||||
const sketchBody = expression.body
|
const sketchBody = expression.body
|
||||||
@ -613,6 +571,19 @@ function executeObjectExpression(
|
|||||||
_programMemory,
|
_programMemory,
|
||||||
property.value
|
property.value
|
||||||
)
|
)
|
||||||
|
} else if (property.value.type === 'ArrayExpression') {
|
||||||
|
obj[property.key.name] = property.value.elements.map((el) => {
|
||||||
|
if (el.type === 'Literal') {
|
||||||
|
return el.value
|
||||||
|
} else if (el.type === 'Identifier') {
|
||||||
|
return _programMemory.root[el.name].value
|
||||||
|
} else if (el.type === 'BinaryExpression') {
|
||||||
|
return getBinaryExpressionResult(el, _programMemory)
|
||||||
|
} else if (el.type === 'ObjectExpression') {
|
||||||
|
return executeObjectExpression(_programMemory, el)
|
||||||
|
}
|
||||||
|
throw new Error('Invalid argument type')
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unexpected property type ${property.value.type} in object expression`
|
`Unexpected property type ${property.value.type} in object expression`
|
||||||
@ -626,3 +597,131 @@ function executeObjectExpression(
|
|||||||
})
|
})
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function executeCallExpression(
|
||||||
|
programMemory: ProgramMemory,
|
||||||
|
expression: CallExpression,
|
||||||
|
previousPathToNode: PathToNode = [],
|
||||||
|
pipeInfo: {
|
||||||
|
isInPipe: boolean
|
||||||
|
previousResults: any[]
|
||||||
|
expressionIndex: number
|
||||||
|
body: PipeExpression['body']
|
||||||
|
} = {
|
||||||
|
isInPipe: false,
|
||||||
|
previousResults: [],
|
||||||
|
expressionIndex: 0,
|
||||||
|
body: [],
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const { isInPipe, previousResults, expressionIndex, body } = pipeInfo
|
||||||
|
const functionName = expression.callee.name
|
||||||
|
const fnArgs = expression.arguments.map((arg) => {
|
||||||
|
if (arg.type === 'Literal') {
|
||||||
|
return arg.value
|
||||||
|
} else if (arg.type === 'Identifier') {
|
||||||
|
const temp = programMemory.root[arg.name]
|
||||||
|
return temp?.type === 'userVal' ? temp.value : temp
|
||||||
|
} else if (arg.type === 'PipeSubstitution') {
|
||||||
|
return previousResults[expressionIndex - 1]
|
||||||
|
} else if (arg.type === 'ArrayExpression') {
|
||||||
|
return arg.elements.map((el) => {
|
||||||
|
if (el.type === 'Literal') {
|
||||||
|
return el.value
|
||||||
|
} else if (el.type === 'Identifier') {
|
||||||
|
return programMemory.root[el.name]
|
||||||
|
} else if (el.type === 'BinaryExpression') {
|
||||||
|
return getBinaryExpressionResult(el, programMemory)
|
||||||
|
}
|
||||||
|
throw new Error('Invalid argument type')
|
||||||
|
})
|
||||||
|
} else if (arg.type === 'CallExpression') {
|
||||||
|
const result: any = executeCallExpression(
|
||||||
|
programMemory,
|
||||||
|
arg,
|
||||||
|
previousPathToNode
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
throw new Error('Invalid argument type')
|
||||||
|
})
|
||||||
|
if ('rx' === functionName || 'ry' === functionName || 'rz' === functionName) {
|
||||||
|
const result = sketchFns[functionName](
|
||||||
|
programMemory,
|
||||||
|
[expression.start, expression.end],
|
||||||
|
fnArgs[0],
|
||||||
|
fnArgs[1]
|
||||||
|
)
|
||||||
|
return isInPipe
|
||||||
|
? executePipeBody(
|
||||||
|
body,
|
||||||
|
programMemory,
|
||||||
|
previousPathToNode,
|
||||||
|
expressionIndex + 1,
|
||||||
|
[...previousResults, result]
|
||||||
|
)
|
||||||
|
: result
|
||||||
|
}
|
||||||
|
if (functionName === 'extrude') {
|
||||||
|
const result = sketchFns[functionName](
|
||||||
|
programMemory,
|
||||||
|
'yo',
|
||||||
|
[expression.start, expression.end],
|
||||||
|
fnArgs[0],
|
||||||
|
fnArgs[1]
|
||||||
|
)
|
||||||
|
return isInPipe
|
||||||
|
? executePipeBody(
|
||||||
|
body,
|
||||||
|
programMemory,
|
||||||
|
previousPathToNode,
|
||||||
|
expressionIndex + 1,
|
||||||
|
[...previousResults, result]
|
||||||
|
)
|
||||||
|
: result
|
||||||
|
}
|
||||||
|
if (functionName === 'translate' || functionName === 'transform') {
|
||||||
|
const result = sketchFns[functionName](
|
||||||
|
programMemory,
|
||||||
|
[expression.start, expression.end],
|
||||||
|
fnArgs[0],
|
||||||
|
fnArgs[1]
|
||||||
|
)
|
||||||
|
return isInPipe
|
||||||
|
? executePipeBody(
|
||||||
|
body,
|
||||||
|
programMemory,
|
||||||
|
previousPathToNode,
|
||||||
|
expressionIndex + 1,
|
||||||
|
[...previousResults, result]
|
||||||
|
)
|
||||||
|
: result
|
||||||
|
}
|
||||||
|
if (functionName === 'getExtrudeWallTransform') {
|
||||||
|
const result = sketchFns[functionName](
|
||||||
|
programMemory,
|
||||||
|
[expression.start, expression.end],
|
||||||
|
fnArgs[0],
|
||||||
|
fnArgs[1]
|
||||||
|
)
|
||||||
|
return isInPipe
|
||||||
|
? executePipeBody(
|
||||||
|
body,
|
||||||
|
programMemory,
|
||||||
|
previousPathToNode,
|
||||||
|
expressionIndex + 1,
|
||||||
|
[...previousResults, result]
|
||||||
|
)
|
||||||
|
: result
|
||||||
|
}
|
||||||
|
const result = programMemory.root[functionName].value(...fnArgs)
|
||||||
|
return isInPipe
|
||||||
|
? executePipeBody(
|
||||||
|
body,
|
||||||
|
programMemory,
|
||||||
|
previousPathToNode,
|
||||||
|
expressionIndex + 1,
|
||||||
|
[...previousResults, result]
|
||||||
|
)
|
||||||
|
: result
|
||||||
|
}
|
||||||
|
@ -5,6 +5,8 @@ import {
|
|||||||
ExtrudeGroup,
|
ExtrudeGroup,
|
||||||
SourceRange,
|
SourceRange,
|
||||||
ExtrudeSurface,
|
ExtrudeSurface,
|
||||||
|
Position,
|
||||||
|
Rotation,
|
||||||
} from './executor'
|
} from './executor'
|
||||||
import { lineGeo, extrudeGeo } from './engine'
|
import { lineGeo, extrudeGeo } from './engine'
|
||||||
import { Quaternion, Vector3 } from 'three'
|
import { Quaternion, Vector3 } from 'three'
|
||||||
@ -179,21 +181,40 @@ export const sketchFns = {
|
|||||||
from = lastPoint.to
|
from = lastPoint.to
|
||||||
}
|
}
|
||||||
const to = line.to
|
const to = line.to
|
||||||
const geo = extrudeGeo({
|
const {
|
||||||
|
geo,
|
||||||
|
position: facePosition,
|
||||||
|
rotation: faceRotation,
|
||||||
|
} = extrudeGeo({
|
||||||
from: [from[0], from[1], 0],
|
from: [from[0], from[1], 0],
|
||||||
to: [to[0], to[1], 0],
|
to: [to[0], to[1], 0],
|
||||||
length,
|
length,
|
||||||
})
|
})
|
||||||
extrudeSurfaces.push({
|
const groupQuaternion = new Quaternion(...rotation)
|
||||||
|
const currentWallQuat = new Quaternion(...faceRotation)
|
||||||
|
const unifiedQuit = new Quaternion().multiplyQuaternions(
|
||||||
|
currentWallQuat,
|
||||||
|
groupQuaternion.clone().invert()
|
||||||
|
)
|
||||||
|
|
||||||
|
const facePositionVector = new Vector3(...facePosition)
|
||||||
|
facePositionVector.applyQuaternion(groupQuaternion.clone())
|
||||||
|
const unifiedPosition = new Vector3().addVectors(
|
||||||
|
facePositionVector,
|
||||||
|
new Vector3(...position)
|
||||||
|
)
|
||||||
|
const surface: ExtrudeSurface = {
|
||||||
type: 'extrudePlane',
|
type: 'extrudePlane',
|
||||||
position, // todo should come from extrudeGeo
|
position: unifiedPosition.toArray() as Position,
|
||||||
rotation, // todo should come from extrudeGeo
|
rotation: unifiedQuit.toArray() as Rotation,
|
||||||
__geoMeta: {
|
__geoMeta: {
|
||||||
geo,
|
geo,
|
||||||
sourceRange: line.__geoMeta.sourceRange,
|
sourceRange: line.__geoMeta.sourceRange,
|
||||||
pathToNode: line.__geoMeta.pathToNode,
|
pathToNode: line.__geoMeta.pathToNode,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
line.name && (surface.name = line.name)
|
||||||
|
extrudeSurfaces.push(surface)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
@ -211,6 +232,8 @@ export const sketchFns = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
translate,
|
translate,
|
||||||
|
transform,
|
||||||
|
getExtrudeWallTransform,
|
||||||
}
|
}
|
||||||
|
|
||||||
function rotateOnAxis<T extends SketchGroup | ExtrudeGroup>(
|
function rotateOnAxis<T extends SketchGroup | ExtrudeGroup>(
|
||||||
@ -258,7 +281,7 @@ function translate<T extends SketchGroup | ExtrudeGroup>(
|
|||||||
const newPosition = oldPosition.add(new Vector3(...vec3))
|
const newPosition = oldPosition.add(new Vector3(...vec3))
|
||||||
return {
|
return {
|
||||||
...sketch,
|
...sketch,
|
||||||
position: [newPosition.x, newPosition.y, newPosition.z],
|
position: newPosition.toArray(),
|
||||||
__meta: [
|
__meta: [
|
||||||
...sketch.__meta,
|
...sketch.__meta,
|
||||||
{
|
{
|
||||||
@ -268,3 +291,52 @@ function translate<T extends SketchGroup | ExtrudeGroup>(
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function transform<T extends SketchGroup | ExtrudeGroup>(
|
||||||
|
programMemory: ProgramMemory,
|
||||||
|
sourceRange: SourceRange,
|
||||||
|
transformInfo: {
|
||||||
|
position: Position
|
||||||
|
quaternion: Rotation
|
||||||
|
},
|
||||||
|
sketch: T
|
||||||
|
): T {
|
||||||
|
const quaternionToApply = new Quaternion(...transformInfo.quaternion)
|
||||||
|
const newQuaternion = new Quaternion(...sketch.rotation).multiply(
|
||||||
|
quaternionToApply.invert()
|
||||||
|
)
|
||||||
|
|
||||||
|
const oldPosition = new Vector3(...sketch.position)
|
||||||
|
const newPosition = oldPosition
|
||||||
|
.applyQuaternion(quaternionToApply)
|
||||||
|
.add(new Vector3(...transformInfo.position))
|
||||||
|
return {
|
||||||
|
...sketch,
|
||||||
|
position: newPosition.toArray(),
|
||||||
|
rotation: newQuaternion.toArray(),
|
||||||
|
__meta: [
|
||||||
|
...sketch.__meta,
|
||||||
|
{
|
||||||
|
sourceRange,
|
||||||
|
pathToNode: [], // TODO
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExtrudeWallTransform(
|
||||||
|
programMemory: ProgramMemory,
|
||||||
|
sourceRange: SourceRange,
|
||||||
|
pathName: string,
|
||||||
|
extrudeGroup: ExtrudeGroup
|
||||||
|
): {
|
||||||
|
position: Position
|
||||||
|
quaternion: Rotation
|
||||||
|
} {
|
||||||
|
const path = extrudeGroup.value.find((path) => path.name === pathName)
|
||||||
|
if (!path) throw new Error(`Could not find path with name ${pathName}`)
|
||||||
|
return {
|
||||||
|
position: path.position,
|
||||||
|
quaternion: path.rotation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user