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') {
return (
<>
{artifact.start && (
<PathRender
geoInfo={artifact.start}
forceHighlight={false}
rotation={artifact.rotation}
position={artifact.position}
/>
)}
{artifact.value.map((geoInfo, key) => (
<PathRender
geoInfo={geoInfo}
@ -356,7 +364,7 @@ function PathRender({
return (
<>
{geoInfo.__geoMeta.geos.map((meta, i) => {
if (meta.type === 'line') {
if (meta.type === 'line')
return (
<LineRender
key={i}
@ -367,8 +375,7 @@ function PathRender({
position={position}
/>
)
}
if (meta.type === 'lineEnd') {
if (meta.type === 'lineEnd')
return (
<MovingSphere
key={i}
@ -380,7 +387,17 @@ function PathRender({
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(
(node) =>
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(

View File

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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,10 @@ export const segLen: InternalFn = (
function segEndFactory(which: 'x' | 'y'): InternalFn {
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
if (!line) return 0
return which === 'x' ? line.to[0] : line.to[1]