From 65f86a187b4ece76ed3a84eb623a039dcf33b29e Mon Sep 17 00:00:00 2001 From: David Clegg Date: Wed, 5 Apr 2023 21:19:56 +0200 Subject: [PATCH] feat: Adding magde, a bike messenger bag pattern --- config/exceptions.yaml | 2 + config/software/designs.json | 7 + designs/magde/CHANGELOG.md | 9 + designs/magde/README.md | 296 ++++++++++++++++++++++ designs/magde/build.mjs | 35 +++ designs/magde/data.mjs | 4 + designs/magde/package.json | 69 +++++ designs/magde/src/backPanel.mjs | 130 ++++++++++ designs/magde/src/bodyLiner.mjs | 212 ++++++++++++++++ designs/magde/src/frontOrganiserBase.mjs | 96 +++++++ designs/magde/src/frontOrganiserFront.mjs | 119 +++++++++ designs/magde/src/frontPanel.mjs | 187 ++++++++++++++ designs/magde/src/index.mjs | 35 +++ designs/magde/src/lidLiner.mjs | 124 +++++++++ designs/magde/src/lidOnePiece.mjs | 117 +++++++++ designs/magde/src/strapAttachments.mjs | 136 ++++++++++ designs/magde/src/twoPieceLidBottom.mjs | 110 ++++++++ designs/magde/src/twoPieceLidTop.mjs | 117 +++++++++ designs/magde/tests/shared.test.mjs | 16 ++ 19 files changed, 1821 insertions(+) create mode 100644 designs/magde/CHANGELOG.md create mode 100644 designs/magde/README.md create mode 100644 designs/magde/build.mjs create mode 100644 designs/magde/data.mjs create mode 100644 designs/magde/package.json create mode 100644 designs/magde/src/backPanel.mjs create mode 100644 designs/magde/src/bodyLiner.mjs create mode 100644 designs/magde/src/frontOrganiserBase.mjs create mode 100644 designs/magde/src/frontOrganiserFront.mjs create mode 100644 designs/magde/src/frontPanel.mjs create mode 100644 designs/magde/src/index.mjs create mode 100644 designs/magde/src/lidLiner.mjs create mode 100644 designs/magde/src/lidOnePiece.mjs create mode 100644 designs/magde/src/strapAttachments.mjs create mode 100644 designs/magde/src/twoPieceLidBottom.mjs create mode 100644 designs/magde/src/twoPieceLidTop.mjs create mode 100644 designs/magde/tests/shared.test.mjs diff --git a/config/exceptions.yaml b/config/exceptions.yaml index 27bec9534ad..ed52c27c108 100644 --- a/config/exceptions.yaml +++ b/config/exceptions.yaml @@ -35,6 +35,8 @@ packageJson: author: SeaZeeZee (https://github.com/SeaZeeZee) lunetius: &starf author: Starfetch (https://github.com/starfetch) + magde: + author: clegganator259 (https://github.com/clegganator259) new-design: exports: '!' bin: diff --git a/config/software/designs.json b/config/software/designs.json index f4a64a98798..1188fd8936a 100644 --- a/config/software/designs.json +++ b/config/software/designs.json @@ -63,6 +63,13 @@ "difficulty": 2, "tags": ["accessories", "historical", "bags"] }, + "magde": { + "description": "A FreeSewing pattern for a bike messenger bag", + "code": "clegganator259", + "design": "clegganator259", + "difficulty": 3, + "tags": ["accessories", "bags"] + }, "octoplushy": { "description": "A FreeSewing pattern for an octopus plushy toy", "code": "Wouter Van Wageningen", diff --git a/designs/magde/CHANGELOG.md b/designs/magde/CHANGELOG.md new file mode 100644 index 00000000000..0e0ea3da423 --- /dev/null +++ b/designs/magde/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change log for: @freesewing/magde + + + +This is the **initial release**, and the start of this change log. + +> Prior to version 2, FreeSewing was not a JavaScript project. +> As such, that history is out of scope for this change log. + diff --git a/designs/magde/README.md b/designs/magde/README.md new file mode 100644 index 00000000000..dd08f2012da --- /dev/null +++ b/designs/magde/README.md @@ -0,0 +1,296 @@ +![FreeSewing](https://static.freesewing.org/banner.png) +

@freesewing/magde on NPM + License: MIT + Code quality on DeepScan + Open issues tagged pkg:magde + All Contributors +

Follow @freesewing_org on Twitter + Chat with us on Discord + Become a FreeSewing Patron + Follow @freesewing_org on Twitter +

+ +# @freesewing/magde + +A FreeSewing pattern for a bike messenger bag + + + + +> #### Note: Version 3 is a work in progress +> +> We are working on a new major version (v3) but it is not ready for prime-time. +> For production use, please refer to our v2 packages (the `latest` on NPM) +> or [the `v2` branch in our monorepo](https://github.com/freesewing/freesewing/tree/v2). +> +> We the `main` branch and `next` packages on NPM holds v3 code. But it's alpha for now. + +## What am I looking at? πŸ€” + +This repository is our *monorepo* holding all our NPM designs, plugins, other NPM packages, and (web)sites. + +This folder holds: @freesewing/magde + +If you're not entirely sure what to do or how to start, type this command: + +``` +npm run tips +``` + +> If you don't want to set up a dev environment, you can run it in your browser: +> +> [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/freesewing/freesewing) +> +> We recommend that you fork our repository and then +> put `gitpod.io/# to start up a browser-based dev environment of your own. + +## About FreeSewing πŸ’€ + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate +our sewing patterns adapted to your measurements. + +If you're a developer, our documentation is on [freesewing.dev](https://freesewing.dev/). +Our [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox +for parametric design of sewing patterns. But we also provide a range +of [plugins](https://freesewing.dev/reference/plugins/) that further extend the +functionality of the platform. + +If you have NodeJS installed, you can try it right now by running: + +```bash +npx create-freesewing-pattern +``` + +Or, consult our getting started guides +for [Linux](https://freesewing.dev/tutorials/getting-started-linux/), +[MacOS](https://freesewing.dev/tutorials/getting-started-mac/), +or [Windows](https://freesewing.dev/tutorials/getting-started-windows/). + +We also have a [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) that +walks you through your first parametric design, +and [a friendly community](https://freesewing.org/community/where/) with +people who can help you when you get stuck. + +## Support FreeSewing: Become a patron πŸ₯° + +FreeSewing is an open source project run by a community, +and financially supported by our patrons. + +If you feel what we do is worthwhile, and you can spend a few coind without +hardship, then you should [join us and become a patron](https://freesewing.org/community/join). + +## Links πŸ‘©β€πŸ’» + + - πŸ’» Makers website: [freesewing.org](https://freesewing.org) + - πŸ’» Developers website: [freesewing.dev](https://freesewing.dev) + - πŸ’¬ Chat: On Discord via [discord.freesewing.org](https://discord.freesewing.org/) + - βœ… Todo list/Kanban board: On Github via [todo.freesewing.org](https://todo.freesewing.org/) + - 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org) + - πŸ“· Instagram: [@freesewing_org](https://instagram.com/freesewing_org) + +## License: MIT πŸ€“ + +Β© [Joost De Cock](https://github.com/joostdecock). +See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details. + +## Where to get help 🀯 + +Our [chatrooms on Discord](https://chat.freesewing.org/) are the best place to ask questions, +share your feedback, or just hang out. + +If you want to report a problem, please [create an issue](https://github.com/freesewing/freesewing/issues/new). + + + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Adam Tomkins
Adam Tomkins

πŸ“–
Alexandre Ignjatovic
Alexandre Ignjatovic

πŸ’»
AlfaLyr
AlfaLyr

πŸ’» πŸ”Œ 🎨
Andrew James
Andrew James

πŸ“–
Anneke
Anneke

πŸ“– 🌍
Annie Kao
Annie Kao

πŸ“–
Anternative
Anternative

πŸ“–
Anthony
Anthony

πŸ’¬
Ari Grayzel-student
Ari Grayzel-student

πŸ’»
Bart
Bart

πŸ“–
BenJamesBen
BenJamesBen

πŸ’» πŸ“– πŸ›
Cameron Dubas
Cameron Dubas

πŸ“–
Carsten Biebricher
Carsten Biebricher

πŸ“–
Cathy Zoller
Cathy Zoller

πŸ“–
Chantal Lapointe
Chantal Lapointe

🌍
Damien PIQUET
Damien PIQUET

πŸ’»
Darigov Research
Darigov Research

πŸ“– πŸ€”
Elena FdR
Elena FdR

πŸ“– πŸ“
Emmanuel Nyachoke
Emmanuel Nyachoke

πŸ’» πŸ“–
Enoch Riese
Enoch Riese

πŸ’»
EvEkSwed
EvEkSwed

🌍
Fantastik-Maman
Fantastik-Maman

🌍
Forrest O.
Forrest O.

πŸ“–
FrΓ©dΓ©ric
FrΓ©dΓ©ric

🌍
Glenn Matthews
Glenn Matthews

πŸ“–
Greg Sadetsky
Greg Sadetsky

πŸ“–
Igor Couto
Igor Couto

πŸ›
Ikko Ashimine
Ikko Ashimine

πŸ“–
Irapeke
Irapeke

🌍
Jacek Sawoszczuk
Jacek Sawoszczuk

πŸ“–
Jason Williams
Jason Williams

πŸ“–
Jeremy Jackson
Jeremy Jackson

πŸ’»
Jeroen Hoek
Jeroen Hoek

πŸ“–
Joe Schofield
Joe Schofield

πŸ“–
Joebidido
Joebidido

🌍
Joost De Cock
Joost De Cock

🚧
Josh Essman
Josh Essman

πŸ“–
Kake
Kake

πŸ“–
Kapunahele Wong
Kapunahele Wong

πŸ“–
Karen
Karen

πŸ“– πŸ“‹
Katie McGinley
Katie McGinley

πŸ“–
Kieran Klaassen
Kieran Klaassen

πŸ’»
Kittycatou
Kittycatou

🌍
Kris
Kris

πŸ“–
Kristin Ruben
Kristin Ruben

πŸ’»
Loudepeuter
Loudepeuter

🌍
Lucian
Lucian

πŸ“‹
MA-TATAS
MA-TATAS

πŸ“–
Marcus
Marcus

🌍
Martin Tribo
Martin Tribo

πŸ“–
Nadege Michel
Nadege Michel

⚠️ πŸ“–
Natalia
Natalia

πŸ’» 🎨 πŸ“
Nathan Yergler
Nathan Yergler

πŸ“–
Nick Dower
Nick Dower

πŸ“– πŸ’» πŸ›
Nikhil Chelliah
Nikhil Chelliah

πŸ“–
OysteinHoiby
OysteinHoiby

πŸ’»
Patrick Forringer
Patrick Forringer

πŸ”Œ
Paul
Paul

πŸ“– πŸ“ 🌍
Phillip Thelen
Phillip Thelen

πŸ’»
Pixieish
Pixieish

πŸ“–
Prof. dr. Sorcha NΓ­ Dhubhghaill
Prof. dr. Sorcha NΓ­ Dhubhghaill

πŸ“–
Quentin FELIX
Quentin FELIX

πŸ’» 🎨
Rik Hekker
Rik Hekker

πŸ›
Sam Livingston-Gray
Sam Livingston-Gray

πŸ“–
Sanne
Sanne

πŸ’» πŸ“–
Sara Latorre
Sara Latorre

🌍
SeaZeeZee
SeaZeeZee

πŸ“– πŸ’»
SimonbJohnson
SimonbJohnson

πŸ›
SirCharlotte
SirCharlotte

🌍
Slylele
Slylele

πŸ“– 🌍
Soazillon
Soazillon

🌍
SoneaTheBest
SoneaTheBest

🌍
Stefan Sydow
Stefan Sydow

🌍 πŸ“– πŸ’»
TrΓ­ona
TrΓ­ona

πŸ“–
Unmutual
Unmutual

πŸ“–
Wouter van Wageningen
Wouter van Wageningen

πŸ’» 🎨 πŸ”§
amysews
amysews

πŸ“–
anna-puk
anna-puk

πŸ’»
beautifulsummermoon
beautifulsummermoon

🌍
berce
berce

πŸ“–
biou
biou

πŸ’»
bobgeorgethe3rd
bobgeorgethe3rd

πŸ’» πŸ“– 🎨
brmlyklr
brmlyklr

πŸ“–
chri5b
chri5b

πŸ’» ⚠️
dingcycle
dingcycle

🌍
drowned-in-books
drowned-in-books

πŸ’¬
econo202
econo202

πŸ“–
ericamattos
ericamattos

🌍
fightingrabbit
fightingrabbit

πŸ’»
gaylyndie
gaylyndie

πŸ“–
grimlokason
grimlokason

πŸ’»
hellgy
hellgy

🎨
jackseye
jackseye

πŸ“–
marckiesel
marckiesel

🌍
mergerg
mergerg

πŸ“–
mesil
mesil

πŸ›
starfetch
starfetch

πŸ’» πŸ“– 🌍 🎨
timorl
timorl

πŸ’»
ttimearl
ttimearl

πŸ–‹
tuesgloomsday
tuesgloomsday

πŸ“–
valadaptive
valadaptive

πŸ’»
viocky
viocky

🌍
woolishboy
woolishboy

πŸ’»
yc
yc

🌍
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! + diff --git a/designs/magde/build.mjs b/designs/magde/build.mjs new file mode 100644 index 00000000000..99ace216bc8 --- /dev/null +++ b/designs/magde/build.mjs @@ -0,0 +1,35 @@ +/* This script will build the package with esbuild */ +import esbuild from 'esbuild' +import pkg from './package.json' assert { type: 'json' } + +// Create banner based on package info +const banner = `/** + * ${pkg.name} | v${pkg.version} + * ${pkg.description} + * (c) ${new Date().getFullYear()} ${pkg.author} + * @license ${pkg.license} + */` + +// Shared esbuild options +const options = { + banner: { js: banner }, + bundle: true, + entryPoints: ['src/index.mjs'], + format: 'esm', + outfile: 'dist/index.mjs', + external: ['@freesewing'], + metafile: process.env.VERBOSE ? true : false, + minify: process.env.NO_MINIFY ? false : true, + sourcemap: true, +} + +// Let esbuild generate the build +const build = async () => { + const result = await esbuild.build(options).catch(() => process.exit(1)) + + if (process.env.VERBOSE) { + const info = await esbuild.analyzeMetafile(result.metafile) + console.log(info) + } +} +build() diff --git a/designs/magde/data.mjs b/designs/magde/data.mjs new file mode 100644 index 00000000000..70f691b1d70 --- /dev/null +++ b/designs/magde/data.mjs @@ -0,0 +1,4 @@ +// This file is auto-generated | All changes you make will be overwritten. +export const name = '@freesewing/magde' +export const version = '3.0.0-alpha.8' +export const data = { name, version } diff --git a/designs/magde/package.json b/designs/magde/package.json new file mode 100644 index 00000000000..4c7d9edb919 --- /dev/null +++ b/designs/magde/package.json @@ -0,0 +1,69 @@ +{ + "name": "@freesewing/magde", + "version": "3.0.0-alpha.8", + "description": "A FreeSewing pattern for a bike messenger bag", + "author": "clegganator259 (https://github.com/clegganator259)", + "homepage": "https://freesewing.org/", + "repository": "github:freesewing/freesewing", + "license": "MIT", + "bugs": { + "url": "https://github.com/freesewing/freesewing/issues" + }, + "funding": { + "type": "individual", + "url": "https://freesewing.org/patrons/join" + }, + "keywords": [ + "freesewing", + "design", + "diy", + "fashion", + "made to measure", + "parametric design", + "pattern", + "sewing", + "sewing pattern" + ], + "type": "module", + "module": "dist/index.mjs", + "exports": { + ".": "./dist/index.mjs" + }, + "scripts": { + "build": "node build.mjs", + "clean": "rimraf dist", + "mbuild": "NO_MINIFY=1 node build.mjs", + "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", + "test": "npx mocha tests/*.test.mjs", + "vbuild": "VERBOSE=1 node build.mjs", + "lab": "cd ../../sites/lab && yarn start", + "tips": "node ../../scripts/help.mjs", + "lint": "npx eslint 'src/**' 'tests/*.mjs'", + "prettier": "npx prettier --write 'src/*.mjs' 'tests/*.mjs'", + "testci": "npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js", + "cibuild_step5": "node build.mjs", + "wbuild": "node build.mjs", + "wcibuild_step5": "node build.mjs" + }, + "peerDependencies": { + "@freesewing/core": "3.0.0-alpha.8", + "@freesewing/plugin-bundle": "3.0.0-alpha.8" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "10.0.0", + "chai": "4.2.0" + }, + "files": [ + "dist/*", + "README.md" + ], + "publishConfig": { + "access": "public", + "tag": "next" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8" + } +} diff --git a/designs/magde/src/backPanel.mjs b/designs/magde/src/backPanel.mjs new file mode 100644 index 00000000000..2d4e5b4bbfb --- /dev/null +++ b/designs/magde/src/backPanel.mjs @@ -0,0 +1,130 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftBackPanel({ + options, + Point, + Path, + points, + paths, + complete, + sa, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const depth = options.size * 150 + const taperWidth = width * options.taperRatio + points.origin = new Point(0, 0) + points.topRightCorner = new Point(width, 0) + points.bottomRightCorner = new Point(taperWidth + depth, height) + points.baseFlapBackRight = new Point(taperWidth, height) + points.baseFlapFrontRight = new Point(taperWidth, height + depth) + points.bottomLeftCorner = new Point(0, height + depth) + + paths.seam = new Path() + .move(points.bottomLeftCorner) + .line(points.baseFlapFrontRight) + .line(points.baseFlapBackRight) + .line(points.bottomRightCorner) + .line(points.topRightCorner) + .line(points.origin) + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.origin, + to: points.bottomLeftCorner, + }) + + macro('title', { + at: new Point(taperWidth / 2, height / 2), + title: 'Back Panel', + nr: '1', + }) + + paths.foldLine = new Path() + .move(new Point(0, points.baseFlapBackRight.y)) + .line(points.baseFlapBackRight) + .setClass('dotted note') + .addText('Base Fold', 'center note') + + if (sa) { + var bottomSeam = new Path() + .move(points.bottomLeftCorner) + .line(points.baseFlapFrontRight) + .addText('Flat fell', 'center text-sm') + .offset(2 * sa) + var sideFlapSeam = new Path() + .move(points.baseFlapFrontRight) + .line(points.baseFlapBackRight) + .line(points.bottomRightCorner) + .offset(2 * sa) + .trim() + var sideSeam = new Path() + .move(points.bottomRightCorner) + .line(points.topRightCorner) + .offset(sa) + var topSeam = new Path() + .move(points.topRightCorner) + .line(points.origin) + .offset(2 * sa) + paths.sa = bottomSeam + .join(sideFlapSeam) + .join(sideSeam) + .join(topSeam) + .trim() + .setClass('fabric sa') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.topRightCorner, + y: -(2 * sa + 15), + }) + macro('hd', { + from: points.topRightCorner, + to: points.bottomRightCorner, + y: -(2 * sa + 15), + }) + macro('hd', { + from: points.bottomRightCorner, + to: points.baseFlapBackRight, + y: points.baseFlapFrontRight.y + 2 * sa + 15, + }) + macro('hd', { + from: points.baseFlapBackRight, + to: points.origin, + y: points.baseFlapFrontRight.y + 2 * sa + 15, + }) + macro('vd', { + from: points.origin, + to: points.bottomRightCorner, + x: points.bottomRightCorner.x + 2 * sa + 15, + }) + macro('vd', { + from: points.bottomRightCorner, + to: points.baseFlapFrontRight, + x: points.bottomRightCorner.x + 2 * sa + 15, + }) + } + + return part +} + +export const backPanel = { + name: 'backPanel', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftBackPanel, +} diff --git a/designs/magde/src/bodyLiner.mjs b/designs/magde/src/bodyLiner.mjs new file mode 100644 index 00000000000..500ff540ce7 --- /dev/null +++ b/designs/magde/src/bodyLiner.mjs @@ -0,0 +1,212 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftBodyLiner({ + options, + Point, + Path, + points, + paths, + complete, + sa, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const depth = options.size * 150 + const taperWidth = width * options.taperRatio + const openingWidth = taperWidth * options.openingRatio + const openingHeight = height * options.openingRatio + const frontFlapHeight = height * options.flapHeightRatio + const frontFlapWidth = taperWidth * 0.8 + points.origin = new Point(0, 0) + points.bodyTopRight = new Point(width, 0) + points.sideFlapFrontPoint = new Point(taperWidth + depth, height) + points.sideFlapBackPoint = new Point(taperWidth, height) + points.baseFrontRight = new Point(taperWidth, height + depth) + points.frontFlapMidRight = new Point(width, 2 * height + depth) + points.falseFrontFlapRight = new Point(frontFlapWidth, frontFlapHeight + 2 * height + depth) + points.frontFlapPeakRight = points.frontFlapMidRight.shiftFractionTowards( + points.falseFrontFlapRight, + 0.2 + ) + points.frontOpeningRight = new Point(openingWidth, openingHeight + height + depth) + points.frontOpeningLeft = new Point(0, openingHeight + height + depth) + + paths.seam = new Path() + .move(points.frontOpeningLeft) + .line(points.frontOpeningRight) + .line(points.frontFlapPeakRight) + .line(points.frontFlapMidRight) + .line(points.baseFrontRight) + .line(points.sideFlapBackPoint) + .line(points.sideFlapFrontPoint) + .line(points.bodyTopRight) + .line(points.origin) + .close() + .attr('class', 'lining') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.origin, + to: points.frontOpeningLeft, + }) + points.label = new Point(taperWidth / 2, height / 2) + macro('title', { + at: points.label, + nr: '5', + title: 'Body Lining', + }) + + paths.foldLineSideFlap = new Path() + .move(points.bodyTopRight) + .line(points.sideFlapBackPoint) + .setClass('dotted note') + .addText('SideFlap Fold', 'center note') + + paths.foldLineBaseBack = new Path() + .move(new Point(0, points.sideFlapBackPoint.y)) + .line(points.sideFlapBackPoint) + .setClass('dotted note') + .addText('Base Fold', 'center note') + paths.foldLineBaseFront = new Path() + .move(new Point(0, points.baseFrontRight.y)) + .line(points.baseFrontRight) + .setClass('dotted note') + .addText('Base Fold', 'center note') + + if (sa) { + points.temp = points.baseFrontRight.shiftFractionTowards(points.sideFlapBackPoint, -0.2) + var baseFrenchSeams = new Path() + .move(points.baseFrontRight) + .line(points.sideFlapBackPoint) + .line(points.sideFlapFrontPoint) + .offset(2 * sa) + .addText('French Seam') + var openingBindingTop = new Path() + .move(points.frontOpeningLeft) + .line(points.frontOpeningRight) + .offset(-sa) + var openingBindingSideRough = new Path() + .move(points.frontOpeningRight) + .line(points.frontFlapPeakRight) + .offset(-sa) + var openingBinding = openingBindingTop + .join( + new Path() + .move(openingBindingSideRough.start()) + .line( + openingBindingSideRough.intersects( + new Path() + .move(points.frontFlapPeakRight) + .line(points.frontFlapMidRight) + .line(points.baseFrontRight) + )[0] + ) + ) + .addText('Bind with seamtape', 'center text-sm') + .setClass('lining sa') + var frontSideSa = new Path() + .move(points.frontFlapMidRight) + .line(points.baseFrontRight) + .offset(sa) + + var sideFlapSa = new Path() + .move(points.sideFlapFrontPoint) + .line(points.bodyTopRight) + .offset(sa) + + paths.openingBinding = openingBinding + paths.baseSa = new Path() + .move(points.baseFrontRight) + .join(baseFrenchSeams) + .addText('French Seam', 'center text-lg') + .join(sideFlapSa) + .join( + new Path() + .move(points.bodyTopRight) + .line(points.origin) + .offset(2 * sa) + ) + .trim() + .setClass('lining sa') + paths.frontAndTopSa = new Path() + .move(points.frontFlapMidRight) + .line(frontSideSa.start()) + .line(frontSideSa.intersects(paths.baseSa)[0]) + .trim() + .setClass('lining sa') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.bodyTopRight, + to: points.sideFlapFrontPoint, + y: points.bodyTopRight.y - 2 * sa - 15, + }) + macro('hd', { + from: points.origin, + to: points.sideFlapFrontPoint, + y: points.bodyTopRight.y - 2 * sa - 25, + }) + macro('hd', { + from: points.sideFlapBackPoint, + to: points.sideFlapFrontPoint, + y: points.sideFlapBackPoint.y - 15, + }) + macro('hd', { + from: points.frontOpeningLeft, + to: points.frontOpeningRight, + y: points.frontOpeningRight.y + 2 * sa + 15, + }) + macro('hd', { + from: points.frontOpeningLeft, + to: points.frontFlapPeakRight, + y: points.frontFlapPeakRight.y + 2 * sa, + }) + macro('hd', { + from: points.frontFlapPeakRight, + to: points.frontFlapMidRight, + y: points.frontFlapPeakRight.y + 2 * sa, + }) + macro('vd', { + from: points.bodyTopRight, + to: points.sideFlapFrontPoint, + x: points.sideFlapFrontPoint.x + 2 * sa, + }) + macro('vd', { + from: points.sideFlapFrontPoint, + to: points.baseFrontRight, + x: points.sideFlapFrontPoint.x + 2 * sa, + }) + macro('vd', { + from: points.baseFrontRight, + to: points.frontFlapMidRight, + x: points.sideFlapFrontPoint.x + 2 * sa, + }) + macro('vd', { + from: points.frontFlapMidRight, + to: points.frontFlapPeakRight, + x: points.sideFlapFrontPoint.x + 2 * sa, + }) + } + + return part +} + +export const bodyLiner = { + name: 'bodyLiner', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftBodyLiner, +} diff --git a/designs/magde/src/frontOrganiserBase.mjs b/designs/magde/src/frontOrganiserBase.mjs new file mode 100644 index 00000000000..48d7ef23432 --- /dev/null +++ b/designs/magde/src/frontOrganiserBase.mjs @@ -0,0 +1,96 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftFrontOrganiserBase({ + options, + Point, + Path, + Snippet, + points, + paths, + complete, + sa, + snippets, + paperless, + macro, + part, +}) { + // Width is *not halved* as this is not cut on fold unlike most other pattern + // pieces + const width = options.size * 500 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const openingWidth = taperWidth * options.openingRatio + const openingHeight = height * options.openingRatio + + points.origin = new Point(0, 0) + points.bottomRight = new Point(openingWidth, openingHeight) + points.bottomLeft = new Point(0, openingHeight) + points.topRight = new Point(openingWidth, 0) + + paths.seam = new Path() + .move(points.origin) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.topRight) + .line(points.origin) + .close() + .setClass('fabric') + + // Complete? + if (complete) { + points.label = new Point(openingWidth / 4, openingHeight / 2) + macro('title', { + at: points.label, + title: 'Organiser Base', + nr: '7', + }) + + if (sa) { + paths.sa = paths.seam.offset(2 * sa).setClass('fabric sa') + paths.leftHem = new Path() + .move(points.bottomLeft) + .line(points.origin) + .addText('Rolled Hem', 'center') + paths.RighHem = new Path() + .move(points.topRight) + .line(points.bottomRight) + .addText('Rolled Hem', 'center') + paths.topHem = new Path() + .move(points.origin) + .line(points.topRight) + .addText('Rolled Hem', 'center') + paths.bottomSeam = new Path() + .move(points.bottomRight) + .line(points.bottomLeft) + .addText('Baste into Front Panel SA', 'center') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.bottomRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('vd', { + from: points.origin, + to: points.bottomRight, + x: points.bottomRight.x + 2 * sa + 15, + }) + } + + return part +} + +export const frontOrganiserBase = { + name: 'frontOrganiserBase', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftFrontOrganiserBase, +} diff --git a/designs/magde/src/frontOrganiserFront.mjs b/designs/magde/src/frontOrganiserFront.mjs new file mode 100644 index 00000000000..6a92505543b --- /dev/null +++ b/designs/magde/src/frontOrganiserFront.mjs @@ -0,0 +1,119 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftFrontOrganiserFront({ + options, + Point, + Path, + Snippet, + points, + paths, + complete, + sa, + snippets, + paperless, + macro, + part, +}) { + // Width is *not halved* as this is not cut on fold unlike most other pattern + // pieces + const width = options.size * 500 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const openingWidth = taperWidth * options.openingRatio + const openingHeight = height * options.openingRatio + const penInsertXCoords = [ + openingWidth / 2, + (5 * openingWidth) / 8, + (6 * openingWidth) / 8, + (7 * openingWidth) / 8, + ] + + points.origin = new Point(0, 0) + points.bottomRight = new Point(openingWidth, openingHeight * 0.66) + points.bottomLeft = new Point(0, openingHeight * 0.66) + points.topRight = new Point(openingWidth, 0) + + paths.seam = new Path() + .move(points.origin) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.topRight) + .line(points.origin) + .close() + .setClass('fabric') + + // Complete? + if (complete) { + points.label = new Point(openingWidth * 0.1, openingHeight / 2) + macro('title', { + at: points.label, + title: 'Organiser Front', + nr: '8', + }) + + if (sa) { + penInsertXCoords.forEach(function (xVal, i) { + paths[`penInsert${i}`] = new Path() + .move(new Point(xVal, 0)) + .line(new Point(xVal, points.bottomRight.y)) + .setClass('note sa') + .addText('Divider Seam', 'center text-color-note') + }) + paths.sa = paths.seam.offset(2 * sa).setClass('fabric sa') + paths.leftHem = new Path() + .move(points.bottomLeft) + .line(points.origin) + .addText('Rolled Hem', 'center') + paths.RighHem = new Path() + .move(points.topRight) + .line(points.bottomRight) + .addText('Rolled Hem', 'center') + paths.topHem = new Path() + .move(points.origin) + .line(points.topRight) + .addText('Rolled Hem', 'center') + paths.bottomSeam = new Path() + .move(points.bottomRight) + .line(points.bottomLeft) + .addText('Baste into Front Panel SA', 'center') + } + } + + // Paperless? + if (paperless) { + var verticalSeamsXCoords = [0].concat(penInsertXCoords).concat([openingWidth]) + for (var i = 0; i < verticalSeamsXCoords.length - 1; i++) { + var thisX = verticalSeamsXCoords[i] + var nextX = verticalSeamsXCoords[i + 1] + macro('hd', { + from: new Point(thisX, 0), + to: new Point(nextX, 0), + y: points.bottomRight.y / 4, + }) + } + macro('hd', { + from: points.origin, + to: points.bottomRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('vd', { + from: points.origin, + to: points.bottomRight, + x: points.bottomRight.x + 2 * sa + 15, + }) + } + + return part +} + +export const frontOrganiserFront = { + name: 'frontOrganiserFront', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftFrontOrganiserFront, +} diff --git a/designs/magde/src/frontPanel.mjs b/designs/magde/src/frontPanel.mjs new file mode 100644 index 00000000000..8644f207ad5 --- /dev/null +++ b/designs/magde/src/frontPanel.mjs @@ -0,0 +1,187 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftFrontPanel({ + options, + Point, + Path, + Snippet, + points, + paths, + complete, + sa, + snippets, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const openingWidth = taperWidth * options.openingRatio + const openingHeight = height * options.openingRatio + const frontFlapHeight = height * options.flapHeightRatio + const frontFlapWidth = taperWidth * 0.8 + points.origin = new Point(0, 0) + points.frontFlapMidRight = new Point(width, height) + points.frontFlapBottom = new Point(taperWidth, 0) + points.falseFrontFlapRight = new Point(frontFlapWidth, frontFlapHeight + height) + points.frontFlapPeakRight = points.frontFlapMidRight.shiftFractionTowards( + points.falseFrontFlapRight, + 0.2 + ) + points.frontOpeningRight = new Point(openingWidth, openingHeight) + points.frontOpeningLeft = new Point(0, openingHeight) + + paths.seam = new Path() + .move(points.frontOpeningLeft) + .line(points.frontOpeningRight) + .line(points.frontFlapPeakRight) + .line(points.frontFlapMidRight) + .line(points.frontFlapBottom) + .line(points.origin) + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.origin, + to: points.frontOpeningLeft, + }) + + points.label = new Point(openingWidth / 4, openingHeight / 2) + macro('title', { + at: points.label, + title: 'Front Panel', + nr: '2', + }) + + paths.FrontOrganiserAlignment = new Path() + .move(new Point(points.frontOpeningRight.x, 0)) + .line(points.frontOpeningRight) + .setClass('note dotted') + paths.velcro = paths.FrontOrganiserAlignment.join( + new Path() + .move(new Point(points.falseFrontFlapRight.x, points.frontOpeningRight.y)) + .line(new Point(points.falseFrontFlapRight.x, 0)) + ).setClass('various fill-various') + var midVelcroX = (points.frontOpeningRight.x + points.falseFrontFlapRight.x) / 2 + paths.velcroLabel = new Path() + .move(new Point(midVelcroX, points.frontOpeningRight.y)) + .line(new Point(midVelcroX, 0)) + .addText('Velcro loop', 'note center') + .addClass('no-stroke') + snippets.webbingNotch = new Snippet('notch', new Point(midVelcroX, 0)) + + if (sa) { + var saPath = new Path() + .move(points.frontFlapMidRight) + .line(points.frontFlapBottom) + .line(points.origin) + .offset(sa * 2) + paths.sa = new Path().move(points.frontFlapMidRight).join(saPath).setClass('fabric sa') + var openingBindingTop = new Path() + .move(points.frontOpeningLeft) + .line(points.frontOpeningRight) + .offset(-sa) + var openingBindingSideRough = new Path() + .move(points.frontOpeningRight) + .line(points.frontFlapPeakRight) + .offset(-sa) + paths.openingBinding = openingBindingTop + .join( + new Path() + .move(openingBindingSideRough.start()) + .line( + openingBindingSideRough.intersects( + new Path() + .move(points.frontFlapPeakRight) + .line(points.frontFlapMidRight) + .line(points.frontFlapBottom) + )[0] + ) + ) + .addText('Bind with seamtape', 'center text-sm') + .setClass('fabric sa') + var lidBindingRough = new Path() + .move(points.frontFlapPeakRight) + .line(points.frontFlapMidRight) + .offset(-sa) + lidBindingRough = new Path() + .move(lidBindingRough.start()) + .line(lidBindingRough.start().shiftFractionTowards(lidBindingRough.end(), 3)) + paths.lidBinding = new Path() + .move( + lidBindingRough.intersects( + new Path().move(points.frontOpeningRight).line(points.frontFlapPeakRight) + )[0] + ) + .line( + lidBindingRough.intersects( + new Path().move(points.frontFlapMidRight).line(points.frontFlapBottom) + )[0] + ) + .addText('Bind with lid', 'center text-sm') + .setClass('fabric sa') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.frontFlapBottom, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.frontFlapBottom, + to: points.frontFlapMidRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.frontFlapMidRight, + to: points.frontFlapPeakRight, + y: points.frontFlapPeakRight.y + 2 * sa + 15, + }) + macro('hd', { + from: points.frontFlapPeakRight, + to: points.frontOpeningRight, + y: points.frontFlapPeakRight.y + 2 * sa + 15, + }) + macro('hd', { + from: points.frontOpeningRight, + to: points.frontOpeningLeft, + y: points.frontFlapPeakRight.y + 2 * sa + 15, + }) + macro('vd', { + from: points.origin, + to: points.frontOpeningLeft, + x: points.origin.x - 15, + }) + macro('vd', { + from: points.origin, + to: points.frontFlapMidRight, + x: points.frontFlapMidRight.x + 15, + }) + macro('vd', { + from: points.frontFlapMidRight, + to: points.frontFlapPeakRight, + x: points.frontFlapMidRight.x + 15, + }) + } + + return part +} + +export const frontPanel = { + name: 'frontPanel', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftFrontPanel, +} diff --git a/designs/magde/src/index.mjs b/designs/magde/src/index.mjs new file mode 100644 index 00000000000..908ade9b737 --- /dev/null +++ b/designs/magde/src/index.mjs @@ -0,0 +1,35 @@ +// + +import { Design } from '@freesewing/core' +import { data } from '../data.mjs' +// Parts +import { bodyLiner } from './bodyLiner.mjs' +import { frontPanel } from './frontPanel.mjs' +import { frontOrganiserBase } from './frontOrganiserBase.mjs' +import { frontOrganiserFront } from './frontOrganiserFront.mjs' +import { backPanel } from './backPanel.mjs' +import { lidOnePiece } from './lidOnePiece.mjs' +import { twoPieceLidTop } from './twoPieceLidTop.mjs' +import { twoPieceLidBottom } from './twoPieceLidBottom.mjs' +import { lidLiner } from './lidLiner.mjs' +import { strapAttachments } from './strapAttachments.mjs' + +// Create new design +const Magde = new Design({ + data, + parts: [ + backPanel, + frontPanel, + frontOrganiserBase, + frontOrganiserFront, + lidOnePiece, + twoPieceLidTop, + twoPieceLidBottom, + strapAttachments, + bodyLiner, + lidLiner, + ], +}) + +// Named exports +export { bodyLiner, Magde } diff --git a/designs/magde/src/lidLiner.mjs b/designs/magde/src/lidLiner.mjs new file mode 100644 index 00000000000..01a60197fc1 --- /dev/null +++ b/designs/magde/src/lidLiner.mjs @@ -0,0 +1,124 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftLidLiner({ + options, + Point, + Path, + points, + paths, + complete, + sa, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const lidFlapHeight = height * options.flapHeightRatio + const lidFlapWidth = taperWidth * 0.8 + points.origin = new Point(0, 0) + points.lidTopRight = new Point(lidFlapWidth, 0) + points.lidBottomRight = new Point(width, lidFlapHeight) + points.lidBottomLeft = new Point(0, lidFlapHeight) + + paths.seam = new Path() + .move(points.lidBottomLeft) + .line(points.lidBottomRight) + .line(points.lidTopRight) + .line(points.origin) + .close() + .attr('class', 'lining') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.origin, + to: points.lidBottomLeft, + }) + + points.label = new Point(lidFlapWidth / 2, lidFlapHeight / 2) + + macro('title', { + at: points.label, + title: 'Lid Liner', + nr: '6', + }) + + points.velcroPoint = new Path() + .move(new Point(0, 0.1 * height)) + .line(new Point(points.lidBottomRight.x, 0.1 * height)) + .intersects(new Path().move(points.lidTopRight).line(points.lidBottomRight))[0] + paths.velcro = new Path() + .move(new Point(0, points.velcroPoint.y)) + .line(points.velcroPoint) + .line(points.lidTopRight) + .line(points.origin) + .close() + .setClass('various fill-various') + paths.velcroLabel = new Path() + .move(new Point(0, points.velcroPoint.y / 1.5)) + .line(new Point(points.velcroPoint.x, points.velcroPoint.y / 1.5)) + .addText('Velcro hook', 'text-note center') + .addClass('no-stroke') + if (sa) { + paths.sa = new Path() + .move(points.lidBottomLeft) + .line(points.lidBottomRight) + .offset(2 * sa) + .addText('Flat fell seam', 'left') + .line(points.lidBottomRight) + .setClass('lining sa') + } + var topBindingLineRough = new Path().move(points.lidTopRight).line(points.origin).offset(-sa) + var sideBindingLineRough = new Path() + .move(points.lidBottomRight) + .line(points.lidTopRight) + .offset(-sa) + paths.boundLine = new Path() + .move(sideBindingLineRough.intersectsY(lidFlapHeight)[0]) + .line(topBindingLineRough.intersects(sideBindingLineRough)[0]) + .line(topBindingLineRough.end()) + .addText('Bind with tape once finished', 'center') + .setClass('lining sa') + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.lidTopRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidTopRight, + to: points.lidBottomRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidBottomRight, + to: points.lidBottomLeft, + y: points.lidBottomLeft.y + 2 * sa + 15, + }) + macro('vd', { + from: points.origin, + to: points.lidBottomRight, + x: points.lidBottomRight.x + 2 * sa + 15, + }) + } + + return part +} + +export const lidLiner = { + name: 'lidLiner', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftLidLiner, +} diff --git a/designs/magde/src/lidOnePiece.mjs b/designs/magde/src/lidOnePiece.mjs new file mode 100644 index 00000000000..268e3dcda43 --- /dev/null +++ b/designs/magde/src/lidOnePiece.mjs @@ -0,0 +1,117 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftLidOnePiece({ + options, + Point, + Path, + Snippet, + points, + paths, + complete, + sa, + snippets, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const lidFlapHeight = height * options.flapHeightRatio + const lidFlapWidth = taperWidth * 0.8 + const openingWidth = taperWidth * options.openingRatio + points.origin = new Point(0, 0) + points.lidTopRight = new Point(lidFlapWidth, 0) + points.lidBottomRight = new Point(width, lidFlapHeight) + points.lidBottomLeft = new Point(0, lidFlapHeight) + + paths.seam = new Path() + .move(points.lidBottomLeft) + .line(points.lidBottomRight) + .line(points.lidTopRight) + .line(points.origin) + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.origin, + to: points.lidBottomLeft, + }) + + points.label = new Point(lidFlapWidth / 2, lidFlapHeight / 2) + + macro('title', { + at: points.label, + title: 'Lid - One Piece', + nr: '3', + }) + points.notchPoint = new Point((openingWidth + lidFlapWidth) / 2, lidFlapHeight * 0.2).addText( + 'Webbing Notch', + 'center' + ) + snippets.webbingNotch = new Snippet('notch', points.notchPoint) + if (sa) { + paths.sa = new Path() + .move(points.lidBottomLeft) + .line(points.lidBottomRight) + .offset(2 * sa) + .addText('Flat fell seam', 'left') + .line(points.lidBottomRight) + .setClass('fabric sa') + } + var topBindingLineRough = new Path().move(points.lidTopRight).line(points.origin).offset(-sa) + var sideBindingLineRough = new Path() + .move(points.lidBottomRight) + .line(points.lidTopRight) + .offset(-sa) + paths.boundLine = new Path() + .move(sideBindingLineRough.intersectsY(lidFlapHeight)[0]) + .line(topBindingLineRough.intersects(sideBindingLineRough)[0]) + .line(topBindingLineRough.end()) + .addText('Bind with tape once finished', 'center') + .setClass('fabric sa') + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.lidTopRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidTopRight, + to: points.lidBottomRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidBottomRight, + to: points.lidBottomLeft, + y: points.lidBottomLeft.y + 2 * sa + 15, + }) + macro('vd', { + from: points.origin, + to: points.lidBottomRight, + x: points.lidBottomRight.x + 2 * sa + 15, + }) + } + if (!options.onePieceLid) part.hide() + + return part +} + +export const lidOnePiece = { + name: 'lidOnePiece', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + onePieceLid: { bool: false, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftLidOnePiece, +} diff --git a/designs/magde/src/strapAttachments.mjs b/designs/magde/src/strapAttachments.mjs new file mode 100644 index 00000000000..773c0fab6f7 --- /dev/null +++ b/designs/magde/src/strapAttachments.mjs @@ -0,0 +1,136 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftStrapAttachments({ + options, + Point, + Path, + Snippet, + points, + paths, + snippets, + complete, + sa, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const idealWebbingSize = height / 7.5 + var webbingSize = idealWebbingSize + if (options.useCommonWebbingSizes) { + var lowerBound = 6 + var upperBound = idealWebbingSize + const commonWebbingSizes = [6, 10, 12, 15, 20, 25, 30, 40, 45, 50] + // get the bigest size smaller than the ideal + var smallerSizes = commonWebbingSizes.filter(function (webbing) { + return webbing < idealWebbingSize + }) + lowerBound = smallerSizes.length >= 1 ? smallerSizes.at(-1) : lowerBound + // get the smallest size bigger than the ideal + var largerSizes = commonWebbingSizes.filter(function (webbing) { + return webbing >= idealWebbingSize + }) + upperBound = largerSizes.length >= 1 ? largerSizes[0] : upperBound + + // Pick the value closest to ideal defaulting to smaller + if (upperBound - idealWebbingSize > idealWebbingSize - lowerBound) { + webbingSize = lowerBound + } else { + webbingSize = upperBound + } + } else { + webbingSize = idealWebbingSize + } + + points.origin = new Point(0, 0) + points.webbingOpeningBottom = new Point(1.25 * webbingSize, 0) + points.bagAttachmentTop = new Point(0, 1.25 * webbingSize) + points.fakeBagCorner = new Point(height, points.bagAttachmentTop.y + (width - taperWidth)) + points.frontFlapBottom = new Point(taperWidth, 0) + points.bagAttachmentBottom = points.bagAttachmentTop.shiftFractionTowards( + points.fakeBagCorner, + 0.33 + ) + + paths.seam = new Path() + .move(points.bagAttachmentTop) + .line(points.bagAttachmentBottom) + .line(points.webbingOpeningBottom) + .line(points.origin) + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.origin, + to: points.bagAttachmentTop, + }) + + points.label = points.origin.shiftFractionTowards(points.bagAttachmentBottom, 0.55) + macro('title', { + at: new Point(webbingSize, webbingSize), + cutlist: true, + title: 'Strap Attachment', + nr: '4', + scale: 0.3, + }) + + points.webbingCenterNotch = points.origin.shiftFractionTowards(points.webbingOpeningBottom, 0.5) + points.webbingCenterLabel = points.webbingCenterNotch + .clone() + .translate(0, -5) + .addText(`Center of webbing (${webbingSize}mm)`, 'center text-xs') + + snippets.webbingCenter = new Snippet('notch', points.webbingCenterNotch) + + if (sa) { + var bagAttachSeam = new Path().move(points.bagAttachmentTop).line(points.bagAttachmentBottom) + var attachSeamAllowance = bagAttachSeam.offset(sa) + var bagAttachmentSa = new Path() + .move(attachSeamAllowance.intersectsX(0)[0]) + .line(attachSeamAllowance.end()) + var restOfSa = new Path() + .move(points.bagAttachmentBottom) + .line(points.webbingOpeningBottom) + .line(points.origin) + .offset(sa) + paths.sa = bagAttachmentSa.join(restOfSa).close().setClass('fabric sa') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.webbingOpeningBottom, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.origin, + to: points.bagAttachmentBottom, + y: points.bagAttachmentBottom.y + 2 * sa + 15, + }) + macro('vd', { + from: points.origin, + to: points.bagAttachmentBottom, + x: points.bagAttachmentBottom.x + 2 * sa, + }) + } + + return part +} + +export const strapAttachments = { + name: 'strapAttachments', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + useCommonWebbingSizes: { bool: true, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftStrapAttachments, +} diff --git a/designs/magde/src/twoPieceLidBottom.mjs b/designs/magde/src/twoPieceLidBottom.mjs new file mode 100644 index 00000000000..c9534db122e --- /dev/null +++ b/designs/magde/src/twoPieceLidBottom.mjs @@ -0,0 +1,110 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftTwoPieceLidBottom({ + options, + Point, + Path, + points, + paths, + complete, + sa, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const lidFlapHeight = height * options.flapHeightRatio + const lidFlapWidth = taperWidth * 0.8 + points.origin = new Point(0, 0) + points.lidTopRight = new Point(lidFlapWidth, 0) + points.lidBottomRight = new Point(width, lidFlapHeight) + points.lidBottomLeft = new Point(0, lidFlapHeight) + points.lidSeamRight = points.lidTopRight.shiftFractionTowards(points.lidBottomRight, 0.25) + points.lidSeamLeft = new Point(0, points.lidSeamRight.y) + + paths.seam = new Path() + .move(points.lidSeamLeft) + .line(points.lidSeamRight) + .line(points.lidTopRight) + .line(points.origin) + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + // macro('cutonfold', { + // from: points.lidTopLeft, + // to: points.lidSeamLeft, + // }) + + points.label = new Point(points.lidSeamRight.x / 3, points.lidSeamRight.y / 1.5) + + macro('title', { + at: points.label, + title: 'Lid Bottom - Two Piece', + nr: '3.2', + scale: 0.4, + }) + if (sa) { + var bindingLineSideRough = new Path() + .move(points.lidSeamRight) + .line(points.lidTopRight) + .offset(-sa) + var bindingLineTopRough = new Path().move(points.lidTopRight).line(points.origin).offset(-sa) + // points.tmp1 = bindingLineSideRough.intersectsY(points.lidSeamRight.y)[0] + paths.bindingLine = new Path() + .move(bindingLineSideRough.intersectsY(points.lidSeamLeft.y)[0]) + .line(bindingLineSideRough.intersects(bindingLineTopRough)[0]) + .line(bindingLineTopRough.end()) + .addClass('fabric sa') + paths.sa = new Path() + .move(points.lidSeamLeft) + .line(points.lidSeamRight) + .offset(2 * sa) + .line(points.lidSeamRight) + .setClass('fabric sa') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.lidSeamRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidTopRight, + to: points.lidSeamRight, + y: points.origin.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidSeamRight, + to: points.lidSeamLeft, + y: points.lidSeamLeft.y + 2 * sa + 15, + }) + macro('vd', { + from: points.origin, + to: points.lidSeamLeft, + x: points.lidSeamRight.x + 2 * sa, + }) + } + if (options.onePieceLid) part.hide() + return part +} + +export const twoPieceLidBottom = { + name: 'twoPieceLidBottom', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + onePieceLid: { bool: false, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftTwoPieceLidBottom, +} diff --git a/designs/magde/src/twoPieceLidTop.mjs b/designs/magde/src/twoPieceLidTop.mjs new file mode 100644 index 00000000000..46460f38749 --- /dev/null +++ b/designs/magde/src/twoPieceLidTop.mjs @@ -0,0 +1,117 @@ +import { pluginBundle } from '@freesewing/plugin-bundle' + +function draftTwoPieceLidTop({ + options, + Point, + Path, + Snippet, + points, + paths, + complete, + sa, + snippets, + paperless, + macro, + part, +}) { + // Width is halved as this is cut on a fold + const width = (options.size * 500) / 2 + const height = options.size * 300 + const taperWidth = width * options.taperRatio + const lidFlapHeight = height * options.flapHeightRatio + const lidFlapWidth = taperWidth * 0.8 + const openingWidth = taperWidth * options.openingRatio + points.origin = new Point(0, 0) + points.lidTopRight = new Point(lidFlapWidth, 0) + points.lidBottomRight = new Point(width, lidFlapHeight) + points.lidBottomLeft = new Point(0, lidFlapHeight) + points.lidSeamRight = points.lidTopRight.shiftFractionTowards(points.lidBottomRight, 0.2) + points.lidSeamLeft = new Point(0, points.lidSeamRight.y) + + paths.seam = new Path() + .move(points.lidBottomLeft) + .line(points.lidBottomRight) + .line(points.lidSeamRight) + .line(points.lidSeamLeft) + .close() + .attr('class', 'fabric') + + // Complete? + if (complete) { + macro('cutonfold', { + from: points.lidSeamLeft, + to: points.lidBottomLeft, + }) + + points.label = new Point(lidFlapWidth / 2, lidFlapHeight / 2) + + macro('title', { + at: points.label, + title: 'Lid Top - Two Piece', + nr: '3.1', + }) + points.notchPoint = new Point((openingWidth + lidFlapWidth) / 2, points.lidSeamLeft.y).addText( + 'Webbing Notch', + 'center' + ) + snippets.webbingNotch = new Snippet('bnotch', points.notchPoint) + + if (sa) { + paths.topSa = new Path() + .move(points.lidSeamRight) + .join( + new Path() + .move(points.lidSeamRight) + .line(points.lidSeamLeft) + .offset(2 * sa) + ) + .setClass('fabric sa') + paths.bottomSa = new Path() + .move(points.lidBottomLeft) + .line(points.lidBottomRight) + .offset(2 * sa) + .line(points.lidBottomRight) + .setClass('fabric sa') + } + } + + // Paperless? + if (paperless) { + macro('hd', { + from: points.origin, + to: points.lidSeamRight, + y: points.lidSeamLeft.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidSeamRight, + to: points.lidBottomRight, + y: points.lidSeamLeft.y - 2 * sa - 15, + }) + macro('hd', { + from: points.lidBottomRight, + to: points.lidBottomLeft, + y: points.lidBottomLeft.y + 2 * sa + 15, + }) + macro('vd', { + from: points.lidSeamRight, + to: points.lidBottomRight, + x: points.lidBottomRight.x + 2 * sa, + }) + } + + if (options.onePieceLid) part.hide() + return part +} + +export const twoPieceLidTop = { + name: 'twoPieceLidTop', + options: { + size: { pct: 100, min: 15, max: 200, menu: 'style' }, + taperRatio: { pct: 60, min: 50, max: 100, menu: 'style' }, + flapHeightRatio: { pct: 83, min: 60, max: 100, menu: 'style' }, + openingRatio: { pct: 66, min: 30, max: 90, menu: 'style' }, + onePieceLid: { bool: false, menu: 'style' }, + }, + plugins: [pluginBundle], + draft: draftTwoPieceLidTop, +} diff --git a/designs/magde/tests/shared.test.mjs b/designs/magde/tests/shared.test.mjs new file mode 100644 index 00000000000..1d7256bd762 --- /dev/null +++ b/designs/magde/tests/shared.test.mjs @@ -0,0 +1,16 @@ +// This file is auto-generated | Any changes you make will be overwritten. +import { Magde } from '../src/index.mjs' + +// Shared tests +import { testPatternConfig } from '../../../tests/designs/config.mjs' +import { testPatternDrafting } from '../../../tests/designs/drafting.mjs' +import { testPatternSampling } from '../../../tests/designs/sampling.mjs' + +// Test config +testPatternConfig(Magde) + +// Test drafting - Change the second parameter to `true` to log errors +testPatternDrafting(Magde, false) + +// Test sampling - Change the second parameter to `true` to log errors +testPatternSampling(Magde, false)