sparkles: Auto-fitting of collar via brianFitCollar option
This commit is contained in:
parent
bb81f44678
commit
ebb29cd5c5
9 changed files with 982 additions and 923 deletions
|
@ -14,6 +14,7 @@ export default {
|
||||||
options: {
|
options: {
|
||||||
// Constants
|
// Constants
|
||||||
brianFitSleeve: true,
|
brianFitSleeve: true,
|
||||||
|
brianFitCollar: true,
|
||||||
collarFactor: 4.8,
|
collarFactor: 4.8,
|
||||||
|
|
||||||
// Percentages
|
// Percentages
|
||||||
|
|
|
@ -35,7 +35,9 @@
|
||||||
focus: 'manSize34',
|
focus: 'manSize34',
|
||||||
models: freesewing.models.men
|
models: freesewing.models.men
|
||||||
}
|
}
|
||||||
pattern.settings.onl='base';
|
pattern.settings.nly= ['base'];
|
||||||
|
//pattern.options.brianFitSleeve = false;
|
||||||
|
//pattern.options.brianFitCollar = false;
|
||||||
//pattern.sampleOption('shoulderSlopeReduction');
|
//pattern.sampleOption('shoulderSlopeReduction');
|
||||||
//pattern.sampleMeasurement('shoulderSlope');
|
//pattern.sampleMeasurement('shoulderSlope');
|
||||||
//pattern.sampleModels(freesewing.models.men, 'manSize34');
|
//pattern.sampleModels(freesewing.models.men, 'manSize34');
|
||||||
|
|
1798
packages/brian/package-lock.json
generated
1798
packages/brian/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -59,8 +59,8 @@
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||||
"@freesewing/antman": "0.2.0",
|
"@freesewing/antman": "0.2.0",
|
||||||
"@freesewing/models": "0.4.0",
|
"@freesewing/models": "0.4.0",
|
||||||
"@freesewing/plugin-debug": "0.1.0",
|
"@freesewing/plugin-debug": "0.3.0",
|
||||||
"@freesewing/plugin-designer": "0.7.2",
|
"@freesewing/plugin-designer": "0.8.0",
|
||||||
"@freesewing/plugin-theme": "0.13.2",
|
"@freesewing/plugin-theme": "0.13.2",
|
||||||
"@freesewing/plugin-validate": "0.2.0",
|
"@freesewing/plugin-validate": "0.2.0",
|
||||||
"@freesewing/plugin-i18n": "0.0.1",
|
"@freesewing/plugin-i18n": "0.0.1",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import freesewing from "freesewing";
|
import freesewing from "freesewing";
|
||||||
|
import * as shared from "./shared";
|
||||||
|
|
||||||
var base = {
|
var base = {
|
||||||
draft: function(part) {
|
draft: function(part) {
|
||||||
part.render = false;
|
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
let {measurements, options, store, points, snippets, Point, Snippet, utils, complete } = part.shorthand();
|
let {units, debug, measurements, options, store, points, snippets, Point, Snippet, Path, paths, utils, complete } = part.shorthand();
|
||||||
|
|
||||||
store.set(
|
store.set(
|
||||||
"shoulderEase",
|
"shoulderEase",
|
||||||
|
@ -100,7 +99,7 @@ var base = {
|
||||||
.shiftTowards(points.neck, points.shoulder.dy(points.armholePitch) / 5)
|
.shiftTowards(points.neck, points.shoulder.dy(points.armholePitch) / 5)
|
||||||
.rotate(90, points.shoulder);
|
.rotate(90, points.shoulder);
|
||||||
|
|
||||||
// Neck opening
|
// Neck opening (back)
|
||||||
points._tmp4 = points.neck
|
points._tmp4 = points.neck
|
||||||
.shiftTowards(points.shoulder, 10)
|
.shiftTowards(points.shoulder, 10)
|
||||||
.rotate(-90, points.neck);
|
.rotate(-90, points.neck);
|
||||||
|
@ -110,9 +109,56 @@ var base = {
|
||||||
points.cbNeck.y
|
points.cbNeck.y
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fit collar
|
||||||
|
points.cfNeck = points.neck.rotate(-90, new Point(0, 0));
|
||||||
|
let target = measurements.neckCircumference * (1 + options.collarEase);
|
||||||
|
let delta = 0;
|
||||||
|
let run = 0;
|
||||||
|
do {
|
||||||
|
run++;
|
||||||
|
points.cfNeck = points.cfNeck.shift(90, delta / 3);
|
||||||
|
points.frontNeckCpEdge = utils.beamsIntersect(
|
||||||
|
points.neck,
|
||||||
|
points.neckCp2,
|
||||||
|
points.cfNeck,
|
||||||
|
new Point(20, points.cfNeck.y)
|
||||||
|
);
|
||||||
|
points.cfNeckCp1 = points.cfNeck.shiftFractionTowards(
|
||||||
|
points.frontNeckCpEdge,
|
||||||
|
0.55
|
||||||
|
);
|
||||||
|
points.neckCp2Front = points.neck.shiftFractionTowards(
|
||||||
|
points.frontNeckCpEdge,
|
||||||
|
0.65
|
||||||
|
);
|
||||||
|
paths.neckOpening = new Path()
|
||||||
|
.move(points.cfNeck)
|
||||||
|
.curve(points.cfNeckCp1, points.neckCp2Front, points.neck)
|
||||||
|
.curve(points.neckCp2, points.cbNeck, points.cbNeck)
|
||||||
|
.attr("class", "dashed stroke-xl various");
|
||||||
|
delta = paths.neckOpening.length() * 2 - target;
|
||||||
|
} while (Math.abs(delta) > 1 && options.brianFitCollar && run < 10);
|
||||||
|
delete paths.neckOpening;
|
||||||
|
if (options.brianFitCollar) {
|
||||||
|
debug(
|
||||||
|
{ style: "success", label: "🏁 Collar fitted" },
|
||||||
|
// prettier-ignore
|
||||||
|
`Target was ${units(target)}, delta of ${units(delta)} reached in ${run} attempts.`
|
||||||
|
);
|
||||||
|
} else
|
||||||
|
debug({ style: "warning", label: "🚫 Not fitting collar" }, "(in Brian)");
|
||||||
|
|
||||||
// Anchor point for sampling
|
// Anchor point for sampling
|
||||||
points.gridAnchor = points.cbHips;
|
points.gridAnchor = points.cbHips;
|
||||||
|
|
||||||
|
// Seamline
|
||||||
|
paths.saBase = shared.saBase("back", points, Path);
|
||||||
|
paths.seam = new Path()
|
||||||
|
.move(points.cbNeck)
|
||||||
|
.line(points.cbHips)
|
||||||
|
.join(paths.saBase)
|
||||||
|
.attr("class", "fabric");
|
||||||
|
|
||||||
// Complete pattern?
|
// Complete pattern?
|
||||||
if (complete) {
|
if (complete) {
|
||||||
points.title = new Point(
|
points.title = new Point(
|
||||||
|
|
|
@ -14,17 +14,15 @@ var front = {
|
||||||
points.armholePitchCp2.x -= deeper;
|
points.armholePitchCp2.x -= deeper;
|
||||||
|
|
||||||
// Rename cb (center back) to cf (center front)
|
// Rename cb (center back) to cf (center front)
|
||||||
for (let key of ["Neck", "Shoulder", "Armhole", "Waist", "Hips"]) {
|
for (let key of ["Shoulder", "Armhole", "Waist", "Hips"]) {
|
||||||
points[`cf${key}`] = new Point(
|
points[`cf${key}`] = new Point(
|
||||||
points[`cb${key}`].x,
|
points[`cb${key}`].x,
|
||||||
points[`cb${key}`].y
|
points[`cb${key}`].y
|
||||||
);
|
);
|
||||||
delete points[`cb${key}`];
|
delete points[`cb${key}`];
|
||||||
}
|
}
|
||||||
|
// Front neckline points
|
||||||
// Adapt neck opening
|
points.neckCp2 = new Point(points.neckCp2Front.x, points.neckCp2Front.y);
|
||||||
points.cfNeck = points.cfNeck.shift(-90, points.neck.x);
|
|
||||||
points.neckCp2 = points.cfNeck.shift(0, points.neck.x * 0.7);
|
|
||||||
|
|
||||||
// Seamline
|
// Seamline
|
||||||
paths.saBase = shared.saBase("front", points, Path);
|
paths.saBase = shared.saBase("front", points, Path);
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function saBase(side, points, Path) {
|
||||||
if (side === "back") {
|
if (side === "back") {
|
||||||
path.curve(points.neckCp2, points.cbNeck, points.cbNeck);
|
path.curve(points.neckCp2, points.cbNeck, points.cbNeck);
|
||||||
} else {
|
} else {
|
||||||
path.curve(points.neckCp2, points.cfNeck, points.cfNeck);
|
path.curve(points.neckCp2, points.cfNeckCp1, points.cfNeck);
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -7,8 +7,11 @@ var sleeve = {
|
||||||
|
|
||||||
// Wrist
|
// Wrist
|
||||||
let top = paths.sleevecap.bbox().topLeft.y;
|
let top = paths.sleevecap.bbox().topLeft.y;
|
||||||
debug("Sleevecap height is ", units(Math.abs(top)));
|
debug({ style: "info", label: "🗸 Sleevecap height" }, units(Math.abs(top)));
|
||||||
debug("Sleeve width is ", units(points.bicepsRight.x * 2));
|
debug(
|
||||||
|
{ style: "info", label: "🗸 Sleevecap width" },
|
||||||
|
units(points.bicepsRight.x * 2)
|
||||||
|
);
|
||||||
points.centerWrist = new Point(
|
points.centerWrist = new Point(
|
||||||
0,
|
0,
|
||||||
top + measurements.shoulderToWrist * (1 + options.sleeveLengthBonus)
|
top + measurements.shoulderToWrist * (1 + options.sleeveLengthBonus)
|
||||||
|
|
|
@ -131,13 +131,13 @@ function draftSleevecap(part, run) {
|
||||||
|
|
||||||
// Store sleevecap length
|
// Store sleevecap length
|
||||||
store.set("sleevecapLength", paths.sleevecap.length());
|
store.set("sleevecapLength", paths.sleevecap.length());
|
||||||
if (run === 1) {
|
if (run === 0) {
|
||||||
let armholeLength =
|
let armholeLength =
|
||||||
store.get("frontArmholeLength") + store.get("backArmholeLength");
|
store.get("frontArmholeLength") + store.get("backArmholeLength");
|
||||||
let sleevecapEase = armholeLength * options.sleevecapEase;
|
let sleevecapEase = armholeLength * options.sleevecapEase;
|
||||||
store.set("sleevecapEase", sleevecapEase);
|
store.set("sleevecapEase", sleevecapEase);
|
||||||
store.set("sleevecapTarget", armholeLength + sleevecapEase);
|
store.set("sleevecapTarget", armholeLength + sleevecapEase);
|
||||||
debug("Sleevecap ease is", units(sleevecapEase));
|
debug({ style: "info", label: "🗸 Sleevecap ease" }, units(sleevecapEase));
|
||||||
|
|
||||||
// Uncomment this line to see all sleevecap iterations
|
// Uncomment this line to see all sleevecap iterations
|
||||||
//paths[run] = paths.sleevecap;
|
//paths[run] = paths.sleevecap;
|
||||||
|
@ -150,21 +150,30 @@ var sleevecap = {
|
||||||
let {debug, store, units, sa, measurements, options, Point, points, Path, paths } = part.shorthand();
|
let {debug, store, units, sa, measurements, options, Point, points, Path, paths } = part.shorthand();
|
||||||
|
|
||||||
store.set("sleeveFactor", 1);
|
store.set("sleeveFactor", 1);
|
||||||
let run = 1;
|
let run = 0;
|
||||||
|
let delta = 0;
|
||||||
do {
|
do {
|
||||||
draftSleevecap(part, run);
|
draftSleevecap(part, run);
|
||||||
debug(
|
delta = sleevecapDelta(store);
|
||||||
`Sleevecap draft ${run}, sleevecap delta is ${units(
|
|
||||||
sleevecapDelta(store)
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
sleevecapAdjust(store);
|
sleevecapAdjust(store);
|
||||||
run++;
|
run++;
|
||||||
} while (
|
} while (
|
||||||
options.brianFitSleeve === true &&
|
options.brianFitSleeve === true &&
|
||||||
run < 100 &&
|
run < 30 &&
|
||||||
Math.abs(sleevecapDelta(store)) > 2
|
Math.abs(sleevecapDelta(store)) > 2
|
||||||
);
|
);
|
||||||
|
if (options.brianFitSleeve) {
|
||||||
|
debug(
|
||||||
|
{ style: "success", label: "🏁 Sleevecap fitted" },
|
||||||
|
`Target was ${units(store.get("sleevecapTarget"))}, delta of ${units(
|
||||||
|
delta
|
||||||
|
)} reached in ${run} attempts.`
|
||||||
|
);
|
||||||
|
} else
|
||||||
|
debug(
|
||||||
|
{ style: "warning", label: "🚫 Not fitting sleevecap" },
|
||||||
|
"(in Brian)"
|
||||||
|
);
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
paths.sleevecap.attr("class", "fabric");
|
paths.sleevecap.attr("class", "fabric");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue