Give startSketchAt a 3D artifact (#65)

* Give startSketchAt a 3D artifact

* fix tests

* refactor start geo to be in the start property

* small tweak
This commit is contained in:
Kurt Hutten
2023-03-17 08:27:40 +11:00
committed by GitHub
parent d73003e3fd
commit c11e7e7fd3
9 changed files with 113 additions and 29 deletions

View File

@ -240,6 +240,14 @@ function RenderViewerArtifact({
if (artifact.type === 'sketchGroup') { if (artifact.type === 'sketchGroup') {
return ( return (
<> <>
{artifact.start && (
<PathRender
geoInfo={artifact.start}
forceHighlight={false}
rotation={artifact.rotation}
position={artifact.position}
/>
)}
{artifact.value.map((geoInfo, key) => ( {artifact.value.map((geoInfo, key) => (
<PathRender <PathRender
geoInfo={geoInfo} geoInfo={geoInfo}
@ -356,7 +364,7 @@ function PathRender({
return ( return (
<> <>
{geoInfo.__geoMeta.geos.map((meta, i) => { {geoInfo.__geoMeta.geos.map((meta, i) => {
if (meta.type === 'line') { if (meta.type === 'line')
return ( return (
<LineRender <LineRender
key={i} key={i}
@ -367,8 +375,7 @@ function PathRender({
position={position} position={position}
/> />
) )
} if (meta.type === 'lineEnd')
if (meta.type === 'lineEnd') {
return ( return (
<MovingSphere <MovingSphere
key={i} key={i}
@ -380,7 +387,17 @@ function PathRender({
position={position} position={position}
/> />
) )
} if (meta.type === 'sketchBase')
return (
<LineRender
key={i}
geo={meta.geo}
sourceRange={geoInfo.__geoMeta.sourceRange}
forceHighlight={forceHighlight || editorCursor}
rotation={rotation}
position={position}
/>
)
})} })}
</> </>
) )

View File

@ -60,7 +60,10 @@ export const SetHorzDistance = ({
const isAllTooltips = nodes.every( const isAllTooltips = nodes.every(
(node) => (node) =>
node?.type === 'CallExpression' && node?.type === 'CallExpression' &&
toolTips.includes(node.callee.name as any) [
...toolTips,
'startSketchAt', // TODO probably a better place for this to live
].includes(node.callee.name as any)
) )
const theTransforms = getTransformInfos( const theTransforms = getTransformInfos(

View File

@ -25,5 +25,5 @@ code {
#code-mirror-override .cm-cursor { #code-mirror-override .cm-cursor {
display: block; display: block;
width: 200px; width: 200px;
background: linear-gradient(to right, rgb(0, 55, 94) 0%, #0084e2ff 2%, #0084e255 5%, transparent 100%); background: linear-gradient(to right, rgb(0, 55, 94) 0%, #0084e2ff 2%, #0084e255 5%, transparent 100%);
} }

View File

@ -21,7 +21,16 @@ show(mySketch001)`
expect(artifactsWithoutGeos).toEqual([ expect(artifactsWithoutGeos).toEqual([
{ {
type: 'sketchGroup', type: 'sketchGroup',
start: [0, 0], start: {
type: 'base',
to: [0, 0],
from: [0, 0],
__geoMeta: {
sourceRange: [21, 42],
pathToNode: [],
geos: ['sketchBase'],
},
},
value: [ value: [
{ {
type: 'toPoint', type: 'toPoint',
@ -275,6 +284,15 @@ function removeGeo(arts: (SketchGroup | ExtrudeGroup)[]): any {
} }
return { return {
...art, ...art,
start: art.start
? {
...art.start,
__geoMeta: {
...art.start.__geoMeta,
geos: art.start.__geoMeta.geos.map((g) => g.type),
},
}
: {},
value: art.value.map((v) => ({ value: art.value.map((v) => ({
...v, ...v,
__geoMeta: { __geoMeta: {

View File

@ -88,6 +88,12 @@ export function lineGeo({
} }
} }
export function sketchBaseGeo({ to }: { to: [number, number, number] }): {
base: BufferGeometry
} {
return { base: new SphereGeometry(0.25).translate(to[0], to[1], to[2]) }
}
export interface extrudeWallGeo { export interface extrudeWallGeo {
line: BufferGeometry line: BufferGeometry
tip: BufferGeometry tip: BufferGeometry

View File

@ -166,7 +166,16 @@ show(mySketch)
const striptVersion = removeGeoFromSketch(root.mySk1 as SketchGroup) const striptVersion = removeGeoFromSketch(root.mySk1 as SketchGroup)
expect(striptVersion).toEqual({ expect(striptVersion).toEqual({
type: 'sketchGroup', type: 'sketchGroup',
start: [0, 0], start: {
type: 'base',
to: [0, 0],
from: [0, 0],
__geoMeta: {
sourceRange: [14, 34],
pathToNode: [],
geos: ['sketchBase'],
},
},
value: [ value: [
{ {
type: 'toPoint', type: 'toPoint',
@ -420,6 +429,15 @@ function exe(
function removeGeoFromSketch(sketch: SketchGroup): SketchGroup { function removeGeoFromSketch(sketch: SketchGroup): SketchGroup {
return { return {
...sketch, ...sketch,
start: !sketch.start
? undefined
: {
...sketch.start,
__geoMeta: {
...sketch.start.__geoMeta,
geos: sketch.start.__geoMeta.geos.map((geo) => geo.type as any),
},
},
value: removeGeoFromPaths(sketch.value), value: removeGeoFromPaths(sketch.value),
} }
} }

View File

@ -30,7 +30,7 @@ interface BasePath {
__geoMeta: { __geoMeta: {
geos: { geos: {
geo: BufferGeometry geo: BufferGeometry
type: 'line' | 'lineEnd' type: 'line' | 'lineEnd' | 'sketchBase'
}[] }[]
sourceRange: SourceRange sourceRange: SourceRange
pathToNode: PathToNode pathToNode: PathToNode
@ -41,6 +41,10 @@ export interface ToPoint extends BasePath {
type: 'toPoint' type: 'toPoint'
} }
export interface Base extends BasePath {
type: 'base'
}
export interface HorizontalLineTo extends BasePath { export interface HorizontalLineTo extends BasePath {
type: 'horizontalLineTo' type: 'horizontalLineTo'
x: number x: number
@ -61,12 +65,12 @@ interface GeoMeta {
} }
} }
export type Path = ToPoint | HorizontalLineTo | AngledLineTo export type Path = ToPoint | HorizontalLineTo | AngledLineTo | Base
export interface SketchGroup { export interface SketchGroup {
type: 'sketchGroup' type: 'sketchGroup'
value: Path[] value: Path[]
start?: Path['from'] start?: Base
position: Position position: Position
rotation: Rotation rotation: Rotation
__meta: Metadata[] __meta: Metadata[]

View File

@ -18,7 +18,7 @@ import {
getNodeFromPathCurry, getNodeFromPathCurry,
getNodePathFromSourceRange, getNodePathFromSourceRange,
} from '../queryAst' } from '../queryAst'
import { lineGeo } from '../engine' import { lineGeo, sketchBaseGeo } from '../engine'
import { GuiModes, toolTips, TooTip } from '../../useStore' import { GuiModes, toolTips, TooTip } from '../../useStore'
import { getLastIndex } from '../modifyAst' import { getLastIndex } from '../modifyAst'
@ -46,7 +46,7 @@ export type Coords2d = [number, number]
export function getCoordsFromPaths(skGroup: SketchGroup, index = 0): Coords2d { export function getCoordsFromPaths(skGroup: SketchGroup, index = 0): Coords2d {
const currentPath = skGroup?.value?.[index] const currentPath = skGroup?.value?.[index]
if (!currentPath && skGroup?.start) { if (!currentPath && skGroup?.start) {
return skGroup.start return skGroup.start.to
} else if (!currentPath) { } else if (!currentPath) {
return [0, 0] return [0, 0]
} }
@ -83,6 +83,8 @@ export function createFirstArg(
return createObjectExpression({ length: val, tag }) return createObjectExpression({ length: val, tag })
if (['xLineTo', 'yLineTo'].includes(sketchFn)) if (['xLineTo', 'yLineTo'].includes(sketchFn))
return createObjectExpression({ to: val, tag }) return createObjectExpression({ to: val, tag })
if (['startSketchAt'].includes(sketchFn))
return createObjectExpression({ to: val, tag })
} }
throw new Error('all sketch line types should have been covered') throw new Error('all sketch line types should have been covered')
} }
@ -895,18 +897,22 @@ export const angledLineToX: SketchLineHelper = {
) )
const angle = createLiteral(roundOff(getAngle(from, to), 0)) const angle = createLiteral(roundOff(getAngle(from, to), 0))
const xArg = createLiteral(roundOff(to[0], 2)) const xArg = createLiteral(roundOff(to[0], 2))
const newLine = createCallback if (replaceExisting && createCallback) {
? createCallback([angle, xArg]).callExp const { callExp, valueUsedInTransform } = createCallback([angle, xArg])
: createCallExpression('angledLineToX', [ const callIndex = getLastIndex(pathToNode)
createArrayExpression([angle, xArg]), pipe.body[callIndex] = callExp
createPipeSubstitution(), return {
]) modifiedAst: _node,
const callIndex = getLastIndex(pathToNode) pathToNode,
if (replaceExisting) { valueUsedInTransform,
pipe.body[callIndex] = newLine }
} else {
pipe.body = [...pipe.body, newLine]
} }
const callExp = createCallExpression('angledLineToX', [
createArrayExpression([angle, xArg]),
createPipeSubstitution(),
])
pipe.body = [...pipe.body, callExp]
return { return {
modifiedAst: _node, modifiedAst: _node,
pathToNode, pathToNode,
@ -1288,14 +1294,20 @@ export const startSketchAt: InternalFn = (
} }
): SketchGroup => { ): SketchGroup => {
const to = 'to' in data ? data.to : data const to = 'to' in data ? data.to : data
const geo = sketchBaseGeo({ to: [...to, 0] })
const currentPath: Path = { const currentPath: Path = {
type: 'toPoint', type: 'base',
to, to,
from: to, from: to,
__geoMeta: { __geoMeta: {
sourceRange, sourceRange,
pathToNode: [], // TODO pathToNode: [], // TODO
geos: [], geos: [
{
type: 'sketchBase',
geo: geo.base,
},
],
}, },
} }
if ('tag' in data) { if ('tag' in data) {
@ -1303,7 +1315,7 @@ export const startSketchAt: InternalFn = (
} }
return { return {
type: 'sketchGroup', type: 'sketchGroup',
start: to, start: currentPath,
value: [], value: [],
position: [0, 0, 0], position: [0, 0, 0],
rotation: [0, 0, 0, 1], rotation: [0, 0, 0, 1],
@ -1393,7 +1405,7 @@ function getFirstArgValuesForXYLineFns(callExpression: CallExpression): {
return { val: firstArg } return { val: firstArg }
} }
const tag = firstArg.properties.find((p) => p.key.name === 'tag')?.value const tag = firstArg.properties.find((p) => p.key.name === 'tag')?.value
const secondArgName = ['xLineTo', 'yLineTo'].includes( const secondArgName = ['xLineTo', 'yLineTo', 'startSketchAt'].includes(
// const secondArgName = ['xLineTo', 'yLineTo', 'angledLineToX', 'angledLineToY'].includes( // const secondArgName = ['xLineTo', 'yLineTo', 'angledLineToX', 'angledLineToY'].includes(
callExpression?.callee?.name callExpression?.callee?.name
) )
@ -1430,5 +1442,8 @@ export function getFirstArg(callExp: CallExpression): {
if (['xLine', 'yLine', 'xLineTo', 'yLineTo'].includes(name)) { if (['xLine', 'yLine', 'xLineTo', 'yLineTo'].includes(name)) {
return getFirstArgValuesForXYLineFns(callExp) return getFirstArgValuesForXYLineFns(callExp)
} }
if (['startSketchAt'].includes(name)) {
return getFirstArgValuesForXYLineFns(callExp)
}
throw new Error('unexpected call expression') throw new Error('unexpected call expression')
} }

View File

@ -35,7 +35,10 @@ export const segLen: InternalFn = (
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 = sketchGroup?.value.find((seg) => seg.name === segName) const line =
sketchGroup.start?.name === segName
? sketchGroup.start
: sketchGroup?.value.find((seg) => seg.name === segName)
// maybe this should throw, but the language doesn't have a way to handle errors yet // maybe this should throw, but the language doesn't have a way to handle errors yet
if (!line) return 0 if (!line) return 0
return which === 'x' ? line.to[0] : line.to[1] return which === 'x' ? line.to[0] : line.to[1]