UNPKG

@jscad/vtree

Version:

Experimental Object Caching for JSCAD

94 lines (82 loc) 3.52 kB
const { flatten } = require('@jscad/array-utils') const modeling = require('@jscad/modeling') const { cube, cuboid, sphere, cylinder } = modeling.primitives const { circle, ellipse, rectangle, square } = modeling.primitives const { union, difference, intersection } = modeling.booleans const { translate, rotate, scale, mirror } = modeling.transforms const { hull, hullChain } = modeling.hulls const { expand, offset } = modeling.expansions const { extrudeLinear, extrudeRotate, extrudeFromSlices, extrudeRectangular } = modeling.extrusions const { measureArea, measureVolume, measureBounds } = modeling.measurements const { colorize } = modeling.colors /** generate actual geometry based on vtree node(s) * @param {} node * @param {} cache */ const generate = (node, cache) => { let operands if (Array.isArray(node)) { return flatten(node).map((n) => generate(n, cache)) } const { foundData, nodeHash } = cache.find(node) if (foundData) { return foundData } const nodeWithoutParams = (node, operands, fn) => { operands = flatten(node.children).map((n) => generate(n, cache)) return fn(operands) } const nodeWithParams = (node, operands, fn) => { operands = flatten(node.children).map((n) => generate(n, cache)) return fn(node.params, operands) } const lookup = { // various colorize: () => nodeWithParams(node, operands, colorize), // primitives cube: () => cube(node), cuboid: () => cuboid(node), sphere: () => sphere(node), cylinder: () => cylinder(node), circle: () => circle(node), ellipse: () => ellipse(node), rectangle: () => rectangle(node), square: () => square(node), // booelans union: () => nodeWithoutParams(node, operands, union), difference: () => nodeWithoutParams(node, operands, difference), intersection: () => nodeWithoutParams(node, operands, intersection), // transforms translate: () => nodeWithParams(node, operands, translate), rotate: () => nodeWithParams(node, operands, rotate), scale: () => nodeWithParams(node, operands, scale), mirror: () => nodeWithParams(node, operands, mirror), // hulls hull: () => nodeWithoutParams(node, operands, hull), hullChain: () => nodeWithoutParams(node, operands, hullChain), // expansions expand: () => nodeWithParams(node, operands, expand), offset: () => nodeWithParams(node, operands, offset), // extrusions // TODO: do we need an explicit operands = union(operands) extrudeLinear: () => nodeWithParams(node, operands, extrudeLinear), extrudeRotate: () => nodeWithParams(node, operands, extrudeRotate), extrudeRectangular: () => nodeWithParams(node, operands, extrudeRectangular), extrudeFromSlices: () => nodeWithParams(node, operands, extrudeFromSlices), // measurements measureArea: () => // first generate the actual geometry for the items, then compute measureArea(flatten(node.children).map((n) => generate(n, cache))), measureVolume: () => // first generate the actual geometry for the items, then compute measureVolume(flatten(node.children).map((n) => generate(n, cache))), measureBounds: () => // first generate the actual geometry for the items, then compute measureBounds(flatten(node.children).map((n) => generate(n, cache))) } const result = lookup[node.type] ? lookup[node.type]() : node cache.add(nodeHash, result) // lookup[nodeHash] = result return result } module.exports = generate