feat: advance FreeCAD parity and native OCCT history
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { BitByBitOCCT, OccStateEnum } from '@bitbybit-dev/occt-worker'
|
||||
import type { Inputs } from '@bitbybit-dev/occt'
|
||||
import type { ApplyPlacementInput, BooleanCutInput, BooleanIntersectionInput, BooleanUnionInput, ChamferInput, CreateBoxInput, CreateConeInput, CreateCylinderInput, CreateSphereInput, FilletInput, GeometryCapabilities, GeometryDocumentContext, GeometryFileExport, LinearFeatureParameters, MeshAsset, MirrorInput, PadInput, PlanarProfile, PocketInput, Point3, RevolutionInput, ShapeHandle, SubshapeRef, SubshapeTopology } from './types'
|
||||
import type { ApplyPlacementInput, BooleanCutInput, BooleanIntersectionInput, BooleanUnionInput, ChamferInput, CreateBoxInput, CreateConeInput, CreateCylinderInput, CreateSphereInput, FilletInput, GeometryCapabilities, GeometryDocumentContext, GeometryFileExport, LinearFeatureParameters, MeshAsset, MirrorInput, NativeTopologyHistoryInput, NativeTopologyHistoryRecord, PadInput, PlanarProfile, PocketInput, Point3, RevolutionInput, ShapeHandle, SubshapeRef, SubshapeTopology } from './types'
|
||||
import { mapNativeOcctHistoryRecords } from './nativeHistoryProvider'
|
||||
import { NativeOcctHistoryCoordinator, type NativeOcctHistoryProvider } from './nativeHistoryProtocol'
|
||||
import { createEdgeSubshapeRefs, createSubshapeRefs, createVertexSubshapeRefs } from './topologyNaming'
|
||||
|
||||
type KernelShapeReference = Inputs.OCCT.TopoDSShapePointer
|
||||
@@ -230,6 +232,34 @@ export class BitbybitGeometryRuntime {
|
||||
private sequence = 0
|
||||
private readonly shapes = new Map<string, ShapeEntry>()
|
||||
private readonly kernelReferences = new Map<number, KernelReferenceEntry>()
|
||||
private nativeHistory: { provider: NativeOcctHistoryProvider; coordinator: NativeOcctHistoryCoordinator } | null = null
|
||||
private readonly nativeHistoryDocumentVersions = new Map<string, number>()
|
||||
|
||||
configureNativeHistory(provider: NativeOcctHistoryProvider | null, timeoutMs = 120_000) {
|
||||
this.nativeHistory?.coordinator.cancel()
|
||||
if (provider === null) {
|
||||
this.nativeHistory = null
|
||||
this.nativeHistoryDocumentVersions.clear()
|
||||
return
|
||||
}
|
||||
if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) throw new RangeError('Native history timeoutMs must be a positive safe integer.')
|
||||
this.nativeHistory = {
|
||||
provider,
|
||||
coordinator: new NativeOcctHistoryCoordinator((documentId) => this.nativeHistoryDocumentVersions.get(documentId) ?? null, timeoutMs),
|
||||
}
|
||||
}
|
||||
|
||||
nativeHistoryCapabilities() {
|
||||
return this.nativeHistory?.provider.capabilities() ?? {
|
||||
providerId: 'occt-native.history-step',
|
||||
providerVersion: 'unconfigured',
|
||||
occtVersion: 'unknown',
|
||||
availability: 'unavailable' as const,
|
||||
operations: [],
|
||||
transport: 'step-text' as const,
|
||||
reason: 'Native OCCT history provider is not configured.',
|
||||
}
|
||||
}
|
||||
|
||||
capabilities(): GeometryCapabilities { return { ...this.capabilitiesState } }
|
||||
|
||||
@@ -471,6 +501,30 @@ export class BitbybitGeometryRuntime {
|
||||
return { faces: faceTopology.refs, edges: edgeTopology.refs, vertices: vertexTopology.refs, entries }
|
||||
}
|
||||
|
||||
async topologyHistory(input: NativeTopologyHistoryInput): Promise<NativeTopologyHistoryRecord[]> {
|
||||
const nativeHistory = this.nativeHistory
|
||||
if (!nativeHistory) throw new Error('Native OCCT history provider is not configured.')
|
||||
if (!input.operation) throw new Error('Native OCCT history requires a supported Boolean operation.')
|
||||
if (input.inputs.length !== 2) throw new Error('Native OCCT history requires exactly an object and a tool input.')
|
||||
validateDocumentContext(input)
|
||||
this.nativeHistoryDocumentVersions.set(input.documentId, input.documentVersion)
|
||||
const [objectInput, toolInput] = input.inputs
|
||||
const [objectStep, toolStep] = await Promise.all([
|
||||
this.exportStep(objectInput.shape, `${objectInput.objectId}.step`),
|
||||
this.exportStep(toolInput.shape, `${toolInput.objectId}.step`),
|
||||
])
|
||||
const execution = await nativeHistory.coordinator.capture(nativeHistory.provider, {
|
||||
documentId: input.documentId,
|
||||
documentVersion: input.documentVersion,
|
||||
operationId: input.operationId,
|
||||
operation: input.operation,
|
||||
objectStep: objectStep.text,
|
||||
toolStep: toolStep.text,
|
||||
})
|
||||
if (execution.status !== 'completed' || !execution.response) throw new Error(`Native OCCT history ${execution.status}.`)
|
||||
return mapNativeOcctHistoryRecords(execution.response.history, { object: objectInput.objectId, tool: toolInput.objectId })
|
||||
}
|
||||
|
||||
async release(shape: ShapeHandle): Promise<void> {
|
||||
const entry = this.shapes.get(shape.id)
|
||||
if (!entry) return
|
||||
@@ -487,6 +541,7 @@ export class BitbybitGeometryRuntime {
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.nativeHistory?.coordinator.cancel()
|
||||
this.cancelInitialization?.()
|
||||
this.shapes.clear()
|
||||
this.kernelReferences.clear()
|
||||
@@ -496,6 +551,8 @@ export class BitbybitGeometryRuntime {
|
||||
this.worker = null
|
||||
this.initialization = null
|
||||
this.cancelInitialization = null
|
||||
this.nativeHistoryDocumentVersions.clear()
|
||||
this.nativeHistory = null
|
||||
this.capabilitiesState = unavailableCapabilities()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user