UNPKG

@freesewing/core

Version:

A library for creating made-to-measure sewing patterns

217 lines (201 loc) 6.03 kB
/** * A class for handling pattern sampling * @param {Pattern} pattern the pattern that will be sampled */ export function PatternSampler(pattern) { this.pattern = pattern } /** * Handles measurement sampling * * @return {object} this - The Pattern instance */ PatternSampler.prototype.sampleMeasurement = function (measurementName) { this.pattern.store.log.debug(`Sampling measurement \`${measurementName}\``) this.pattern.__runHooks('preSample') this.pattern.__applySettings(this.__measurementSets(measurementName)) this.pattern.__init() this.pattern.__runHooks('postSample') return this.pattern.draft() } /** * Handles models sampling * * @return {object} this - The Pattern instance */ PatternSampler.prototype.sampleModels = function (models, focus = false) { this.pattern.store.log.debug(`Sampling models \`${Object.keys(models).join(', ')}\``) this.pattern.__runHooks('preSample') this.pattern.__applySettings(this.__modelSets(models, focus)) this.pattern.__init() this.pattern.__runHooks('postSample') return this.pattern.draft() } /** * Handles option sampling * * @return {object} this - The Pattern instance */ PatternSampler.prototype.sampleOption = function (optionName) { this.pattern.store.log.debug(`Sampling option \`${optionName}\``) this.pattern.__runHooks('preSample') this.pattern.__applySettings(this.__optionSets(optionName)) this.pattern.__init() this.pattern.__runHooks('postSample') return this.pattern.draft() } /** * Generates an array of settings.options objects for sampling a list or boolean option * * @private * @param {string} optionName - Name of the option to sample * @return {Array} sets - The list of settings objects */ PatternSampler.prototype.__listBoolOptionSets = function (optionName) { let option = this.pattern.config.options[optionName] const base = this.__setBase() const sets = [] let run = 1 if (typeof option.bool !== 'undefined') option = { list: [false, true] } for (const choice of option.list) { const settings = { ...base, options: { ...base.options, }, idPrefix: `sample-${run}`, partClasses: `sample-${run}`, } settings.options[optionName] = choice sets.push(settings) run++ } return sets } /** * Generates an array of settings objects for sampling a measurement * * @private * @param {string} measurementName - The name of the measurement to sample * @return {Array} sets - The list of settings objects */ PatternSampler.prototype.__measurementSets = function (measurementName) { let val = this.pattern.settings[0].measurements[measurementName] if (val === undefined) this.pattern.store.log.error( `Cannot sample measurement \`${measurementName}\` because it's \`undefined\`` ) let step = val / 50 val = val * 0.9 const sets = [] const base = this.__setBase() for (let run = 1; run < 11; run++) { const settings = { ...base, measurements: { ...base.measurements, }, idPrefix: `sample-${run}`, partClasses: `sample-${run}`, } settings.measurements[measurementName] = val sets.push(settings) val += step } return sets } /** * Generates an array of settings objects for sampling a list of models * * @private * @param {object} models - The models to sample * @param {string} focus - The ID of the model that should be highlighted * @return {Array} sets - The list of settings objects */ PatternSampler.prototype.__modelSets = function (models, focus = false) { const sets = [] const base = this.__setBase() let run = 1 // If there's a focus, do it first so it's at the bottom of the SVG if (focus) { sets.push({ ...base, measurements: models[focus], idPrefix: `sample-${run}`, partClasses: `sample-${run} sample-focus`, }) run++ delete models[focus] } for (const measurements of Object.values(models)) { sets.push({ ...base, measurements, idPrefix: `sample-${run}`, partClasses: `sample-${run}`, }) } return sets } /** * Generates an array of settings objects for sampling an option * * @private * @param {string} optionName - The name of the option to sample * @return {Array} sets - The list of settings objects */ PatternSampler.prototype.__optionSets = function (optionName) { const sets = [] if (!(optionName in this.pattern.config.options)) return sets let option = this.pattern.config.options[optionName] if (typeof option.list === 'object' || typeof option.bool !== 'undefined') return this.__listBoolOptionSets(optionName) let factor = 1 let step, val let numberRuns = 10 let stepFactor = numberRuns - 1 if (typeof option.min === 'undefined' || typeof option.max === 'undefined') { const min = option * 0.9 const max = option * 1.1 option = { min, max } } if (typeof option.pct !== 'undefined') factor = 100 val = option.min / factor if (typeof option.count !== 'undefined' || typeof option.mm !== 'undefined') { const numberOfCounts = option.max - option.min + 1 if (numberOfCounts < 10) { numberRuns = numberOfCounts stepFactor = Math.max(numberRuns - 1, 1) } } step = (option.max / factor - val) / stepFactor const base = this.__setBase() const roundVal = typeof option.count !== 'undefined' || typeof option.mm !== 'undefined' for (let run = 1; run <= numberRuns; run++) { const settings = { ...base, options: { ...base.options, }, idPrefix: `sample-${run}`, partClasses: `sample-${run}`, } settings.options[optionName] = roundVal ? Math.ceil(val) : val sets.push(settings) val += step } return sets } /** * Returns the base/defaults to generate a set of settings * * @private * @return {object} settings - The settings object */ PatternSampler.prototype.__setBase = function () { return { measurements: {}, options: {}, ...this.pattern.settings[0], } }