sparkles: Sleevecap part, small fixes and scalebox
This commit is contained in:
parent
22cf515068
commit
52f6e7e850
10 changed files with 277 additions and 197 deletions
|
@ -1,4 +1,3 @@
|
|||
/** Pattern parts */
|
||||
export default {
|
||||
name: "brian",
|
||||
measurements: [
|
||||
|
@ -15,7 +14,7 @@ export default {
|
|||
],
|
||||
options: {
|
||||
// Constants
|
||||
collarFactor: { val: 4.8, type: "constant" },
|
||||
collarFactor: 4.8,
|
||||
|
||||
// Percentages
|
||||
acrossBackFactor: { val: 97, min: 93, max: 100 },
|
||||
|
@ -30,14 +29,14 @@ export default {
|
|||
shoulderEase: { val: 0, min: -2, max: 6 },
|
||||
shoulderSlopeReduction: { val: 0, min: 0, max: 8 },
|
||||
sleevecapEase: { val: 1, min: 0, max: 10 },
|
||||
sleevecapBackFactorX: { val: 50, min: 35, max: 65 },
|
||||
sleevecapBackFactorX: { val: 60, min: 35, max: 65 },
|
||||
sleevecapBackFactorY: { val: 33, min: 35, max: 65 },
|
||||
sleevecapFrontFactorX: { val: 50, min: 35, max: 65 },
|
||||
sleevecapFrontFactorX: { val: 55, min: 35, max: 65 },
|
||||
sleevecapFrontFactorY: { val: 33, min: 35, max: 65 },
|
||||
sleevecapQ1Offset: { val: 5, min: 0, max: 7 },
|
||||
sleevecapQ1Offset: { val: 3, min: 0, max: 7 },
|
||||
sleevecapQ2Offset: { val: 5.5, min: 0, max: 7 },
|
||||
sleevecapQ3Offset: { val: 4.5, min: 0, max: 7 },
|
||||
sleevecapQ4Offset: { val: 2, min: 0, max: 7 },
|
||||
sleevecapQ4Offset: { val: 1, min: 0, max: 7 },
|
||||
sleevecapQ1Spread1: { val: 6, min: 4, max: 20 },
|
||||
sleevecapQ1Spread2: { val: 15, min: 4, max: 20 },
|
||||
sleevecapQ2Spread1: { val: 15, min: 4, max: 20 },
|
||||
|
|
|
@ -17,15 +17,26 @@
|
|||
<script type="text/javascript" src="tmp/antmantest.js"></script>
|
||||
<script>
|
||||
var pattern = freesewing.patterns.brian
|
||||
.with(freesewing.plugins.debug)
|
||||
// .with(freesewing.plugins.debug)
|
||||
.with(freesewing.plugins.theme)
|
||||
.with(freesewing.plugins.designer)
|
||||
// .with(freesewing.plugins.designer)
|
||||
.with(freesewing.plugins.validate)
|
||||
;
|
||||
|
||||
pattern.settings.paperless = true;
|
||||
pattern.settings.measurements = freesewing.models.men.manSize36;
|
||||
|
||||
console.log(freesewing.plugins.bundle);
|
||||
//pattern.settings.paperless = true;
|
||||
//pattern.settings.measurements = freesewing.models.men.manSize36;
|
||||
pattern.settings.measurements = {
|
||||
bicepsCircumference: 335
|
||||
, centerBackNeckToWaist: 480
|
||||
, chestCircumference: 1080
|
||||
, naturalWaistToHip: 120
|
||||
, neckCircumference: 420
|
||||
, shoulderSlope: 55
|
||||
, shoulderToShoulder: 470
|
||||
, hipsCircumference: 950
|
||||
, shoulderToWrist: 700
|
||||
, wristCircumference: 190
|
||||
}
|
||||
pattern.settings.sa = 10;
|
||||
pattern.settings.units = 'metric';
|
||||
pattern.settings.sample = {
|
||||
|
@ -33,9 +44,13 @@ pattern.settings.sample = {
|
|||
measurement: 'shoulderToShoulder'
|
||||
}
|
||||
pattern.debug('debug test from index', 'foo');
|
||||
//pattern.sampleOption('sleeveLengthBonus');
|
||||
//pattern.sampleMeasurement('bicepsCircumference');
|
||||
//pattern.sampleModels(freesewing.antmantest);
|
||||
pattern.settings.idPrefix = 'fme-';
|
||||
//pattern.settings.only = ['base','sleevecap'];
|
||||
console.log(pattern);
|
||||
|
||||
//pattern.sampleOption('chestEase');
|
||||
//pattern.sampleMeasurement('shoulderSlope');
|
||||
//pattern.sampleModels(freesewing.models.men);
|
||||
pattern.draft();
|
||||
document.getElementById("svg").innerHTML = pattern.render();
|
||||
|
||||
|
|
18
packages/brian/package-lock.json
generated
18
packages/brian/package-lock.json
generated
|
@ -911,14 +911,15 @@
|
|||
}
|
||||
},
|
||||
"@freesewing/plugin-bundle": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@freesewing/plugin-bundle/-/plugin-bundle-0.0.1.tgz",
|
||||
"integrity": "sha512-LLqw/HD23K1XmnuoPUbUK9PhrawcKemYn8eBjt1Jvqn9xD6HvndPeB8nwJ4/i/L02yA8ZqXTDnGvi5gMzc0kVw==",
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@freesewing/plugin-bundle/-/plugin-bundle-0.1.2.tgz",
|
||||
"integrity": "sha512-NXlU1QdiwfEKBOgiwOS4Yp516bYGjPE9npPTU2rmjweyigwF4et1DcO3cngn9AraOjfMT9cmgIQbppN91u/uzA==",
|
||||
"requires": {
|
||||
"@freesewing/plugin-cutonfold": "0.9.0",
|
||||
"@freesewing/plugin-dimension": "0.4.0",
|
||||
"@freesewing/plugin-grainline": "0.0.2",
|
||||
"@freesewing/plugin-logo": "0.3.2",
|
||||
"@freesewing/plugin-scalebox": "0.1.0",
|
||||
"@freesewing/plugin-title": "0.6.2"
|
||||
}
|
||||
},
|
||||
|
@ -942,6 +943,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@freesewing/plugin-logo/-/plugin-logo-0.3.2.tgz",
|
||||
"integrity": "sha512-cYmMAcvWl7B0RC3LUaCNRVj98nDIsT47Uf+84fQAnsAeZeAyiA1Y1NmPlmb3n30znlFwiJYjII7cRBn73l6wGQ=="
|
||||
},
|
||||
"@freesewing/plugin-scalebox": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@freesewing/plugin-scalebox/-/plugin-scalebox-0.1.0.tgz",
|
||||
"integrity": "sha512-CKPM5BjJI4p0dLHIFlhaw+Zn7QCbCq9j8R50oSQGuarUXKD4g6Vp2uQYK9NVFbxHBy9PBRpnRSQueN4OEzGdTw=="
|
||||
},
|
||||
"@freesewing/plugin-title": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@freesewing/plugin-title/-/plugin-title-0.6.2.tgz",
|
||||
|
@ -2875,9 +2881,9 @@
|
|||
}
|
||||
},
|
||||
"freesewing": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.6.1.tgz",
|
||||
"integrity": "sha512-G4NIp9TqBi8zuoIHkTSkvqW7+vrs7pyeQLEm41CoLvOXwRYDAtY+57sfh1b6ohpx35Jnh3rQ1VAhsQ5e4bD42A==",
|
||||
"version": "0.8.4",
|
||||
"resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.8.4.tgz",
|
||||
"integrity": "sha512-znA7n8TW3sM1+CBDkM54nhuwUGJGPxboQvtXW0LGcIBU5M2urBAy5pinGMw570PtnMfWwWp/wSw3vI3SjHkI6w==",
|
||||
"requires": {
|
||||
"bezier-js": "2.2.14",
|
||||
"bin-pack": "1.0.2",
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"freesewing": "^0.6.0",
|
||||
"@freesewing/plugin-bundle": "0.0.1"
|
||||
"freesewing": "^0.8.4",
|
||||
"@freesewing/plugin-bundle": "0.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.0.0-beta.56",
|
||||
|
|
|
@ -7,7 +7,12 @@ var back = {
|
|||
let {store, sa, points, Path, paths, Snippet, snippets, final, paperless, macro} = part.shorthand();
|
||||
|
||||
// Seamline
|
||||
paths.seam = shared.seamLine("back", points, Path);
|
||||
paths.saBase = shared.saBase("back", points, Path);
|
||||
paths.seam = new Path()
|
||||
.move(points.cbNeck)
|
||||
.line(points.cbHips)
|
||||
.join(paths.saBase)
|
||||
.attr("class", "fabric");
|
||||
|
||||
// Store lengths to fit sleeve
|
||||
store.set("backArmholeLength", shared.armholeLength(points, Path));
|
||||
|
@ -26,7 +31,14 @@ var back = {
|
|||
|
||||
macro("title", { at: points.title, nr: 2, title: "back" });
|
||||
snippets.armholePitchNotch = new Snippet("bnotch", points.armholePitch);
|
||||
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
|
||||
if (sa) {
|
||||
paths.sa = paths.saBase
|
||||
.offset(sa)
|
||||
.attr("class", "fabric sa")
|
||||
.line(points.cbNeck)
|
||||
.move(points.cbHips);
|
||||
paths.sa.line(paths.sa.start());
|
||||
}
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
|
|
|
@ -26,7 +26,13 @@ var front = {
|
|||
points.cfNeck = points.cfNeck.shift(-90, points.neck.x);
|
||||
points.neckCp2 = points.cfNeck.shift(0, points.neck.x * 0.7);
|
||||
|
||||
paths.seam = shared.seamLine("front", points, Path);
|
||||
// Seamline
|
||||
paths.saBase = shared.saBase("front", points, Path);
|
||||
paths.seam = new Path()
|
||||
.move(points.cfNeck)
|
||||
.line(points.cfHips)
|
||||
.join(paths.saBase)
|
||||
.attr("class", "fabric");
|
||||
|
||||
// Store lengths to fit sleeve
|
||||
store.set("frontArmholeLength", shared.armholeLength(points, Path));
|
||||
|
@ -44,7 +50,14 @@ var front = {
|
|||
});
|
||||
macro("title", { at: points.title, nr: 1, title: "front" });
|
||||
snippets.armholePitchNotch = new Snippet("notch", points.armholePitch);
|
||||
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
|
||||
if (sa) {
|
||||
paths.sa = paths.saBase
|
||||
.offset(sa)
|
||||
.attr("class", "fabric sa")
|
||||
.line(points.cfNeck)
|
||||
.move(points.cfHips);
|
||||
paths.sa.line(paths.sa.start());
|
||||
}
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
|
|
|
@ -7,6 +7,7 @@ import { version } from "../package.json";
|
|||
import base from "./base";
|
||||
import back from "./back";
|
||||
import front from "./front";
|
||||
import sleevecap from "./sleevecap";
|
||||
import sleeve from "./sleeve";
|
||||
|
||||
var pattern = new freesewing.Pattern({ version: version, ...config }).with(
|
||||
|
@ -15,9 +16,25 @@ var pattern = new freesewing.Pattern({ version: version, ...config }).with(
|
|||
|
||||
pattern.draft = function() {
|
||||
this.parts.base = this.draftBase(new pattern.Part());
|
||||
if (!this.needs("base", true)) this.parts.base.render = false;
|
||||
if (this.needs(["back", "front", "sleeve", "sleevecap"])) {
|
||||
this.parts.back = this.draftBack(new pattern.Part().copy(this.parts.base));
|
||||
this.parts.front = this.draftFront(new pattern.Part().copy(this.parts.back));
|
||||
this.parts.sleeve = this.draftSleeve(new pattern.Part());
|
||||
}
|
||||
if (this.needs(["front", "sleeve", "sleevecap"])) {
|
||||
this.parts.front = this.draftFront(
|
||||
new pattern.Part().copy(this.parts.back)
|
||||
);
|
||||
}
|
||||
if (this.needs(["sleeve", "sleevecap"])) {
|
||||
this.parts.sleevecap = this.draftSleevecap(new pattern.Part());
|
||||
// Don't render sleevecap unless specifically requested
|
||||
if (!this.needs("sleevecap", true)) this.parts.sleevecap.render = false;
|
||||
}
|
||||
if (this.needs("sleeve")) {
|
||||
this.parts.sleeve = this.draftSleeve(
|
||||
new pattern.Part().copy(this.parts.sleevecap)
|
||||
);
|
||||
}
|
||||
|
||||
return pattern;
|
||||
};
|
||||
|
@ -25,6 +42,7 @@ pattern.draft = function() {
|
|||
pattern.draftBase = part => base.draft(part);
|
||||
pattern.draftBack = part => back.draft(part);
|
||||
pattern.draftFront = part => front.draft(part);
|
||||
pattern.draftSleevecap = part => sleevecap.draft(part);
|
||||
pattern.draftSleeve = part => sleeve.draft(part);
|
||||
|
||||
export default pattern;
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
export function seamLine(side, points, Path) {
|
||||
export function saBase(side, points, Path) {
|
||||
let path = new Path();
|
||||
if (side === "back") {
|
||||
path.move(points.cbNeck);
|
||||
path.line(points.cbHips);
|
||||
} else {
|
||||
path.move(points.cfNeck);
|
||||
path.line(points.cfHips);
|
||||
}
|
||||
if (side === "back") path.move(points.cbHips);
|
||||
else path.move(points.cfHips);
|
||||
path
|
||||
.line(points.hips)
|
||||
.line(points.armhole)
|
||||
|
@ -19,7 +14,6 @@ export function seamLine(side, points, Path) {
|
|||
} else {
|
||||
path.curve(points.neckCp2, points.cfNeck, points.cfNeck);
|
||||
}
|
||||
path.close().attr("class", "fabric");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -41,7 +35,6 @@ export function shoulderToArmholePitch(points, Path) {
|
|||
}
|
||||
|
||||
export function dimensions(macro, points, Path, sa) {
|
||||
console.log("points for dimensions", points);
|
||||
macro("pd", {
|
||||
path: new Path()
|
||||
.move(points.armhole)
|
||||
|
|
|
@ -1,167 +1,10 @@
|
|||
import freesewing from "freesewing";
|
||||
|
||||
/** Calculates the differece between actual and optimal sleevecap length
|
||||
* Positive values mean sleevecap is longer than armhole
|
||||
*/
|
||||
function sleevecapDelta(store) {
|
||||
return store.get("sleevecapLength") - store.get("sleevecapTarget");
|
||||
}
|
||||
|
||||
function sleevecapAdjust(store) {
|
||||
let delta = sleevecapDelta(store);
|
||||
let factor = store.get("sleeveFactor");
|
||||
if (delta > 0) factor = factor * 0.98;
|
||||
else factor = factor * 1.02;
|
||||
store.set("sleeveFactor", factor);
|
||||
}
|
||||
|
||||
function draftSleevecap(part, run) {
|
||||
// prettier-ignore
|
||||
let {debug, units, store, measurements, options, Point, points, Path, paths} = part.shorthand();
|
||||
// Sleeve center axis
|
||||
points.centerBiceps = new Point(0, 0);
|
||||
points.centerCap = points.centerBiceps.shift(
|
||||
90,
|
||||
measurements.bicepsCircumference *
|
||||
(1 + options.bicepsEase) *
|
||||
options.armholeDepthFactor *
|
||||
store.get("sleeveFactor")
|
||||
);
|
||||
|
||||
// Left and right biceps points, limit impact of sleeveFactor to 25%
|
||||
let halfWidth =
|
||||
(measurements.bicepsCircumference * (1 + options.bicepsEase)) / 2;
|
||||
points.bicepsLeft = points.centerBiceps.shift(
|
||||
180,
|
||||
halfWidth * options.sleeveWidthGuarantee +
|
||||
halfWidth * (1 - options.sleeveWidthGuarantee) * store.get("sleeveFactor")
|
||||
);
|
||||
points.bicepsRight = points.bicepsLeft.flipX(points.centerBiceps);
|
||||
|
||||
// Pitch points
|
||||
let width = points.bicepsRight.x;
|
||||
let height = points.centerCap.y;
|
||||
points.backPitch = new Point(
|
||||
-1 * width * options.sleevecapBackFactorX,
|
||||
height * options.sleevecapBackFactorY
|
||||
);
|
||||
points.frontPitch = new Point(
|
||||
width * options.sleevecapFrontFactorX,
|
||||
height * options.sleevecapFrontFactorY
|
||||
);
|
||||
|
||||
// 4 sleevecap quadrants
|
||||
// Base points
|
||||
points.capQ1Base = points.frontPitch.shiftFractionTowards(
|
||||
points.bicepsRight,
|
||||
0.5
|
||||
);
|
||||
points.capQ2Base = points.frontPitch.shiftFractionTowards(
|
||||
points.centerCap,
|
||||
0.5
|
||||
);
|
||||
points.capQ3Base = points.backPitch.shiftFractionTowards(
|
||||
points.centerCap,
|
||||
0.5
|
||||
);
|
||||
points.capQ4Base = points.backPitch.shiftFractionTowards(
|
||||
points.bicepsLeft,
|
||||
0.5
|
||||
);
|
||||
// Offset points
|
||||
let baseOffset = measurements.bicepsCircumference * (1 + options.bicepsEase);
|
||||
points.capQ1 = points.capQ1Base.shift(
|
||||
points.bicepsRight.angle(points.frontPitch) + 90,
|
||||
baseOffset * options.sleevecapQ1Offset
|
||||
);
|
||||
points.capQ2 = points.capQ2Base.shift(
|
||||
points.centerCap.angle(points.frontPitch) + 90,
|
||||
baseOffset * options.sleevecapQ2Offset
|
||||
);
|
||||
points.capQ3 = points.capQ3Base.shift(
|
||||
points.centerCap.angle(points.backPitch) - 90,
|
||||
baseOffset * options.sleevecapQ3Offset
|
||||
);
|
||||
points.capQ4 = points.capQ4Base.shift(
|
||||
points.bicepsLeft.angle(points.backPitch) - 90,
|
||||
baseOffset * options.sleevecapQ4Offset
|
||||
);
|
||||
// Control points
|
||||
points.capQ1Cp1 = points.capQ1.shift(
|
||||
points.frontPitch.angle(points.bicepsRight),
|
||||
baseOffset * options.sleevecapQ1Spread1
|
||||
);
|
||||
points.capQ1Cp2 = points.capQ1.shift(
|
||||
points.frontPitch.angle(points.bicepsRight),
|
||||
baseOffset * options.sleevecapQ1Spread2 * -1
|
||||
);
|
||||
points.capQ2Cp1 = points.capQ2.shift(
|
||||
points.centerCap.angle(points.frontPitch),
|
||||
baseOffset * options.sleevecapQ2Spread1
|
||||
);
|
||||
points.capQ2Cp2 = points.capQ2.shift(
|
||||
points.centerCap.angle(points.frontPitch),
|
||||
baseOffset * options.sleevecapQ2Spread2 * -1
|
||||
);
|
||||
points.capQ3Cp1 = points.capQ3.shift(
|
||||
points.backPitch.angle(points.centerCap),
|
||||
baseOffset * options.sleevecapQ3Spread1
|
||||
);
|
||||
points.capQ3Cp2 = points.capQ3.shift(
|
||||
points.backPitch.angle(points.centerCap),
|
||||
baseOffset * options.sleevecapQ3Spread2 * -1
|
||||
);
|
||||
points.capQ4Cp1 = points.capQ4.shift(
|
||||
points.bicepsLeft.angle(points.backPitch),
|
||||
baseOffset * options.sleevecapQ4Spread1
|
||||
);
|
||||
points.capQ4Cp2 = points.capQ4.shift(
|
||||
points.bicepsLeft.angle(points.backPitch),
|
||||
baseOffset * options.sleevecapQ4Spread2 * -1
|
||||
);
|
||||
|
||||
// Sleevecap seamline
|
||||
paths.sleevecap = new Path()
|
||||
.move(points.bicepsRight)
|
||||
.curve(points.bicepsRight, points.capQ1Cp1, points.capQ1)
|
||||
.curve(points.capQ1Cp2, points.capQ2Cp1, points.capQ2)
|
||||
.curve(points.capQ2Cp2, points.capQ3Cp1, points.capQ3)
|
||||
.curve(points.capQ3Cp2, points.capQ4Cp1, points.capQ4)
|
||||
.curve(points.capQ4Cp2, points.bicepsLeft, points.bicepsLeft);
|
||||
|
||||
// Store sleevecap length
|
||||
store.set("sleevecapLength", paths.sleevecap.length());
|
||||
if (run === 1) {
|
||||
let armholeLength =
|
||||
store.get("frontArmholeLength") + store.get("backArmholeLength");
|
||||
let sleevecapEase = armholeLength * options.sleevecapEase;
|
||||
store.set("sleevecapEase", sleevecapEase);
|
||||
store.set("sleevecapTarget", armholeLength + sleevecapEase);
|
||||
debug("Sleevecap ease is", units(sleevecapEase));
|
||||
|
||||
// Uncomment this line to see all sleevecap iterations
|
||||
//paths[run] = paths.sleevecap;
|
||||
}
|
||||
}
|
||||
|
||||
var sleeve = {
|
||||
draft: function(part) {
|
||||
// prettier-ignore
|
||||
let {debug, store, units, sa, measurements, options, Point, points, Path, paths, Snippet, snippets, final, paperless, macro} = part.shorthand();
|
||||
|
||||
store.set("sleeveFactor", 1);
|
||||
let run = 1;
|
||||
do {
|
||||
draftSleevecap(part, run);
|
||||
debug(
|
||||
`Sleevecap draft ${run}, sleevecap delta is ${units(
|
||||
sleevecapDelta(store)
|
||||
)}`
|
||||
);
|
||||
sleevecapAdjust(store);
|
||||
run++;
|
||||
} while (Math.abs(sleevecapDelta(store)) > 2 && run < 100);
|
||||
|
||||
// Wrist
|
||||
let top = paths.sleevecap.bbox().topLeft.y;
|
||||
debug("Sleevecap height is ", units(Math.abs(top)));
|
||||
|
@ -200,6 +43,11 @@ var sleeve = {
|
|||
snippets.logo = new Snippet("logo", points.logo);
|
||||
macro("title", { at: points.centerBiceps, nr: 3, title: "sleeve" });
|
||||
macro("grainline", { from: points.centerWrist, to: points.centerBiceps });
|
||||
points.scaleboxAnchor = points.scalebox = points.centerBiceps.shiftFractionTowards(
|
||||
points.centerWrist,
|
||||
0.5
|
||||
);
|
||||
macro("scalebox", { at: points.scalebox });
|
||||
|
||||
points.sleeveTip = paths.sleevecap.shiftFractionAlong(0.5);
|
||||
points.frontNotch = paths.sleevecap.shiftAlong(
|
||||
|
|
176
packages/brian/src/sleevecap.js
Normal file
176
packages/brian/src/sleevecap.js
Normal file
|
@ -0,0 +1,176 @@
|
|||
import freesewing from "freesewing";
|
||||
|
||||
/** Calculates the differece between actual and optimal sleevecap length
|
||||
* Positive values mean sleevecap is longer than armhole
|
||||
*/
|
||||
function sleevecapDelta(store) {
|
||||
return store.get("sleevecapLength") - store.get("sleevecapTarget");
|
||||
}
|
||||
|
||||
function sleevecapAdjust(store) {
|
||||
let delta = sleevecapDelta(store);
|
||||
let factor = store.get("sleeveFactor");
|
||||
if (delta > 0) factor = factor * 0.98;
|
||||
else factor = factor * 1.02;
|
||||
store.set("sleeveFactor", factor);
|
||||
}
|
||||
|
||||
function draftSleevecap(part, run) {
|
||||
// prettier-ignore
|
||||
let {debug, units, store, measurements, options, Point, points, Path, paths} = part.shorthand();
|
||||
// Sleeve center axis
|
||||
points.centerBiceps = new Point(0, 0);
|
||||
points.centerCap = points.centerBiceps.shift(
|
||||
90,
|
||||
measurements.bicepsCircumference *
|
||||
(1 + options.bicepsEase) *
|
||||
options.armholeDepthFactor *
|
||||
store.get("sleeveFactor")
|
||||
);
|
||||
|
||||
// Left and right biceps points, limit impact of sleeveFactor to 25%
|
||||
let halfWidth =
|
||||
(measurements.bicepsCircumference * (1 + options.bicepsEase)) / 2;
|
||||
points.bicepsLeft = points.centerBiceps.shift(
|
||||
180,
|
||||
halfWidth * options.sleeveWidthGuarantee +
|
||||
halfWidth * (1 - options.sleeveWidthGuarantee) * store.get("sleeveFactor")
|
||||
);
|
||||
points.bicepsRight = points.bicepsLeft.flipX(points.centerBiceps);
|
||||
|
||||
// Pitch points
|
||||
let width = points.bicepsRight.x;
|
||||
let height = points.centerCap.y;
|
||||
points.backPitch = new Point(
|
||||
-1 * width * options.sleevecapBackFactorX,
|
||||
height * options.sleevecapBackFactorY
|
||||
);
|
||||
points.frontPitch = new Point(
|
||||
width * options.sleevecapFrontFactorX,
|
||||
height * options.sleevecapFrontFactorY
|
||||
);
|
||||
|
||||
// 4 sleevecap quadrants
|
||||
// Base points
|
||||
points.capQ1Base = points.frontPitch.shiftFractionTowards(
|
||||
points.bicepsRight,
|
||||
0.5
|
||||
);
|
||||
points.capQ2Base = points.frontPitch.shiftFractionTowards(
|
||||
points.centerCap,
|
||||
0.5
|
||||
);
|
||||
points.capQ3Base = points.backPitch.shiftFractionTowards(
|
||||
points.centerCap,
|
||||
0.5
|
||||
);
|
||||
points.capQ4Base = points.backPitch.shiftFractionTowards(
|
||||
points.bicepsLeft,
|
||||
0.5
|
||||
);
|
||||
// Offset points
|
||||
let baseOffset = measurements.bicepsCircumference * (1 + options.bicepsEase);
|
||||
points.capQ1 = points.capQ1Base.shift(
|
||||
points.bicepsRight.angle(points.frontPitch) + 90,
|
||||
baseOffset * options.sleevecapQ1Offset
|
||||
);
|
||||
points.capQ2 = points.capQ2Base.shift(
|
||||
points.centerCap.angle(points.frontPitch) + 90,
|
||||
baseOffset * options.sleevecapQ2Offset
|
||||
);
|
||||
points.capQ3 = points.capQ3Base.shift(
|
||||
points.centerCap.angle(points.backPitch) - 90,
|
||||
baseOffset * options.sleevecapQ3Offset
|
||||
);
|
||||
points.capQ4 = points.capQ4Base.shift(
|
||||
points.bicepsLeft.angle(points.backPitch) - 90,
|
||||
baseOffset * options.sleevecapQ4Offset
|
||||
);
|
||||
// Control points
|
||||
points.capQ1Cp1 = points.capQ1.shift(
|
||||
points.frontPitch.angle(points.bicepsRight),
|
||||
baseOffset * options.sleevecapQ1Spread1
|
||||
);
|
||||
points.capQ1Cp2 = points.capQ1.shift(
|
||||
points.frontPitch.angle(points.bicepsRight),
|
||||
baseOffset * options.sleevecapQ1Spread2 * -1
|
||||
);
|
||||
points.capQ2Cp1 = points.capQ2.shift(
|
||||
points.centerCap.angle(points.frontPitch),
|
||||
baseOffset * options.sleevecapQ2Spread1
|
||||
);
|
||||
points.capQ2Cp2 = points.capQ2.shift(
|
||||
points.centerCap.angle(points.frontPitch),
|
||||
baseOffset * options.sleevecapQ2Spread2 * -1
|
||||
);
|
||||
points.capQ3Cp1 = points.capQ3.shift(
|
||||
points.backPitch.angle(points.centerCap),
|
||||
baseOffset * options.sleevecapQ3Spread1
|
||||
);
|
||||
points.capQ3Cp2 = points.capQ3.shift(
|
||||
points.backPitch.angle(points.centerCap),
|
||||
baseOffset * options.sleevecapQ3Spread2 * -1
|
||||
);
|
||||
points.capQ4Cp1 = points.capQ4.shift(
|
||||
points.bicepsLeft.angle(points.backPitch),
|
||||
baseOffset * options.sleevecapQ4Spread1
|
||||
);
|
||||
points.capQ4Cp2 = points.capQ4.shift(
|
||||
points.bicepsLeft.angle(points.backPitch),
|
||||
baseOffset * options.sleevecapQ4Spread2 * -1
|
||||
);
|
||||
|
||||
// Sleevecap seamline
|
||||
paths.sleevecap = new Path()
|
||||
.move(points.bicepsRight)
|
||||
.curve(points.bicepsRight, points.capQ1Cp1, points.capQ1)
|
||||
.curve(points.capQ1Cp2, points.capQ2Cp1, points.capQ2)
|
||||
.curve(points.capQ2Cp2, points.capQ3Cp1, points.capQ3)
|
||||
.curve(points.capQ3Cp2, points.capQ4Cp1, points.capQ4)
|
||||
.curve(points.capQ4Cp2, points.bicepsLeft, points.bicepsLeft);
|
||||
|
||||
// Store sleevecap length
|
||||
store.set("sleevecapLength", paths.sleevecap.length());
|
||||
if (run === 1) {
|
||||
let armholeLength =
|
||||
store.get("frontArmholeLength") + store.get("backArmholeLength");
|
||||
let sleevecapEase = armholeLength * options.sleevecapEase;
|
||||
store.set("sleevecapEase", sleevecapEase);
|
||||
store.set("sleevecapTarget", armholeLength + sleevecapEase);
|
||||
debug("Sleevecap ease is", units(sleevecapEase));
|
||||
|
||||
// Uncomment this line to see all sleevecap iterations
|
||||
//paths[run] = paths.sleevecap;
|
||||
}
|
||||
}
|
||||
|
||||
var sleevecap = {
|
||||
draft: function(part) {
|
||||
// prettier-ignore
|
||||
let {debug, store, units, sa, measurements, options, Point, points, Path, paths, Snippet, snippets, final, paperless, macro} = part.shorthand();
|
||||
|
||||
store.set("sleeveFactor", 1);
|
||||
let run = 1;
|
||||
do {
|
||||
draftSleevecap(part, run);
|
||||
debug(
|
||||
`Sleevecap draft ${run}, sleevecap delta is ${units(
|
||||
sleevecapDelta(store)
|
||||
)}`
|
||||
);
|
||||
sleevecapAdjust(store);
|
||||
run++;
|
||||
} while (Math.abs(sleevecapDelta(store)) > 2 && run < 100);
|
||||
|
||||
// Paths
|
||||
paths.sleevecap.attr("class", "fabric");
|
||||
|
||||
// Anchor point for sampling
|
||||
points.gridAnchor = points.origin;
|
||||
points.test = new Point(10, 10);
|
||||
|
||||
return part;
|
||||
}
|
||||
};
|
||||
|
||||
export default sleevecap;
|
Loading…
Add table
Add a link
Reference in a new issue