"use strict"
/**
* Builds columns. Input 2D profiles must be centred at (0, 0, 0)
* @namespace builders.columns
*/
const columnBuilder = ({ lib, swLib }) => {
const { cuboid, roundedCylinder, cylinder } = lib.primitives
const { align } = lib.transforms
const { subtract, union } = lib.booleans
const { extrudeLinear } = lib.extrusions
const { measureBoundingBox } = lib.measurements
/**
* Simple cuboid
* @param {Object} opts
* @param {number} opts.height - element height
* @param {number} opts.radius - element radius
*/
const colCuboid = (opts) => {
return cuboid({ size: [opts.radius * 2, opts.radius * 2, opts.height] });
}
/**
* Simple cylinder
* @param {Object} opts
* @param {number} opts.height - element height
* @param {number} opts.radius - element radius
*/
const colCylinder = (opts) => {
return cylinder({ radius: opts.radius, height: opts.height });
}
/**
* Simple round cylinder
* @param {Object} opts
* @param {number} opts.height - element height
* @param {number} opts.radius - element radius
* @param {number} opts.roundRadius - radius of cylinder edge
*/
const capRdCylinder = (opts) => {
const rdRadius = opts.roundRadius || 0.75;
const baseShape = roundedCylinder({ radius: opts.radius, height: opts.height * 2, roundRadius: rdRadius });
const cutBlock = align(
{ modes: ['none', 'none', 'min'] },
cuboid({ size: [opts.radius * 2.5, opts.radius * 2.5, opts.height * 2] })
);
return subtract(baseShape, cutBlock);
}
/**
* Base round cylinder
* @param {Object} opts
* @param {number} opts.height - element height
* @param {number} opts.radius - element radius
* @param {number} opts.roundRadius - radius of cylinder edge
*/
const baseRdCylinder = (opts) => {
const rdRadius = opts.roundRadius || 1;
const baseShape = roundedCylinder({ radius: opts.radius, height: opts.height * 2, roundRadius: rdRadius });
const cutBlock = align(
{ modes: ['none', 'none', 'max'] },
cuboid({ size: [opts.radius * 2.5, opts.radius * 2.5, opts.height * 2] })
);
return subtract(baseShape, cutBlock);
}
/**
* Simple extrude
* @param {Object} opts
* @param {number} opts.height - element height
* @param {geom2.Geom2} geomProfile - 2D cross-section profile
*/
const colExtrude = (opts, geomProfile) => {
return extrudeLinear({ height: opts.height }, geomProfile);
}
/**
* Defines the construction of column sub-components (base, shaft, capital).
* All functions follow the function signature of base.cuboid().
* @access private
*/
const columnPartBuilder = {
base: {
cuboid: colCuboid,
cylinder: colCylinder,
roundCylinder: baseRdCylinder,
extrude: colExtrude,
},
shaft: {
cuboid: colCuboid,
cylinder: colCylinder,
extrude: colExtrude,
},
capital: {
cuboid: colCuboid,
cylinder: colCylinder,
roundCylinder: capRdCylinder,
extrude: colExtrude,
},
}
return {
columnPartBuilder,
/**
* Builds a three-part column using the specified dimensions and styles.
* @memberof builders.columns
* @instance
* @param {Object} opts
* @param {Array<string|number|geom2.Geom2|null>} opts.base - specs for column base (style, height, radius, geomProfile)
* @param {Array<string|number|geom2.Geom2|null>} opts.shaft - specs for column shaft (style, radius, geomProfile)
* @param {Array<string|number|geom2.Geom2|null>} opts.capital - specs for column capital (style, height, radius, geomProfile)
* @param {number} opts.height - total height of column
*/
threePtColumn: (opts) => {
const baseStyle = opts.base[0];
const shaftStyle = opts.shaft[0];
const capitalStyle = opts.capital[0];
const base = columnPartBuilder.base[baseStyle]({
height: opts.base[1],
radius: opts.base[2],
}, opts.base[3]);
const shaft = columnPartBuilder.shaft[shaftStyle]({
height: opts.height,
radius: opts.shaft[1],
}, opts.shaft[2]);
const capital = columnPartBuilder.capital[capitalStyle]({
height: opts.capital[1],
radius: opts.capital[2],
}, opts.capital[3]);
const shaftBbox = measureBoundingBox(shaft);
const [shaftMin, shaftMax] = [shaftBbox[0][2], shaftBbox[1][2]];
const alignedBase = align({ modes: ['center', 'center', 'min'], relativeTo: [0, 0, shaftMin] }, base)
const alignedCap = align({ modes: ['center', 'center', 'max'], relativeTo: [0, 0, shaftMax] }, capital)
return align({ modes: ['center', 'center', 'min'] }, union(alignedBase, shaft, alignedCap))
}
}
}
module.exports = { init: columnBuilder };