feat: add experimental linear pattern feature
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { DependencyGraph, type RecomputeState } from './dependencyGraph'
|
||||
import { cloneSketch, solveSketch } from './sketcher'
|
||||
import type { BooleanCutInput, BooleanIntersectionInput, BooleanUnionInput, ChamferInput, CreateBoxInput, CreateConeInput, CreateCylinderInput, CreateSphereInput, DocumentObjectSnapshot, DocumentSnapshot, FilletInput, PadInput, PlanarProfile, PocketInput, RevolutionInput, ShapeHandle } from './types'
|
||||
import type { ApplyPlacementInput, BooleanCutInput, BooleanIntersectionInput, BooleanUnionInput, ChamferInput, CreateBoxInput, CreateConeInput, CreateCylinderInput, CreateSphereInput, DocumentObjectSnapshot, DocumentSnapshot, FilletInput, PadInput, PlanarProfile, PocketInput, RevolutionInput, ShapeHandle } from './types'
|
||||
|
||||
export type RecomputeExecutionStatus = 'completed' | 'failed' | 'cancelled' | 'stale'
|
||||
|
||||
@@ -35,6 +35,7 @@ export type RecomputeGeometryRuntime = {
|
||||
createCylinder(input: CreateCylinderInput): Promise<ShapeHandle>
|
||||
createSphere(input: CreateSphereInput): Promise<ShapeHandle>
|
||||
createCone(input: CreateConeInput): Promise<ShapeHandle>
|
||||
applyPlacement(input: ApplyPlacementInput): Promise<ShapeHandle>
|
||||
union(input: BooleanUnionInput): Promise<ShapeHandle>
|
||||
cut(input: BooleanCutInput): Promise<ShapeHandle>
|
||||
intersection(input: BooleanIntersectionInput): Promise<ShapeHandle>
|
||||
@@ -301,7 +302,7 @@ export const createFacadeGeometryRecomputeExecutor = (
|
||||
return base
|
||||
}
|
||||
if (base.status === 'failed' || object.sketch || geometry.capabilities().status !== 'ready') return base
|
||||
if (!['Part::Box', 'Part::Cylinder', 'Part::Sphere', 'Part::Cone', 'Part::Fuse', 'Part::Cut', 'Part::Common', 'PartDesign::Pad', 'PartDesign::Pocket', 'PartDesign::Revolution', 'PartDesign::Fillet', 'PartDesign::Chamfer'].includes(object.typeId)) return base
|
||||
if (!['Part::Box', 'Part::Cylinder', 'Part::Sphere', 'Part::Cone', 'Part::Fuse', 'Part::Cut', 'Part::Common', 'PartDesign::Pad', 'PartDesign::Pocket', 'PartDesign::Revolution', 'PartDesign::Fillet', 'PartDesign::Chamfer', 'PartDesign::LinearPattern'].includes(object.typeId)) return base
|
||||
|
||||
const requiresProfile = object.typeId === 'PartDesign::Pad' || object.typeId === 'PartDesign::Pocket' || object.typeId === 'PartDesign::Revolution'
|
||||
const profileObject = requiresProfile ? linkedObject(object, 'Profile', document) : undefined
|
||||
@@ -357,6 +358,26 @@ export const createFacadeGeometryRecomputeExecutor = (
|
||||
const baseShape = baseObject ? shapes.get(baseObject.id) : undefined
|
||||
if (!baseShape) return geometryFailure(object.id, 'BASE_SHAPE_MISSING', 'Fillet base has no valid recomputed Shape.')
|
||||
result = await geometry.fillet({ ...documentContext, base: baseShape, radius: numberProperty('Radius', 1) })
|
||||
} else if (object.typeId === 'PartDesign::LinearPattern') {
|
||||
const baseObject = linkedObject(object, 'Base', document)
|
||||
const baseShape = baseObject ? shapes.get(baseObject.id) : undefined
|
||||
if (!baseShape) return geometryFailure(object.id, 'BASE_SHAPE_MISSING', 'Linear pattern base has no valid recomputed Shape.')
|
||||
const occurrences = numberProperty('Occurrences', 2)
|
||||
if (!Number.isSafeInteger(occurrences) || occurrences < 2 || occurrences > 100) return geometryFailure(object.id, 'PATTERN_OCCURRENCES_INVALID', 'Linear pattern occurrences must be an integer between 2 and 100.')
|
||||
const length = numberProperty('Length', 20)
|
||||
if (!(length > 0)) return geometryFailure(object.id, 'PATTERN_LENGTH_INVALID', 'Linear pattern length must be greater than zero.')
|
||||
const direction = propertyValue(object, 'Direction')
|
||||
const axis: [number, number, number] = direction === 'Vertical' ? [0, 1, 0] : direction === 'Normal' ? [0, 0, 1] : [1, 0, 0]
|
||||
const copies: ShapeHandle[] = []
|
||||
try {
|
||||
for (let index = 1; index < occurrences; index += 1) {
|
||||
const offset = length * index / (occurrences - 1)
|
||||
copies.push(await geometry.applyPlacement({ ...documentContext, shape: baseShape, placement: { translation: [axis[0] * offset, axis[1] * offset, axis[2] * offset], rotationAxis: [0, 0, 1], rotationAngle: 0 } }))
|
||||
}
|
||||
result = await geometry.union({ ...documentContext, shapes: [baseShape, ...copies] })
|
||||
} finally {
|
||||
await Promise.allSettled(copies.map((copy) => geometry.release(copy)))
|
||||
}
|
||||
} else {
|
||||
const baseObject = linkedObject(object, 'Base', document)
|
||||
const baseShape = baseObject ? shapes.get(baseObject.id) : undefined
|
||||
|
||||
Reference in New Issue
Block a user