Rust artifact graph (#5068)
* Start porting artifact graph creation to Rust * Add most of artifact graph creation * Add handling loft command from recent PR * Refactor artifact merge code so that it errors when a new artifact type is added * Add sweep subtype * Finish implementation of build artifact graph * Fix wasm.ts to use new combined generated ts-rs file * Fix Rust lints * Fix lints * Fix up replacement code * Add artifact graph to WASM outcome * Add artifact graph to simulation test output * Add new artifact graph output snapshots * Fix wall field and reduce unreachable code * Change field order for subtype * Change subtype to be determined from the request, like the TS * Fix plane sweep_id * Condense code * Change ID types to be properly optional * Change to favor the new ID, the same as TS * Fix to make error impossible * Rename artifact type tag values to match TS * Fix name of field on Cap * Update outputs * Change to use Rust source range * Update output snapshots * Add conversion to mermaid mind map and add to snapshot tests * Add new mermaid mind map output * Add flowchart * Remove raw artifact graph from tests * Remove JSON artifact graph output * Update output file with header * Update output after adding flowchart * Fix flowchart to not have duplicate edges, one in each direction * Fix not not output duplicate edges in flowcharts * Change flowchart edge style to be more obvious when a direction is missing * Update output after deduplication of edges * Fix not not skip sketch-on-face artifacts * Add docs * Fix edge iteration order to be stable * Update output after fixing order * Port TS artifactGraph.test.ts tests to simulation tests * Add grouping segments and solid2ds with their path * Update output flowcharts since grouping paths * Remove TS artifactGraph tests * Remove unused d3 dependencies * Fix to track loft ID on paths * Add command ID to error messages * Move artifact graph test code to a separate file since it's a large file * Reduce function visibility * Remove TS artifact graph code * Fix spelling error with serde * Add TODO for edge cut consumed ID * Add comment about mermaid edge rank * Fix mermaid flowchart edge cuts to appear as children of their edges * Update output since fixing flowchart order * Fix to always build the artifact graph even when there's a KCL error * Add artifact graph to error output * Change optional ID merge to match TS * Remove redundant SourceRange definition * Remove Rust-flavored default source range function * Add helper for source range creation * Update doc comment for the website * Update docs after doc comment change * Fix to save engine responses in execution cache * Remove unused import * Fix to not call WASM function before beforeAll callback is run * Remove more unused imports
This commit is contained in:
@ -1,17 +1,25 @@
|
||||
import {
|
||||
ArtifactCommand,
|
||||
ExecState,
|
||||
Artifact,
|
||||
ArtifactGraph,
|
||||
ArtifactId,
|
||||
PathToNode,
|
||||
Program,
|
||||
SourceRange,
|
||||
sourceRangeFromRust,
|
||||
PathArtifact,
|
||||
PlaneArtifact,
|
||||
WallArtifact,
|
||||
SegmentArtifact,
|
||||
Solid2dArtifact as Solid2D,
|
||||
SweepArtifact,
|
||||
SweepEdge,
|
||||
CapArtifact,
|
||||
EdgeCut,
|
||||
} from 'lang/wasm'
|
||||
import { Models } from '@kittycad/lib'
|
||||
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
||||
import { err } from 'lib/trap'
|
||||
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
||||
|
||||
export type ArtifactId = string
|
||||
export type { Artifact, ArtifactId, SegmentArtifact } from 'lang/wasm'
|
||||
|
||||
interface BaseArtifact {
|
||||
id: ArtifactId
|
||||
@ -22,30 +30,12 @@ export interface CodeRef {
|
||||
pathToNode: PathToNode
|
||||
}
|
||||
|
||||
export interface PlaneArtifact extends BaseArtifact {
|
||||
type: 'plane'
|
||||
pathIds: Array<ArtifactId>
|
||||
codeRef: CodeRef
|
||||
}
|
||||
export interface PlaneArtifactRich extends BaseArtifact {
|
||||
type: 'plane'
|
||||
paths: Array<PathArtifact>
|
||||
codeRef: CodeRef
|
||||
}
|
||||
|
||||
export interface PathArtifact extends BaseArtifact {
|
||||
type: 'path'
|
||||
planeId: ArtifactId
|
||||
segIds: Array<ArtifactId>
|
||||
sweepId?: ArtifactId
|
||||
solid2dId?: ArtifactId
|
||||
codeRef: CodeRef
|
||||
}
|
||||
|
||||
interface solid2D extends BaseArtifact {
|
||||
type: 'solid2D'
|
||||
pathId: ArtifactId
|
||||
}
|
||||
export interface PathArtifactRich extends BaseArtifact {
|
||||
type: 'path'
|
||||
/** A path must always lie on a plane */
|
||||
@ -53,18 +43,10 @@ export interface PathArtifactRich extends BaseArtifact {
|
||||
/** A path must always contain 0 or more segments */
|
||||
segments: Array<SegmentArtifact>
|
||||
/** A path may not result in a sweep artifact */
|
||||
sweep?: SweepArtifact
|
||||
sweep: SweepArtifact | null
|
||||
codeRef: CodeRef
|
||||
}
|
||||
|
||||
export interface SegmentArtifact extends BaseArtifact {
|
||||
type: 'segment'
|
||||
pathId: ArtifactId
|
||||
surfaceId?: ArtifactId
|
||||
edgeIds: Array<ArtifactId>
|
||||
edgeCutId?: ArtifactId
|
||||
codeRef: CodeRef
|
||||
}
|
||||
interface SegmentArtifactRich extends BaseArtifact {
|
||||
type: 'segment'
|
||||
path: PathArtifact
|
||||
@ -74,15 +56,6 @@ interface SegmentArtifactRich extends BaseArtifact {
|
||||
codeRef: CodeRef
|
||||
}
|
||||
|
||||
/** A Sweep is a more generic term for extrude, revolve, loft and sweep*/
|
||||
interface SweepArtifact extends BaseArtifact {
|
||||
type: 'sweep'
|
||||
subType: 'extrusion' | 'revolve' | 'loft' | 'sweep'
|
||||
pathId: string
|
||||
surfaceIds: Array<string>
|
||||
edgeIds: Array<string>
|
||||
codeRef: CodeRef
|
||||
}
|
||||
interface SweepArtifactRich extends BaseArtifact {
|
||||
type: 'sweep'
|
||||
subType: 'extrusion' | 'revolve' | 'loft' | 'sweep'
|
||||
@ -92,58 +65,6 @@ interface SweepArtifactRich extends BaseArtifact {
|
||||
codeRef: CodeRef
|
||||
}
|
||||
|
||||
interface WallArtifact extends BaseArtifact {
|
||||
type: 'wall'
|
||||
segId: ArtifactId
|
||||
edgeCutEdgeIds: Array<ArtifactId>
|
||||
sweepId: ArtifactId
|
||||
pathIds: Array<ArtifactId>
|
||||
}
|
||||
interface CapArtifact extends BaseArtifact {
|
||||
type: 'cap'
|
||||
subType: 'start' | 'end'
|
||||
edgeCutEdgeIds: Array<ArtifactId>
|
||||
sweepId: ArtifactId
|
||||
pathIds: Array<ArtifactId>
|
||||
}
|
||||
|
||||
interface SweepEdge extends BaseArtifact {
|
||||
type: 'sweepEdge'
|
||||
segId: ArtifactId
|
||||
sweepId: ArtifactId
|
||||
subType: 'opposite' | 'adjacent'
|
||||
}
|
||||
|
||||
/** A edgeCut is a more generic term for both fillet or chamfer */
|
||||
interface EdgeCut extends BaseArtifact {
|
||||
type: 'edgeCut'
|
||||
subType: 'fillet' | 'chamfer'
|
||||
consumedEdgeId: ArtifactId
|
||||
edgeIds: Array<ArtifactId>
|
||||
surfaceId?: ArtifactId
|
||||
codeRef: CodeRef
|
||||
}
|
||||
|
||||
interface EdgeCutEdge extends BaseArtifact {
|
||||
type: 'edgeCutEdge'
|
||||
edgeCutId: ArtifactId
|
||||
surfaceId: ArtifactId
|
||||
}
|
||||
|
||||
export type Artifact =
|
||||
| PlaneArtifact
|
||||
| PathArtifact
|
||||
| SegmentArtifact
|
||||
| SweepArtifact
|
||||
| WallArtifact
|
||||
| CapArtifact
|
||||
| SweepEdge
|
||||
| EdgeCut
|
||||
| EdgeCutEdge
|
||||
| solid2D
|
||||
|
||||
export type ArtifactGraph = Map<ArtifactId, Artifact>
|
||||
|
||||
export type EngineCommand = Models['WebSocketRequest_type']
|
||||
|
||||
type OkWebSocketResponseData = Models['OkWebSocketResponseData_type']
|
||||
@ -152,437 +73,6 @@ export interface ResponseMap {
|
||||
[commandId: string]: OkWebSocketResponseData
|
||||
}
|
||||
|
||||
/** Creates a graph of artifacts from a list of ordered commands and their responses
|
||||
* muting the Map should happen entirely this function, other functions called within
|
||||
* should return data on how to update the map, and not do so directly.
|
||||
*/
|
||||
export function createArtifactGraph({
|
||||
artifactCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
}: {
|
||||
artifactCommands: Array<ArtifactCommand>
|
||||
responseMap: ResponseMap
|
||||
ast: Node<Program>
|
||||
execStateArtifacts: ExecState['artifacts']
|
||||
}) {
|
||||
const myMap = new Map<ArtifactId, Artifact>()
|
||||
|
||||
/** see docstring for {@link getArtifactsToUpdate} as to why this is needed */
|
||||
let currentPlaneId = ''
|
||||
|
||||
for (const artifactCommand of artifactCommands) {
|
||||
if (artifactCommand.command.type === 'enable_sketch_mode') {
|
||||
currentPlaneId = artifactCommand.command.entity_id
|
||||
}
|
||||
if (artifactCommand.command.type === 'sketch_mode_disable') {
|
||||
currentPlaneId = ''
|
||||
}
|
||||
const artifactsToUpdate = getArtifactsToUpdate({
|
||||
artifactCommand,
|
||||
responseMap,
|
||||
getArtifact: (id: ArtifactId) => myMap.get(id),
|
||||
currentPlaneId,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
artifactsToUpdate.forEach(({ id, artifact }) => {
|
||||
const mergedArtifact = mergeArtifacts(myMap.get(id), artifact)
|
||||
myMap.set(id, mergedArtifact)
|
||||
})
|
||||
}
|
||||
return myMap
|
||||
}
|
||||
|
||||
/** Merges two artifacts, since our artifacts only contain strings and arrays of string for values we coerce that
|
||||
* but maybe types can be improved here.
|
||||
*/
|
||||
function mergeArtifacts(
|
||||
oldArtifact: Artifact | undefined,
|
||||
newArtifact: Artifact
|
||||
): Artifact {
|
||||
// only has string and array of strings
|
||||
interface GenericArtifact {
|
||||
[key: string]: string | Array<string>
|
||||
}
|
||||
if (!oldArtifact) return newArtifact
|
||||
// merging artifacts of different types should never happen, but if it does, just return the new artifact
|
||||
if (oldArtifact.type !== newArtifact.type) return newArtifact
|
||||
const _oldArtifact = oldArtifact as any as GenericArtifact
|
||||
const mergedArtifact = { ...oldArtifact, ...newArtifact } as GenericArtifact
|
||||
Object.entries(newArtifact as any as GenericArtifact).forEach(
|
||||
([propName, value]) => {
|
||||
const otherValue = _oldArtifact[propName]
|
||||
if (Array.isArray(value) && Array.isArray(otherValue)) {
|
||||
mergedArtifact[propName] = [...new Set([...otherValue, ...value])]
|
||||
}
|
||||
}
|
||||
)
|
||||
return mergedArtifact as any as Artifact
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a single command and it's response in order to populate the artifact map
|
||||
* It does not mutate the map directly, but returns an array of artifacts to update
|
||||
*
|
||||
* @param currentPlaneId is only needed for `start_path` commands because this command does not have a pathId
|
||||
* instead it relies on the id used with the `enable_sketch_mode` command, so this much be kept track of
|
||||
* outside of this function. It would be good to update the `start_path` command to include the planeId so we
|
||||
* can remove this.
|
||||
*/
|
||||
export function getArtifactsToUpdate({
|
||||
artifactCommand,
|
||||
getArtifact,
|
||||
responseMap,
|
||||
currentPlaneId,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
}: {
|
||||
artifactCommand: ArtifactCommand
|
||||
responseMap: ResponseMap
|
||||
/** Passing in a getter because we don't wan this function to update the map directly */
|
||||
getArtifact: (id: ArtifactId) => Artifact | undefined
|
||||
currentPlaneId: ArtifactId
|
||||
ast: Node<Program>
|
||||
execStateArtifacts: ExecState['artifacts']
|
||||
}): Array<{
|
||||
id: ArtifactId
|
||||
artifact: Artifact
|
||||
}> {
|
||||
const range = sourceRangeFromRust(artifactCommand.range)
|
||||
const pathToNode = getNodePathFromSourceRange(ast, range)
|
||||
|
||||
const id = artifactCommand.cmdId
|
||||
const response = responseMap[id]
|
||||
const cmd = artifactCommand.command
|
||||
const returnArr: ReturnType<typeof getArtifactsToUpdate> = []
|
||||
if (!response) return returnArr
|
||||
if (cmd.type === 'make_plane' && range[1] !== 0) {
|
||||
// If we're calling `make_plane` and the code range doesn't end at `0`
|
||||
// it's not a default plane, but a custom one from the offsetPlane standard library function
|
||||
return [
|
||||
{
|
||||
id,
|
||||
artifact: {
|
||||
type: 'plane',
|
||||
id,
|
||||
pathIds: [],
|
||||
codeRef: { range, pathToNode },
|
||||
},
|
||||
},
|
||||
]
|
||||
} else if (cmd.type === 'enable_sketch_mode') {
|
||||
const plane = getArtifact(currentPlaneId)
|
||||
const pathIds = plane?.type === 'plane' ? plane?.pathIds : []
|
||||
const codeRef =
|
||||
plane?.type === 'plane' ? plane?.codeRef : { range, pathToNode }
|
||||
const existingPlane = getArtifact(currentPlaneId)
|
||||
if (existingPlane?.type === 'wall') {
|
||||
return [
|
||||
{
|
||||
id: currentPlaneId,
|
||||
artifact: {
|
||||
type: 'wall',
|
||||
id: currentPlaneId,
|
||||
segId: existingPlane.segId,
|
||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||
sweepId: existingPlane.sweepId,
|
||||
pathIds: existingPlane.pathIds,
|
||||
},
|
||||
},
|
||||
]
|
||||
} else {
|
||||
return [
|
||||
{
|
||||
id: currentPlaneId,
|
||||
artifact: { type: 'plane', id: currentPlaneId, pathIds, codeRef },
|
||||
},
|
||||
]
|
||||
}
|
||||
} else if (cmd.type === 'start_path') {
|
||||
returnArr.push({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'path',
|
||||
id,
|
||||
segIds: [],
|
||||
planeId: currentPlaneId,
|
||||
sweepId: undefined,
|
||||
codeRef: { range, pathToNode },
|
||||
},
|
||||
})
|
||||
const plane = getArtifact(currentPlaneId)
|
||||
const codeRef =
|
||||
plane?.type === 'plane' ? plane?.codeRef : { range, pathToNode }
|
||||
if (plane?.type === 'plane') {
|
||||
returnArr.push({
|
||||
id: currentPlaneId,
|
||||
artifact: { type: 'plane', id: currentPlaneId, pathIds: [id], codeRef },
|
||||
})
|
||||
}
|
||||
if (plane?.type === 'wall') {
|
||||
returnArr.push({
|
||||
id: currentPlaneId,
|
||||
artifact: {
|
||||
type: 'wall',
|
||||
id: currentPlaneId,
|
||||
segId: plane.segId,
|
||||
edgeCutEdgeIds: plane.edgeCutEdgeIds,
|
||||
sweepId: plane.sweepId,
|
||||
pathIds: [id],
|
||||
},
|
||||
})
|
||||
}
|
||||
return returnArr
|
||||
} else if (cmd.type === 'extend_path' || cmd.type === 'close_path') {
|
||||
const pathId = cmd.type === 'extend_path' ? cmd.path : cmd.path_id
|
||||
returnArr.push({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'segment',
|
||||
id,
|
||||
pathId,
|
||||
surfaceId: undefined,
|
||||
edgeIds: [],
|
||||
codeRef: { range, pathToNode },
|
||||
},
|
||||
})
|
||||
const path = getArtifact(pathId)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: pathId,
|
||||
artifact: { ...path, segIds: [id] },
|
||||
})
|
||||
if (
|
||||
response?.type === 'modeling' &&
|
||||
response.data.modeling_response.type === 'close_path'
|
||||
) {
|
||||
returnArr.push({
|
||||
id: response.data.modeling_response.data.face_id,
|
||||
artifact: {
|
||||
type: 'solid2D',
|
||||
id: response.data.modeling_response.data.face_id,
|
||||
pathId,
|
||||
},
|
||||
})
|
||||
const path = getArtifact(pathId)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: pathId,
|
||||
artifact: {
|
||||
...path,
|
||||
solid2dId: response.data.modeling_response.data.face_id,
|
||||
},
|
||||
})
|
||||
}
|
||||
return returnArr
|
||||
} else if (
|
||||
cmd.type === 'extrude' ||
|
||||
cmd.type === 'revolve' ||
|
||||
cmd.type === 'sweep'
|
||||
) {
|
||||
const subType = cmd.type === 'extrude' ? 'extrusion' : cmd.type
|
||||
returnArr.push({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'sweep',
|
||||
subType: subType,
|
||||
id,
|
||||
pathId: cmd.target,
|
||||
surfaceIds: [],
|
||||
edgeIds: [],
|
||||
codeRef: { range, pathToNode },
|
||||
},
|
||||
})
|
||||
const path = getArtifact(cmd.target)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: cmd.target,
|
||||
artifact: { ...path, sweepId: id },
|
||||
})
|
||||
return returnArr
|
||||
} else if (
|
||||
cmd.type === 'loft' &&
|
||||
response.type === 'modeling' &&
|
||||
response.data.modeling_response.type === 'loft'
|
||||
) {
|
||||
returnArr.push({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'sweep',
|
||||
subType: 'loft',
|
||||
id,
|
||||
// TODO: make sure to revisit this choice, don't think it matters for now
|
||||
pathId: cmd.section_ids[0],
|
||||
surfaceIds: [],
|
||||
edgeIds: [],
|
||||
codeRef: { range, pathToNode },
|
||||
},
|
||||
})
|
||||
for (const sectionId of cmd.section_ids) {
|
||||
const path = getArtifact(sectionId)
|
||||
if (path?.type === 'path')
|
||||
returnArr.push({
|
||||
id: sectionId,
|
||||
artifact: { ...path, sweepId: id },
|
||||
})
|
||||
}
|
||||
return returnArr
|
||||
} else if (
|
||||
cmd.type === 'solid3d_get_extrusion_face_info' &&
|
||||
response?.type === 'modeling' &&
|
||||
response.data.modeling_response.type === 'solid3d_get_extrusion_face_info'
|
||||
) {
|
||||
let lastPath: PathArtifact
|
||||
response.data.modeling_response.data.faces.forEach(
|
||||
({ curve_id, cap, face_id }) => {
|
||||
if (cap === 'none' && curve_id && face_id) {
|
||||
const seg = getArtifact(curve_id)
|
||||
if (seg?.type !== 'segment') return
|
||||
const path = getArtifact(seg.pathId)
|
||||
if (path?.type === 'path' && seg?.type === 'segment') {
|
||||
lastPath = path
|
||||
returnArr.push({
|
||||
id: face_id,
|
||||
artifact: {
|
||||
type: 'wall',
|
||||
id: face_id,
|
||||
segId: curve_id,
|
||||
edgeCutEdgeIds: [],
|
||||
// TODO: Add explicit check for sweepId. Should never use ''
|
||||
sweepId: path.sweepId ?? '',
|
||||
pathIds: [],
|
||||
},
|
||||
})
|
||||
returnArr.push({
|
||||
id: curve_id,
|
||||
artifact: { ...seg, surfaceId: face_id },
|
||||
})
|
||||
if (path.sweepId) {
|
||||
const sweep = getArtifact(path.sweepId)
|
||||
if (sweep?.type === 'sweep') {
|
||||
returnArr.push({
|
||||
id: path.sweepId,
|
||||
artifact: {
|
||||
...sweep,
|
||||
surfaceIds: [face_id],
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
response.data.modeling_response.data.faces.forEach(({ cap, face_id }) => {
|
||||
if ((cap === 'top' || cap === 'bottom') && face_id) {
|
||||
const path = lastPath
|
||||
if (path?.type === 'path') {
|
||||
returnArr.push({
|
||||
id: face_id,
|
||||
artifact: {
|
||||
type: 'cap',
|
||||
id: face_id,
|
||||
subType: cap === 'bottom' ? 'start' : 'end',
|
||||
edgeCutEdgeIds: [],
|
||||
// TODO: Add explicit check for sweepId. Should never use ''
|
||||
sweepId: path.sweepId ?? '',
|
||||
pathIds: [],
|
||||
},
|
||||
})
|
||||
if (path.sweepId) {
|
||||
const sweep = getArtifact(path.sweepId)
|
||||
if (sweep?.type !== 'sweep') return
|
||||
returnArr.push({
|
||||
id: path.sweepId,
|
||||
artifact: {
|
||||
...sweep,
|
||||
surfaceIds: [face_id],
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return returnArr
|
||||
} else if (
|
||||
// is opposite edge
|
||||
(cmd.type === 'solid3d_get_opposite_edge' &&
|
||||
response.type === 'modeling' &&
|
||||
response.data.modeling_response.type === 'solid3d_get_opposite_edge' &&
|
||||
response.data.modeling_response.data.edge) ||
|
||||
// or is adjacent edge
|
||||
(cmd.type === 'solid3d_get_next_adjacent_edge' &&
|
||||
response.type === 'modeling' &&
|
||||
response.data.modeling_response.type ===
|
||||
'solid3d_get_next_adjacent_edge' &&
|
||||
response.data.modeling_response.data.edge)
|
||||
) {
|
||||
const wall = getArtifact(cmd.face_id)
|
||||
if (wall?.type !== 'wall') return returnArr
|
||||
const sweep = getArtifact(wall.sweepId)
|
||||
if (sweep?.type !== 'sweep') return returnArr
|
||||
const path = getArtifact(sweep.pathId)
|
||||
if (path?.type !== 'path') return returnArr
|
||||
const segment = getArtifact(cmd.edge_id)
|
||||
if (segment?.type !== 'segment') return returnArr
|
||||
|
||||
return [
|
||||
{
|
||||
id: response.data.modeling_response.data.edge,
|
||||
artifact: {
|
||||
type: 'sweepEdge',
|
||||
id: response.data.modeling_response.data.edge,
|
||||
subType:
|
||||
cmd.type === 'solid3d_get_next_adjacent_edge'
|
||||
? 'adjacent'
|
||||
: 'opposite',
|
||||
segId: cmd.edge_id,
|
||||
// TODO: Add explicit check for sweepId. Should never use ''
|
||||
sweepId: path.sweepId ?? '',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: cmd.edge_id,
|
||||
artifact: {
|
||||
...segment,
|
||||
edgeIds: [response.data.modeling_response.data.edge],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: sweep.id,
|
||||
artifact: {
|
||||
...sweep,
|
||||
edgeIds: [response.data.modeling_response.data.edge],
|
||||
},
|
||||
},
|
||||
]
|
||||
} else if (cmd.type === 'solid3d_fillet_edge') {
|
||||
returnArr.push({
|
||||
id,
|
||||
artifact: {
|
||||
type: 'edgeCut',
|
||||
id,
|
||||
subType: cmd.cut_type,
|
||||
consumedEdgeId: cmd.edge_id,
|
||||
edgeIds: [],
|
||||
surfaceId: undefined,
|
||||
codeRef: { range, pathToNode },
|
||||
},
|
||||
})
|
||||
const consumedEdge = getArtifact(cmd.edge_id)
|
||||
if (consumedEdge?.type === 'segment') {
|
||||
returnArr.push({
|
||||
id: cmd.edge_id,
|
||||
artifact: { ...consumedEdge, edgeCutId: id },
|
||||
})
|
||||
}
|
||||
return returnArr
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/** filter map items of a specific type */
|
||||
export function filterArtifacts<T extends Artifact['type'][]>(
|
||||
{
|
||||
@ -676,7 +166,7 @@ export function expandPath(
|
||||
},
|
||||
artifactGraph
|
||||
)
|
||||
: undefined
|
||||
: null
|
||||
const plane = getArtifactOfTypes(
|
||||
{ key: path.planeId, types: ['plane', 'wall'] },
|
||||
artifactGraph
|
||||
@ -778,11 +268,11 @@ export function getCapCodeRef(
|
||||
}
|
||||
|
||||
export function getSolid2dCodeRef(
|
||||
solid2D: solid2D,
|
||||
solid2d: Solid2D,
|
||||
artifactGraph: ArtifactGraph
|
||||
): CodeRef | Error {
|
||||
const path = getArtifactOfTypes(
|
||||
{ key: solid2D.pathId, types: ['path'] },
|
||||
{ key: solid2d.pathId, types: ['path'] },
|
||||
artifactGraph
|
||||
)
|
||||
if (err(path)) return path
|
||||
@ -881,7 +371,7 @@ export function getCodeRefsByArtifactId(
|
||||
artifactGraph: ArtifactGraph
|
||||
): Array<CodeRef> | null {
|
||||
const artifact = artifactGraph.get(id)
|
||||
if (artifact?.type === 'solid2D') {
|
||||
if (artifact?.type === 'solid2d') {
|
||||
const codeRef = getSolid2dCodeRef(artifact, artifactGraph)
|
||||
if (err(codeRef)) return null
|
||||
return [codeRef]
|
||||
|
Reference in New Issue
Block a user