1
0
Fork 0

tada: Initial commit

This commit is contained in:
Joost De Cock 2018-09-21 21:30:20 +02:00
parent 6ac152f413
commit 0e726bd55b
21 changed files with 7774 additions and 2 deletions

3
packages/hugo/.babelrc Normal file
View file

@ -0,0 +1,3 @@
{
"plugins": ["transform-object-rest-spread"]
}

View file

@ -0,0 +1,13 @@
# editorconfig.org
root = true
[*]
indent_size = 2
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

62
packages/hugo/.gitignore vendored Normal file
View file

@ -0,0 +1,62 @@
dist
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next

2
packages/hugo/.npmignore Normal file
View file

@ -0,0 +1,2 @@
src
.editorconfig

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018 freesewing Copyright (c) 2018 Joost De Cock
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,2 +1,27 @@
<p align="center">
<a title="Go to freesewing.org" href="https://freesewing.org/"><img src="https://freesewing.org/img/logo/black.svg" align="center" width="150px" alt="Freesewing logo"/></a>
</p>
<h4 align="center"><em>&nbsp;<a title="Go to freesewing.org" href="https://freesewing.org/">freesewing</a></em>
<br><sup>a library for made-to-measure sewing patterns</sup>
</h4>
<p align="center">
<a href="https://www.npmjs.com/package/@freesewing/hugo"><img src="https://badgen.net/npm/v/@freesewing/hugo" alt="Version"></a>
<a href="https://www.npmjs.com/package/@freesewing/hugo"><img src="https://badgen.net/npm/license/@freesewing/hugo" alt="License"></a>
<a href="https://gitter.im/freesewing/freesewing"><img src="https://badgen.net/badge/chat/on%20Gitter/cyan" alt="Chat on Gitter"></a>
<a href="https://freesewing.org/patrons/join"><img src="https://badgen.net/badge/become/a%20Patron/FF5B77" alt="Become a Patron"></a>
</p>
# hugo # hugo
A freesewing patter for a hooded sweatshirt
Hugo is a [freesewing](https://github.com/freesewing/freesewing) pattern
for a hooded sweater with raglan sleeves.
See [freesewing.org/patterns/hugo](https://freesewing.org/patterns/hugo)
for more info and examples.
## Install
```
npm i --save @freesewing/hugo
```

View file

@ -0,0 +1,57 @@
export default {
name: "hugo",
measurements: [
"bicepsCircumference",
"centerBackNeckToWaist",
"chestCircumference",
"naturalWaistToHip",
"neckCircumference",
"shoulderSlope",
"shoulderToShoulder",
"hipsCircumference",
"shoulderToWrist",
"wristCircumference",
"headCircumference",
],
options: {
// Constants
brianFitSleeve: false,
collarEase: 0.05,
collarFactor: 4.3,
armholeDepthFactor: 0.5,
shoulderEase: 0,
shoulderSlopeReduction: 0,
frontArmholeDeeper: 0,
sleevecapEase: 0,
sleevecapBackFactorX: 0.5,
sleevecapBackFactorY: 0.35,
sleevecapFrontFactorX: 0.5,
sleevecapFrontFactorY: 0.35,
sleevecapQ1Offset: 0.03,
sleevecapQ2Offset: 0,
sleevecapQ3Offset: 0,
sleevecapQ4Offset: 0.03,
sleevecapQ1Spread1: 0.05,
sleevecapQ1Spread2: 0.05,
sleevecapQ2Spread1: 0.05,
sleevecapQ2Spread2: 0.05,
sleevecapQ3Spread1: 0.05,
sleevecapQ3Spread2: 0.05,
sleevecapQ4Spread1: 0.05,
sleevecapQ4Spread2: 0.05,
sleeveWidthGuarantee: 1,
// Millimeter
// Percentages
acrossBackFactor: { pct: 97, min: 93, max: 100 },
backNeckCutout: { pct: 5, min: 2, max: 8 },
bicepsEase: { pct: 15, min: 0, max: 50 },
chestEase: { pct: 8, min: -4, max: 20 },
cuffEase: { pct: 20, min: 0, max: 200 },
lengthBonus: { pct: 10, min: 0, max: 20 },
sleeveLengthBonus: { pct: 0, min:-40, max: 10 },
ribbingStretchFactor: { pct: 5, min: 0, max: 10 },
ribbingWidth: { pct: 10, min: 4, max: 20 },
}
};

83
packages/hugo/index.html Normal file
View file

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hugo</title>
</head>
<body>
<div id="svg"></div>
<script type="text/javascript" src="node_modules/freesewing/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/plugin-bundle/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/brian/dist/browser.js"></script>
<script type="text/javascript" src="dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/plugin-theme/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/plugin-designer/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/plugin-debug/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/plugin-validate/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/plugin-i18n/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/models/dist/browser.js"></script>
<script type="text/javascript" src="node_modules/@freesewing/antman/dist/browser.js"></script>
<script>
var pattern = freesewing.patterns.hugo
.with(freesewing.plugins.debug)
.with(freesewing.plugins.theme)
.with(freesewing.plugins.designer)
.with(freesewing.plugins.validate)
.with(freesewing.plugins.i18n)
;
pattern.settings.locale = 'nl';
pattern.settings.paperless = true;
pattern.settings.measurements = freesewing.models.men.manSize40;
pattern.settings.margin = 2;
pattern.settings.sa = 10;
pattern.settings.units = 'metric';
pattern.settings.sample = {
type: 'models',
focus: 'manSize34',
models: freesewing.models.men
}
pattern.settings.measurements = {
bicepsCircumference: 335,
centerBackNeckToWaist: 480,
chestCircumference: 1080,
naturalWaistToHip: 120,
neckCircumference: 420,
shoulderSlope: 55,
shoulderToShoulder: 470,
hipsCircumference: 950,
shoulderToWrist: 700,
wristCircumference: 190,
headCircumference: 590
};
//pattern.options.panels = 13;
pattern.settings.onl = ['hoodSide'];
//pattern.sampleOption('panels');
//pattern.sampleMeasurement('shoulderSlope');
//pattern.sampleModels(freesewing.models.men, 'manSize34');
//pattern.sample();
pattern.draft();
document.getElementById("svg").innerHTML = pattern.render();
function pointHover(evt) {
var point = evt.target;
var id = point.id;
var cx = point.getAttribute('x');
var cy = point.getAttribute('y');
var name = point.getAttribute('data-point');
var part = point.getAttribute('data-part');
console.log(name+' ('+cx+', '+cy+') @ '+part);
var scale = 2;
cx = cx-scale*cx;
cy = cy-scale*cy;
point.setAttribute("transform", 'matrix('+scale+', 0, 0, '+scale+', '+cx+', '+cy+')');
pointUnhover(id);
}
function pointUnhover(id) {
setTimeout(function(){
document.getElementById(id).removeAttribute("transform", '');
}, 500);
}
</script>
</body>
</html>

6221
packages/hugo/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
{
"version": "0.1.0",
"name": "@freesewing/hugo",
"description": "Freesewing pattern for a hooded jumper with raglan sleeves",
"author": "Joost De Cock <joost@decock.org> (https://github.com/joostdecock)",
"license": "MIT",
"homepage": "https://github.com/freesewing/hugo#readme",
"repository": "github:freesewing/hugo",
"bugs": {
"url": "https://github.com/freesewing/hugo/issues"
},
"keywords": [
"freesewing",
"pattern",
"sewing",
"womenswear",
"jumper",
"hoodie"
],
"main": "dist/index.js",
"module": "dist/index.mjs",
"unpkg": "dist/browser.js",
"scripts": {
"precommit": "npm run pretty && lint-staged",
"patch": "npm version patch -m ':bookmark: v%s' && npm run build",
"minor": "npm version minor -m ':bookmark: v%s' && npm run build",
"major": "npm version major -m ':bookmark: v%s' && npm run build",
"test": "echo \"Error: no test specified\" && exit 1",
"clean": "rimraf dist",
"pretty": "npx prettier --write \"src/*.js\"",
"lint": "eslint --fix \"src/*.js\"",
"watch": "npx webpack --watch",
"browserbuild": "rollup -c rollup.js -o dist/browser.js -f iife -m true -n freesewing_patterns_hugo --footer 'freesewing.patterns.hugo = freesewing_patterns_hugo;'",
"nodebuild": "rollup -c rollup.js -o dist/index.js -f cjs -m true",
"modulebuild": "rollup -c rollup.js -o dist/index.mjs -f es -m true",
"build": "npm run clean && npm run browserbuild && npm run nodebuild && npm run modulebuild"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,json}": [
"prettier --write",
"git add"
]
},
"dependencies": {
"@freesewing/brian": "^0.11",
"@freesewing/plugin-bundle": "^0.3",
"freesewing": "^0.17"
},
"devDependencies": {
"@babel/core": "7.0.0-beta.56",
"@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.56",
"@babel/preset-env": "7.0.0-beta.56",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.6",
"babel-loader": "^8.0.0-beta.4",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"@freesewing/antman": "0.2.0",
"@freesewing/models": "0.6.0",
"@freesewing/plugin-debug": "0.1.0",
"@freesewing/plugin-designer": "0.7.3",
"@freesewing/plugin-theme": "0.13.2",
"@freesewing/plugin-validate": "0.2.0",
"@freesewing/plugin-i18n": "0.0.1",
"eslint": "5.3.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-prettier": "^2.6.2",
"husky": "^0.14.3",
"lint-staged": "^7.2.0",
"prettier": "1.14.0",
"rimraf": "^2.6.2",
"rollup-plugin-babel": "^3.0.7",
"rollup-plugin-commonjs": "9.1.3",
"rollup-plugin-filesize": "^4.0.1",
"rollup-plugin-json": "^3.0.0",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-terser": "^1.0.1"
},
"files": [
"dist/*",
"README.md",
"package-lock.json",
"package.json"
]
}

33
packages/hugo/rollup.js Normal file
View file

@ -0,0 +1,33 @@
import { terser } from "rollup-plugin-terser";
import babel from "rollup-plugin-babel";
import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import json from "rollup-plugin-json";
import path from "path";
import { name, version, description, author, license } from "./package.json";
export default {
input: "src/index.js",
plugins: [
resolve({
browser: true
}),
json(),
commonjs(),
babel({
exclude: "node_modules/**"
}),
terser({
output: {
preamble: `/**\n * ${name} | v${version}\n * ${description}\n * (c) ${new Date().getFullYear()} ${author}\n * @license ${license}\n */`
}
})
],
external: ["freesewing", "@freesewing/plugin-bundle"],
output: {
globals: {
freesewing: "freesewing",
"@freesewing/plugin-bundle": "freesewing.plugins.bundle"
}
}
};

116
packages/hugo/src/back.js Normal file
View file

@ -0,0 +1,116 @@
var back = {
draft: function(part) {
// Remove clutter
let seam = part.paths.seam;
part.paths = {};
part.paths.seam = seam;
// prettier-ignore
let {utils, store, sa, Point, points, Path, paths, Snippet, snippets, options, measurements, complete, paperless, macro, debug} = part.shorthand();
// Hem is more descripting than hips in this case
points.cbHem = points.cbHips;
points.hem = points.hips;
// Ribbing
points.cbRibbing = points.cbHem.shift(90, store.get("ribbing"));
points.ribbing = points.hem.shift(90, store.get("ribbing"));
// Raglan tip
let neckOpening = new Path()
.move(points.cbNeck)
.curve(points.cbNeck, points.neckCp2, points.neck);
points.raglanTipBack = neckOpening.shiftFractionAlong(0.7);
let neckOpeningParts = neckOpening.split(points.raglanTipBack);
// Paths
paths.saBase = new Path()
.move(points.cbRibbing)
.line(points.ribbing)
.line(points.armhole)
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.line(points.raglanTipBack)
.join(neckOpeningParts[0].reverse());
paths.seam = paths.saBase
.clone()
.close()
.attr("class", "fabric");
paths.saBase.render = false;
// Store neck opening path
store.set("neckOpeningPartBack", neckOpeningParts[1]);
store.set("neckOpeningAnchorBack", points.neck);
store.set("neckOpeningLenBack", neckOpening.length());
store.set("neckCutoutBack", points.cbNeck.y);
// Complete pattern?
if (complete) {
macro("cutonfold", {
from: points.cbNeck,
to: points.cbRibbing,
grainline: true
});
points.title = new Point(points.armhole.x / 2, points.armhole.y);
macro("title", { at: points.title, nr: 2, title: "back" });
store.set(
"notchBack",
points.raglanTipBack.dist(points.armholeHollow) / 2
);
points.sleeveNotch = points.raglanTipBack.shiftTowards(
points.armholeHollow,
store.get("notchBack")
);
snippets.sleeveNotch = new Snippet("bnotch", points.sleeveNotch);
store.set(
"backRaglanTipToNotch",
points.raglanTipBack.dist(points.sleeveNotch)
);
points.logo = points.title.shift(-90, 70);
snippets.logo = new Snippet("logo", points.logo);
if (sa) {
paths.sa = paths.saBase
.offset(sa)
.line(points.cbNeck)
.attr("class", "fabric sa");
paths.sa.move(points.cbRibbing).line(paths.sa.start());
}
}
// Paperless?
if (paperless) {
macro("vd", {
from: points.cbRibbing,
to: points.cbNeck,
x: points.cbNeck.x - 15
});
macro("vd", {
from: points.cbRibbing,
to: points.raglanTipBack,
x: points.cbNeck.x - 30
});
macro("vd", {
from: points.ribbing,
to: points.armhole,
x: points.ribbing.x + 15 + sa
});
macro("hd", {
from: points.cbNeck,
to: points.raglanTipBack,
y: points.raglanTipBack.y - 15 - sa
});
macro("hd", {
from: points.raglanTipBack,
to: points.armhole,
y: points.raglanTipBack.y - 15 - sa
});
macro("hd", {
from: points.cbRibbing,
to: points.ribbing,
y: points.cbRibbing.y + 15 + sa
});
}
return part;
}
};
export default back;

63
packages/hugo/src/cuff.js Normal file
View file

@ -0,0 +1,63 @@
var cuff = {
draft: function(part) {
// prettier-ignore
let {measurements, options, sa, Point, points, Path, paths, complete, paperless, macro, units} = part.shorthand();
let width =
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip) *
options.ribbingWidth *
2;
let length =
measurements.wristCircumference *
(1 + options.cuffEase) *
(1 - options.ribbingStretchFactor);
points.topLeft = new Point(0, 0);
points.bottomLeft = new Point(0, width);
points.topRight = new Point(length, 0);
points.bottomRight = new Point(length, width);
paths.seam = new Path()
.move(points.topLeft)
.line(points.bottomLeft)
.line(points.bottomRight)
.line(points.topRight)
.line(points.topLeft)
.close()
.attr("class", "fabric");
// Complete pattern?
if (complete) {
if (sa) {
paths.sa = paths.seam.offset(sa);
}
points.title = points.bottomLeft.shiftFractionTowards(
points.topRight,
0.5
);
macro("title", { at: points.title, nr: 9, title: "cuff" });
macro("grainline", {
from: points.bottomLeft.shift(0, 20),
to: points.topLeft.shift(0, 20)
});
}
// Paperless?
if (paperless) {
macro("vd", {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
macro("hd", {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomRight.y + sa + 15
});
}
return part;
}
};
export default cuff;

173
packages/hugo/src/front.js Normal file
View file

@ -0,0 +1,173 @@
var front = {
draft: function(part) {
// Remove clutter
let seam = part.paths.seam;
part.paths = {};
part.paths.seam = seam;
// prettier-ignore
let {utils, store, sa, Point, points, Path, paths, Snippet, snippets, options, measurements, complete, paperless, macro, debug} = part.shorthand();
// Absolute values for percentages
store.set(
"lengthBonus",
options.lengthBonus *
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip)
);
store.set(
"ribbing",
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip) *
options.ribbingWidth
);
// Hem is more descripting than hips in this case
points.cfHem = points.cfHips;
points.hem = points.hips;
// Ribbing
points.cfRibbing = points.cfHem.shift(90, store.get("ribbing"));
points.ribbing = points.hem.shift(90, store.get("ribbing"));
// Raglan tip
let neckOpening = new Path()
.move(points.cfNeck)
.curve(points.cfNeck, points.neckCp2, points.neck);
points.raglanTipFront = neckOpening.shiftFractionAlong(0.8);
let neckOpeningParts = neckOpening.split(points.raglanTipFront);
// Pocket
points.pocketHem = points.cfRibbing.shiftFractionTowards(
points.ribbing,
0.6
);
points.pocketCf = points.cfWaist.shift(90, store.get("ribbing"));
points.pocketTop = new Point(points.pocketHem.x, points.pocketCf.y);
points.pocketTip = points.pocketHem
.shift(90, points.pocketHem.x / 3)
.rotate(-30, points.pocketHem);
points.pocketTopCp = points.pocketTop.shift(-90, points.pocketHem.x / 2);
// Paths
paths.saBase = new Path()
.move(points.cfRibbing)
.line(points.ribbing)
.line(points.armhole)
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.line(points.raglanTipFront)
.join(neckOpeningParts[0].reverse());
paths.seam = paths.saBase
.clone()
.close()
.attr("class", "fabric");
paths.saBase.render = false;
paths.pocket = new Path()
.move(points.pocketHem)
.line(points.pocketTip)
.curve(points.pocketTip, points.pocketTopCp, points.pocketTop)
.line(points.pocketCf)
.attr("class", "fabric help");
// Store shoulder seam length, neck opening path, shoulder slope and raglan length
store.set("shoulderLength", points.neck.dist(points.shoulder));
store.set("neckOpeningPartFront", neckOpeningParts[1]);
store.set("neckOpeningAnchorFront", points.neck);
store.set("shoulderSlopeDeltaY", points.neck.dy(points.shoulder));
store.set(
"raglen",
new Path()
.move(points.raglanTipFront)
.line(points.armholeHollow)
.curve(points.armholeHollowCp1, points.armholeCp2, points.armhole)
.length()
);
store.set("neckOpeningLenFront", neckOpening.length());
store.set("neckCutoutFront", points.cfNeck.y);
// Complete pattern?
if (complete) {
macro("cutonfold", {
from: points.cfNeck,
to: points.cfRibbing,
grainline: true
});
points.title = new Point(points.armhole.x / 2, points.armhole.y);
macro("title", { at: points.title, nr: 1, title: "front" });
store.set(
"notchFront",
points.raglanTipFront.dist(points.armholeHollow) / 2
);
points.sleeveNotch = points.raglanTipFront.shiftTowards(
points.armholeHollow,
store.get("notchFront")
);
snippets.sleeveNotch = new Snippet("notch", points.sleeveNotch);
store.set(
"frontRaglanTipToNotch",
points.raglanTipFront.dist(points.sleeveNotch)
);
points.logo = points.title.shift(-90, 70);
snippets.logo = new Snippet("logo", points.logo);
if (sa) {
paths.sa = paths.saBase
.offset(sa)
.line(points.cfNeck)
.attr("class", "fabric sa");
paths.sa.move(points.cfRibbing).line(paths.sa.start());
}
}
// Paperless?
if (paperless) {
macro("vd", {
from: points.cfRibbing,
to: points.cfNeck,
x: points.cfNeck.x - 15
});
macro("vd", {
from: points.cfRibbing,
to: points.raglanTipFront,
x: points.cfNeck.x - 30
});
macro("vd", {
from: points.ribbing,
to: points.armhole,
x: points.ribbing.x + 15 + sa
});
macro("hd", {
from: points.cfNeck,
to: points.raglanTipFront,
y: points.raglanTipFront.y - 15 - sa
});
macro("hd", {
from: points.raglanTipFront,
to: points.armhole,
y: points.raglanTipFront.y - 15 - sa
});
macro("hd", {
from: points.cfRibbing,
to: points.pocketTop,
y: points.cfRibbing.y + 15 + sa
});
macro("hd", {
from: points.cfRibbing,
to: points.pocketTip,
y: points.cfRibbing.y + 30 + sa
});
macro("hd", {
from: points.cfRibbing,
to: points.ribbing,
y: points.cfRibbing.y + 45 + sa
});
macro("vd", {
from: points.pocketHem,
to: points.pocketTop,
x: points.pocketTip.x + 15
});
}
return part;
}
};
export default front;

View file

@ -0,0 +1,68 @@
var hoodCenter = {
draft: function(part) {
// prettier-ignore
let {store, sa, Point, points, Path, paths, complete, paperless, macro, units} = part.shorthand();
let width = store.get("hoodCenterWidth");
points.topLeft = new Point(0, 0);
points.bottomLeft = new Point(0, width);
points.topMidLeft = new Point(width, 0);
points.bottomMidLeft = new Point(width, width);
points.topMidRight = new Point(width * 1.5, 0);
points.bottomMidRight = new Point(width * 1.5, width);
points.topRight = new Point(width * 2.5, 0);
points.bottomRight = new Point(width * 2.5, width);
paths.seam = new Path()
.move(points.topMidLeft)
.line(points.topLeft)
.line(points.bottomLeft)
.line(points.bottomMidLeft)
.move(points.bottomMidRight)
.line(points.bottomRight)
.line(points.topRight)
.line(points.topMidRight)
.attr("class", "fabric");
paths.hint = new Path()
.move(points.topMidLeft)
.line(points.topMidRight)
.move(points.bottomMidLeft)
.line(points.bottomMidRight)
.attr("class", "fabric dashed");
// Complete pattern?
if (complete) {
if (sa) {
paths.sa = paths.seam.offset(sa);
}
points.title = points.bottomLeft.shiftFractionTowards(
points.topRight,
0.5
);
macro("title", { at: points.title, nr: 7, title: "hoodCenter" });
macro("grainline", {
from: points.topLeft.shift(-90, width / 2),
to: points.topRight.shift(-90, width / 2)
});
}
// Paperless?
if (paperless) {
macro("vd", {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
macro("hd", {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomRight.y + sa + 15,
text: units(store.get("hoodCenterLength"))
});
}
return part;
}
};
export default hoodCenter;

View file

@ -0,0 +1,152 @@
var hoodSide = {
draft: function(part) {
// prettier-ignore
let {utils, store, sa, Point, points, Path, paths, Snippet, snippets, options, measurements, complete, paperless, macro, debug} = part.shorthand();
let neckOpening =
store.get("neckOpeningLenFront") + store.get("neckOpeningLenBack");
let hoodOpening = measurements.headCircumference;
let neckCutoutDelta =
store.get("neckCutoutFront") - store.get("neckCutoutBack");
store.set("hoodCenterWidth", measurements.headCircumference / 10);
let halfCenterPanel = store.get("hoodCenterWidth") / 2;
points.topLeft = new Point(0, 0);
points.topRight = new Point(neckOpening, 0);
points.neckRight = new Point(
neckOpening,
(hoodOpening - halfCenterPanel) / 2
);
points.neckLeft = new Point(0, points.neckRight.y);
points.frontLeft = points.neckLeft.shift(-90, neckCutoutDelta);
points.frontEdge = points.neckRight.shift(-90, neckCutoutDelta);
points.neckEdge = points.neckLeft.shift(0, halfCenterPanel);
points.neckEdgeCp2 = new Point(points.neckRight.x / 2, points.neckEdge.y);
points.frontEdgeCp1 = new Point(points.neckEdgeCp2.x, points.frontEdge.y);
points.shoulderNotch = new Path()
.move(points.neckEdge)
.curve(points.neckEdgeCp2, points.frontEdgeCp1, points.frontEdge)
.shiftAlong(store.get("neckOpeningLenBack") - halfCenterPanel);
points.hoodTop = new Point(points.shoulderNotch.x, points.topLeft.y);
points.hoodTopCp2 = points.hoodTop.shift(180, points.neckEdge.y * 0.7);
points.hoodRim = new Point(points.frontEdge.x, points.neckRight.y * 0.2);
points.hoodTopCp1 = points.hoodTop.shift(
0,
points.hoodTop.dx(points.hoodRim) / 2
);
points.frontEdgeCp2 = points.frontEdge.shift(90, halfCenterPanel);
points._tmp1 = new Path()
.move(points.hoodRim)
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
.shiftAlong(2)
.rotate(90, points.hoodRim);
points.hoodRimCp = points.hoodRim.shiftTowards(
points._tmp1,
points.neckRight.y / 3
);
points.neckRoll = points.neckRight.shift(180, halfCenterPanel);
points._tmp2 = new Path()
.move(points.neckRoll)
.curve(points.neckRoll, points.hoodRimCp, points.hoodRim)
.shiftAlong(2);
points.neckRollCp2 = points.neckRoll.shiftTowards(
points._tmp2,
halfCenterPanel
);
points.neckRollCp1 = points.neckRollCp2.rotate(180, points.neckRoll);
paths.seam = new Path()
.move(points.frontEdge)
.curve(points.frontEdgeCp2, points.neckRollCp1, points.neckRoll)
.curve(points.neckRollCp2, points.hoodRimCp, points.hoodRim)
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
.curve(points.hoodTopCp2, points.neckEdge, points.neckEdge)
.curve(points.neckEdgeCp2, points.frontEdgeCp1, points.frontEdge)
.close()
.attr("class", "fabric");
// Store length of center seam
store.set(
"hoodCenterLength",
new Path()
.move(points.hoodRim)
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
.curve(points.hoodTopCp2, points.neckEdge, points.neckEdge)
.length()
);
// Complete pattern?
if (complete) {
if (sa) {
// Reversing this curve sidesteps a bezierjs edge case
paths.sa = paths.seam.reverse().offset(sa * -1);
}
points.title = points.hoodTop.shift(-90, 50);
macro("title", { at: points.title, nr: 6, title: "hoodSide" });
points.logo = points.title.shift(-90, 60);
snippets.logo = new Snippet("logo", points.logo);
macro("grainline", {
from: points.shoulderNotch,
to: points.hoodTop
});
}
// Paperless?
if (paperless) {
let neckSeam = new Path()
.move(points.neckEdge)
.curve(points.neckEdgeCp2, points.frontEdgeCp1, points.frontEdge)
.split(points.shoulderNotch);
let centralSeam = new Path()
.move(points.hoodRim)
.curve(points.hoodRim, points.hoodTopCp1, points.hoodTop)
.curve(points.hoodTopCp2, points.neckEdge, points.neckEdge)
.reverse();
let openingSeam = new Path()
.move(points.neckRoll)
.curve(points.neckRollCp2, points.hoodRimCp, points.hoodRim);
macro("pd", {
path: neckSeam[0],
d: sa + 15
});
macro("pd", {
path: neckSeam[1],
d: sa + 15
});
macro("pd", {
path: centralSeam,
d: sa * -1 - 15
});
macro("hd", {
from: points.neckEdge,
to: points.frontEdge,
y: points.frontEdge.y + sa + 30
});
macro("hd", {
from: centralSeam.edge("left"),
to: points.frontEdge,
y: points.frontEdge.y + sa + 45
});
let openingEdge = openingSeam.edge("left");
macro("hd", {
from: openingEdge,
to: points.frontEdge,
y: openingEdge.y
});
macro("vd", {
from: points.frontEdge,
to: points.hoodRim,
x: points.hoodRim.x + sa + 15
});
macro("vd", {
from: points.frontEdge,
to: points.hoodTop,
x: points.hoodRim.x + sa + 30
});
}
return part;
}
};
export default hoodSide;

147
packages/hugo/src/index.js Normal file
View file

@ -0,0 +1,147 @@
import freesewing from "freesewing";
import brian from "@freesewing/brian";
import pluginBundle from "@freesewing/plugin-bundle";
import config from "../config/config";
import { version } from "../package.json";
import back from "./back";
import front from "./front";
import sleeve from "./sleeve";
import pocket from "./pocket";
import pocketFacing from "./pocketfacing";
import hoodSide from "./hoodside";
import hoodCenter from "./hoodcenter";
import waistband from "./waistband";
import cuff from "./cuff";
var pattern = new freesewing.Pattern({ version: version, ...config }).with(
pluginBundle
);
pattern.draft = function() {
// base from Brian
this.parts.base = this.draftBase(new pattern.Part());
if (this.needs(["front", "sleeve", "pocket", "pocketFacing"])) {
this.parts.frontBase = this.draftFrontBase(
new pattern.Part().copy(this.parts.base)
);
this.parts.front = this.draftFront(
new pattern.Part().copy(this.parts.frontBase)
);
}
if (this.needs(["back", "sleeve"])) {
this.parts.backBase = this.draftBackBase(
new pattern.Part().copy(this.parts.base)
);
this.parts.back = this.draftBack(
new pattern.Part().copy(this.parts.backBase)
);
}
if (this.needs(["sleeve"])) {
let sleevecap = freesewing.patterns.brian.draftSleevecap(
new pattern.Part()
);
this.parts.sleeveBase = this.draftSleeveBase(
new pattern.Part().copy(sleevecap)
);
this.parts.sleeve = this.draftSleeve(
new pattern.Part().copy(this.parts.sleeveBase)
);
}
if (this.needs(["pocket"])) {
this.parts.pocket = this.draftPocket(
new pattern.Part().copy(this.parts.front)
);
}
if (this.needs(["pocketFacing"])) {
this.parts.pocketFacing = this.draftPocketFacing(
new pattern.Part().copy(this.parts.pocket)
);
}
if (this.needs(["hoodSide", "hoodCenter"])) {
this.parts.hoodSide = this.draftHoodSide(new pattern.Part());
}
if (this.needs(["hoodCenter"])) {
this.parts.hoodCenter = this.draftHoodCenter(new pattern.Part());
}
if (this.needs(["waistband"])) {
this.parts.waistband = this.draftWaistband(new pattern.Part());
}
if (this.needs(["cuff"])) {
this.parts.cuff = this.draftCuff(new pattern.Part());
}
// Don't render these unless specifically requested
if (!this.needs("base", true)) this.parts.base.render = false;
if (!this.needs("frontBase", true)) this.parts.frontBase.render = false;
if (!this.needs("backBase", true)) this.parts.backBase.render = false;
if (!this.needs("sleeveBase", true)) this.parts.sleeveBase.render = false;
return pattern;
};
pattern.draftBase = function(part) {
let complete = this.settings.complete;
let paperless = this.settings.paperless;
this.settings.complete = false;
this.settings.paperless = false;
let brianBase = freesewing.patterns.brian.draftBase(part);
this.settings.complete = complete;
this.settings.paperless = paperless;
return brianBase;
};
pattern.draftFrontBase = function(part) {
let complete = this.settings.complete;
let paperless = this.settings.paperless;
this.settings.complete = false;
this.settings.paperless = false;
let brianFront = freesewing.patterns.brian.draftFront(part);
this.settings.complete = complete;
this.settings.paperless = paperless;
return brianFront;
};
pattern.draftBackBase = function(part) {
let complete = this.settings.complete;
let paperless = this.settings.paperless;
this.settings.complete = false;
this.settings.paperless = false;
let brianBack = freesewing.patterns.brian.draftBack(part);
this.settings.complete = complete;
this.settings.paperless = paperless;
return brianBack;
};
pattern.draftSleeveBase = function(part) {
let complete = this.settings.complete;
let paperless = this.settings.paperless;
this.settings.complete = false;
this.settings.paperless = false;
let brianSleeve = freesewing.patterns.brian.draftSleeve(part);
this.settings.complete = complete;
this.settings.paperless = paperless;
return brianSleeve;
};
pattern.draftFront = part => front.draft(part);
pattern.draftBack = part => back.draft(part);
pattern.draftSleeve = part => sleeve.draft(part);
pattern.draftPocket = part => pocket.draft(part);
pattern.draftPocketFacing = part => pocketFacing.draft(part);
pattern.draftHoodSide = part => hoodSide.draft(part);
pattern.draftHoodCenter = part => hoodCenter.draft(part);
pattern.draftWaistband = part => waistband.draft(part);
pattern.draftCuff = part => cuff.draft(part);
export default pattern;

View file

@ -0,0 +1,80 @@
var pocket = {
draft: function(part) {
// Remove clutter
let pocket = part.paths.pocket;
part.paths = {};
part.snippets = {};
// prettier-ignore
let {utils, store, sa, Point, points, Path, paths, Snippet, snippets, options, measurements, complete, paperless, macro, debug} = part.shorthand();
paths.seam = pocket
.line(points.cfRibbing)
.line(points.pocketHem)
.attr("class", "fabric", true);
store.set("facingWidth", points.pocketHem.dist(points.pocketTip) / 2);
let facing = new Path()
.move(points.pocketTip)
.curve(points.pocketTip, points.pocketTopCp, points.pocketTop)
.offset(store.get("facingWidth") * -1);
points._tmp = facing.shiftAlong(2);
points.facingEnd = utils.beamsIntersect(
points._tmp,
facing.start(),
points.pocketHem,
points.pocketTip
);
paths.facing = new Path()
.move(points.facingEnd)
.line(facing.start())
.join(facing)
.attr("class", " fabric help");
// Complete pattern?
if (complete) {
macro("grainline", {
from: points.cfRibbing.shift(0, 15),
to: points.pocketCf.shift(0, 15)
});
points.title = points.cfRibbing.shiftFractionTowards(
points.pocketTop,
0.5
);
macro("title", { at: points.title, nr: 4, title: "pocket" });
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
}
}
// Paperless?
if (paperless) {
macro("hd", {
from: points.cfRibbing,
to: points.pocketTop,
y: points.cfRibbing.y + 15 + sa
});
macro("hd", {
from: points.cfRibbing,
to: points.pocketTip,
y: points.cfRibbing.y + 30 + sa
});
macro("vd", {
from: points.pocketHem,
to: points.pocketTip,
x: points.pocketTip.x + 15 + sa
});
macro("vd", {
from: points.pocketHem,
to: points.pocketTop,
x: points.cfRibbing.x - 15 - sa
});
}
return part;
}
};
export default pocket;

View file

@ -0,0 +1,51 @@
var pocketFacing = {
draft: function(part) {
// Remove clutter
let facing = part.paths.facing;
part.paths = {};
// prettier-ignore
let {sa, Point, points, Path, paths, Snippet, snippets, complete, paperless, macro, utils, store} = part.shorthand();
paths.seam = facing
.line(points.pocketTop)
.curve(points.pocketTopCp, points.pocketTip, points.pocketTip)
.line(points.facingEnd)
.close()
.attr("class", "fabric", true);
points.saStart = points.pocketTop.shift(180, store.get("facingWidth"));
// Complete pattern?
if (complete) {
points.title = points.pocketTopCp.clone();
macro("title", { at: points.title, nr: 5, title: "pocketFacing" });
if (sa) {
paths.sa = new Path()
.move(points.saStart)
.line(points.pocketTop)
.curve(points.pocketTopCp, points.pocketTip, points.pocketTip)
.line(points.facingEnd)
.offset(sa * -1)
.attr("class", "fabric sa");
paths.sa
.line(points.facingEnd)
.move(points.saStart)
.line(paths.sa.start());
}
}
// Paperless?
if (paperless) {
macro("hd", {
from: points.saStart,
to: points.pocketTop,
y: points.saStart.y - 15 - sa
});
}
return part;
}
};
export default pocketFacing;

258
packages/hugo/src/sleeve.js Normal file
View file

@ -0,0 +1,258 @@
var sleeve = {
draft: function(part) {
// prettier-ignore
let {utils, store, sa, Point, points, Path, paths, Snippet, snippets, options, measurements, complete, paperless, macro, debug} = part.shorthand();
// Top of raglan sleeve
points.raglanTop = new Point(
0,
points.sleeveTip.y - store.get("shoulderLength")
);
// Move and rotate front neck opening part
let anchor = store.get("neckOpeningAnchorFront");
let neckOpeningFront = store.get("neckOpeningPartFront");
neckOpeningFront = neckOpeningFront.translate(
anchor.dx(points.raglanTop),
anchor.dy(points.raglanTop)
);
let cp2 = neckOpeningFront.ops[1].cp1;
let cp1 = neckOpeningFront.ops[1].cp2;
let to = neckOpeningFront.ops[0].to;
let angle = points.raglanTop.angle(cp1);
points.raglanTopCp2 = cp1.rotate(180 - angle, points.raglanTop);
points.raglanTipFrontCp1 = cp2.rotate(180 - angle, points.raglanTop);
points.raglanTipFront = to.rotate(180 - angle, points.raglanTop);
// Move and rotate back neck opening part
anchor = store.get("neckOpeningAnchorBack");
let neckOpeningBack = store.get("neckOpeningPartBack");
neckOpeningBack = neckOpeningBack.translate(
anchor.dx(points.raglanTop),
anchor.dy(points.raglanTop)
);
cp2 = neckOpeningBack.ops[1].cp1;
cp1 = neckOpeningBack.ops[1].cp2;
to = neckOpeningBack.ops[0].to;
points.raglanTopCp1 = cp1.flipX(); //rotate(180 - angle, points.raglanTop);
points.raglanTipBackCp2 = cp2.flipX(); //rotate(180 - angle, points.raglanTop);
points.raglanTipBack = to.flipX(); //rotate(180 - angle, points.raglanTop);
angle = points.raglanTop.angle(points.raglanTopCp1);
points.raglanTopCp1 = points.raglanTopCp1.rotate(
360 - angle,
points.raglanTop
);
points.raglanTipBackCp2 = points.raglanTipBackCp2.rotate(
360 - angle,
points.raglanTop
);
points.raglanTipBack = points.raglanTipBack.rotate(
360 - angle,
points.raglanTop
);
let ragDiff = 0;
let runs = 0;
do {
// Curve raglan seam to accomodate shoulder slope
points.raglanMidFront = points.raglanTipFront.shiftFractionTowards(
points.capQ4Base,
0.5
);
points.raglanMidBack = utils.beamsIntersect(
points.raglanTipBack,
points.capQ1Base,
points.raglanMidFront,
points.raglanMidFront.shift(0, 100)
);
points.raglanFrontCp1 = points.raglanTipFront.shiftFractionTowards(
points.capQ4Base,
0.25
);
points.raglanFrontCp2 = points.raglanTipFront.shiftFractionTowards(
points.capQ4Base,
0.75
);
points.raglanBackCp1 = points.raglanTipBack.shiftFractionTowards(
points.capQ1Base,
0.8
);
points.raglanBackCp2 = points.raglanTipBack.shiftFractionTowards(
points.capQ1Base,
0.3
);
let slope = store.get("shoulderSlopeDeltaY");
let angleFront = points.raglanTipFront.angle(points.capQ4Base);
let angleBack = points.raglanTipBack.angle(points.capQ1Base);
points.slopeFront = points.raglanMidFront.shift(
angleFront + 90,
slope / 2
);
points.slopeBack = points.raglanMidBack.shift(angleBack - 90, slope / 2);
points.slopeFrontCp1 = points.raglanFrontCp1.shift(
angleFront + 90,
slope / 2
);
points.slopeFrontCp2 = points.raglanFrontCp2.shift(
angleFront + 90,
slope / 2
);
points.slopeBackCp1 = points.raglanBackCp1.shift(
angleBack - 90,
slope / 2
);
points.slopeBackCp2 = points.raglanBackCp2.shift(
angleBack - 90,
slope / 2
);
points.capQ4BaseCp = utils.beamsIntersect(
points.slopeFrontCp2,
points.capQ4Base,
points.bicepsLeft,
points.capQ4Cp2
);
points.capQ1BaseCp = utils.beamsIntersect(
points.slopeBackCp1,
points.capQ1Base,
points.bicepsRight,
points.capQ1Cp2
);
// Now make sure the length matches the front raglan seam
let raglen = new Path()
.move(points.raglanTipBack)
.curve(points.raglanTipBackCp2, points.raglanTopCp1, points.raglanTop)
.curve(
points.raglanTopCp2,
points.raglanTipFrontCp1,
points.raglanTipFront
)
.curve(points.raglanTipFront, points.slopeFrontCp1, points.slopeFront)
.curve(points.slopeFrontCp2, points.capQ4Base, points.capQ4Base)
.length();
ragDiff = store.get("raglen") - raglen;
let tipPoints = [
"raglanTipFront",
"raglanTipFrontCp1",
"raglanTopCp2",
"raglanTop",
"raglanTopCp1",
"raglanTipBackCp2",
"raglanTipBack"
];
for (let pid of tipPoints) points[pid] = points[pid].shift(90, ragDiff);
// Fix sleeve length
let lenTotal =
store.get("shoulderLength") +
measurements.shoulderToWrist * (1 + options.sleeveLengthBonus) -
options.ribbingWidth;
let lenDelta = points.raglanTop.dist(points.centerWrist) - lenTotal;
let wristPoints = ["wristLeft", "centerWrist", "wristRight"];
for (let pid of wristPoints)
points[pid] = points[pid].shift(90, lenDelta);
runs++;
} while (Math.abs(ragDiff) > 5 && runs < 10);
paths.seam = new Path()
.move(points.raglanTipBack)
.curve(points.raglanTipBackCp2, points.raglanTopCp1, points.raglanTop)
.curve(
points.raglanTopCp2,
points.raglanTipFrontCp1,
points.raglanTipFront
)
.curve(points.raglanTipFront, points.slopeFrontCp1, points.slopeFront)
.curve(points.slopeFrontCp2, points.capQ4Cp2, points.bicepsLeft)
.line(points.wristLeft)
.line(points.wristRight)
.line(points.bicepsRight)
.curve(points.capQ1Cp1, points.slopeBackCp1, points.slopeBack)
.curve(points.slopeBackCp2, points.raglanTipBack, points.raglanTipBack)
.close()
.attr("class", "fabric");
// Complete pattern?
if (complete) {
macro("grainline", {
from: points.centerWrist,
to: points.raglanTop
});
//points.title = new Point(points.armhole.x/2, points.armhole.y);
macro("title", { at: points.gridAnchor, nr: 3, title: "sleeve" });
//points.sleeveNotch = points.raglanTipFront.shiftFractionTowards(points.armholeHollow, 0.5);
//snippets.sleeveNotch = new Snippet("notch", points.sleeveNotch);
//store.set('frontRaglanTipToNotch', points.raglanTipFront.dist(points.sleeveNotch));
points.logo = points.gridAnchor.shift(-90, 70);
snippets.logo = new Snippet("logo", points.logo);
points.scalebox = points.logo.shift(-90, 70);
macro("scalebox", { at: points.scalebox });
points.frontNotch = new Path()
.move(points.raglanTipFront)
.curve(points.raglanTipFront, points.slopeFrontCp1, points.slopeFront)
.curve(points.slopeFrontCp2, points.capQ4Cp2, points.bicepsLeft)
.shiftAlong(store.get("notchFront"));
snippets.frontNotch = new Snippet("notch", points.frontNotch);
points.backNotch = new Path()
.move(points.raglanTipBack)
.curve(points.raglanTipBack, points.slopeBackCp2, points.slopeBack)
.curve(points.slopeBackCp1, points.capQ1Cp1, points.bicepsRight)
.shiftAlong(store.get("notchBack"));
snippets.backNotch = new Snippet("bnotch", points.backNotch);
if (sa) {
paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
}
}
// Paperless?
if (paperless) {
macro("vd", {
from: points.wristLeft,
to: points.bicepsLeft,
x: points.bicepsLeft.x - 15 - sa
});
macro("vd", {
from: points.bicepsLeft,
to: points.raglanTipFront,
x: points.bicepsLeft.x - 15 - sa
});
macro("vd", {
from: points.bicepsRight,
to: points.raglanTop,
x: points.bicepsRight.x + 15 + sa
});
macro("vd", {
from: points.bicepsRight,
to: points.raglanTipBack,
x: points.bicepsRight.x + 30 + sa
});
macro("hd", {
from: points.raglanTipFront,
to: points.raglanTop,
y: points.raglanTipBack.y - 15 - sa
});
macro("hd", {
from: points.raglanTop,
to: points.raglanTipBack,
y: points.raglanTipBack.y - 15 - sa
});
macro("hd", {
from: points.bicepsLeft,
to: points.raglanTop,
y: points.raglanTipBack.y - 30 - sa
});
macro("hd", {
from: points.bicepsLeft,
to: points.bicepsRight,
y: points.raglanTipBack.y - 45 - sa
});
macro("hd", {
from: points.wristLeft,
to: points.wristRight,
y: points.wristLeft.y + 15 + sa
});
}
return part;
}
};
export default sleeve;

View file

@ -0,0 +1,76 @@
var waistband = {
draft: function(part) {
// prettier-ignore
let {measurements, options, sa, Point, points, Path, paths, complete, paperless, macro, units} = part.shorthand();
let width =
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip) *
options.ribbingWidth *
2;
points.topLeft = new Point(0, 0);
points.bottomLeft = new Point(0, width);
points.topMidLeft = new Point(width, 0);
points.bottomMidLeft = new Point(width, width);
points.topMidRight = new Point(width * 1.5, 0);
points.bottomMidRight = new Point(width * 1.5, width);
points.topRight = new Point(width * 2.5, 0);
points.bottomRight = new Point(width * 2.5, width);
paths.seam = new Path()
.move(points.topMidLeft)
.line(points.topLeft)
.line(points.bottomLeft)
.line(points.bottomMidLeft)
.move(points.bottomMidRight)
.line(points.bottomRight)
.line(points.topRight)
.line(points.topMidRight)
.attr("class", "fabric");
paths.hint = new Path()
.move(points.topMidLeft)
.line(points.topMidRight)
.move(points.bottomMidLeft)
.line(points.bottomMidRight)
.attr("class", "fabric dashed");
// Complete pattern?
if (complete) {
if (sa) {
paths.sa = paths.seam.offset(sa);
}
points.title = points.bottomLeft.shiftFractionTowards(
points.topRight,
0.5
);
macro("title", { at: points.title, nr: 8, title: "waistband" });
macro("grainline", {
from: points.bottomMidLeft,
to: points.topMidLeft
});
}
// Paperless?
if (paperless) {
macro("vd", {
from: points.bottomRight,
to: points.topRight,
x: points.topRight.x + sa + 15
});
macro("hd", {
from: points.bottomLeft,
to: points.bottomRight,
y: points.bottomRight.y + sa + 15,
text: units(
measurements.chestCircumference *
(1 + options.chestEase) *
(1 - options.ribbingStretchFactor)
)
});
}
return part;
}
};
export default waistband;