feat(ursula): Initial release of Ursula
Ursula is a basic, highly-customizable underwear pattern
This commit is contained in:
parent
a3b37b060b
commit
cc00ec65ff
7 changed files with 727 additions and 0 deletions
51
packages/ursula/config/index.js
Normal file
51
packages/ursula/config/index.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { version } from '../package.json'
|
||||
|
||||
// ?? 🤔 ?? --> https://en.freesewing.dev/packages/core/config
|
||||
|
||||
export default {
|
||||
name: 'ursula',
|
||||
version,
|
||||
design: 'natalia',
|
||||
code: 'natalia',
|
||||
department: 'womenswear',
|
||||
type: 'pattern',
|
||||
difficulty: 1,
|
||||
tags: [
|
||||
'freesewing',
|
||||
'design',
|
||||
'diy',
|
||||
'fashion',
|
||||
'made to measure',
|
||||
'parametric design',
|
||||
'pattern',
|
||||
'sewing',
|
||||
'sewing pattern',
|
||||
],
|
||||
optionGroups: {
|
||||
fit: ['fabricStretch','gussetWidth','gussetLength','elasticStretch'],
|
||||
style: ['rise','legOpening','frontDip','backDip','taperToGusset','backExposure'],
|
||||
},
|
||||
measurements: ['waist','seat','waistToSeat','waistToUpperLeg'], // Potentially useful: 'hips', 'waistToHips'
|
||||
dependencies: {},
|
||||
inject: {},
|
||||
hide: [],
|
||||
parts: ['front','back','gusset','elastic'],
|
||||
//Constants
|
||||
options: {
|
||||
backToFrontLength: 1.15, // Maybe include this in advanced options?
|
||||
backToFrontWidth: 1.1, // Maybe include this in advanced options?
|
||||
gussetRatio: 0.7, // Relationship between front and back gusset widths
|
||||
|
||||
// Percentages
|
||||
gussetWidth: { pct : 7.7, min: 4, max: 12 }, // Gusset width in relation to seat
|
||||
gussetLength: { pct: 12.7, min: 10, max: 16 }, // Gusset length in relation to seat
|
||||
fabricStretch: { pct: 15, min: 5, max: 25 },
|
||||
rise: { pct: 60, min: 30, max: 100 },
|
||||
legOpening: { pct: 58, min: 5, max: 85 },
|
||||
frontDip: { pct: 5.0, min: -5, max: 15 },
|
||||
backDip: { pct: 2.5, min: -5, max: 15 },
|
||||
taperToGusset: { pct: 70, min: 5, max: 100},
|
||||
backExposure: { pct: 20, min: -30, max: 90},
|
||||
elasticStretch: { pct: 8, min: 5, max: 15 }
|
||||
},
|
||||
}
|
93
packages/ursula/package.json
Normal file
93
packages/ursula/package.json
Normal file
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"name": "@freesewing/ursula",
|
||||
"version": "2.16.2",
|
||||
"description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
|
||||
"author": "Joost De Cock <joost@joost.at> (https://github.com/joostdecock)",
|
||||
"homepage": "https://freesewing.org/",
|
||||
"repository": "github:freesewing/freesewing",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/freesewing/freesewing/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"freesewing",
|
||||
"design",
|
||||
"diy",
|
||||
"fashion",
|
||||
"made to measure",
|
||||
"parametric design",
|
||||
"pattern",
|
||||
"sewing",
|
||||
"sewing pattern"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"build": "rollup -c",
|
||||
"test": "BABEL_ENV=production ../../node_modules/.bin/_mocha tests/*.test.js --require @babel/register",
|
||||
"pubtest": "npm publish --registry http://localhost:6662",
|
||||
"pubforce": "npm publish",
|
||||
"symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -",
|
||||
"start": "rollup -c -w",
|
||||
"netlify": "echo \"Not configured yet\"",
|
||||
"testci": "BABEL_ENV=production ./node_modules/.bin/_mocha tests/*.test.js --require @babel/register"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@freesewing/core": "^2.16.2",
|
||||
"@freesewing/plugin-bundle": "^2.16.2"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^1.1.0",
|
||||
"@freesewing/components": "^2.16.2",
|
||||
"@freesewing/css-theme": "^2.16.2",
|
||||
"@freesewing/i18n": "^2.16.2",
|
||||
"@freesewing/mui-theme": "^2.16.2",
|
||||
"@freesewing/plugin-bust": "^2.16.2",
|
||||
"@freesewing/plugin-buttons": "^2.16.2",
|
||||
"@freesewing/plugin-flip": "^2.16.2",
|
||||
"@freesewing/utils": "^2.16.2",
|
||||
"react-scripts": "^4.0.3",
|
||||
"webpack": "^5.37.0",
|
||||
"rollup": "^2.50.6",
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"@rollup/plugin-commonjs": "^19.0.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.0",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.4",
|
||||
"@material-ui/core": "^4.11.4",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "^v4.0.0-alpha.57",
|
||||
"axios": "0.21.1",
|
||||
"react-intl": "^5.17.6",
|
||||
"prop-types": "^15.7.2",
|
||||
"mocha": "^8.1.0",
|
||||
"chai": "^4.2.0",
|
||||
"chai-string": "^1.5.0",
|
||||
"@babel/register": "^7.10.5"
|
||||
},
|
||||
"files": [
|
||||
"dist/*",
|
||||
"README.md",
|
||||
"package.json"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"tag": "latest"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0",
|
||||
"npm": ">=6"
|
||||
},
|
||||
"rollup": {
|
||||
"exports": "default"
|
||||
}
|
||||
}
|
240
packages/ursula/src/back.js
Normal file
240
packages/ursula/src/back.js
Normal file
|
@ -0,0 +1,240 @@
|
|||
export default function (part) {
|
||||
let {
|
||||
options,
|
||||
Point,
|
||||
Path,
|
||||
points,
|
||||
paths,
|
||||
measurements,
|
||||
// Snippet,
|
||||
// snippets,
|
||||
store,
|
||||
utils,
|
||||
complete,
|
||||
sa,
|
||||
paperless,
|
||||
macro,
|
||||
} = part.shorthand()
|
||||
|
||||
// Design pattern here
|
||||
|
||||
// Create points
|
||||
|
||||
points.backWaistMid = new Point(measurements.seat / 4, 0)
|
||||
points.backWaistBandLeft = new Point(store.get('sideSeamWaist').x / options.backToFrontWidth, store.get('sideSeamWaist').y)
|
||||
points.backLegOpeningLeft = new Point(store.get('sideSeamHip').x / options.backToFrontWidth, store.get('sideSeamHip').y)
|
||||
points.backGussetLeft = new Point(
|
||||
(measurements.seat / 4) - (measurements.waist * options.gussetWidth) * store.get('xScale') / options.gussetRatio * options.backToFrontWidth,
|
||||
measurements.waistToUpperLeg * options.backToFrontLength
|
||||
)
|
||||
points.backGussetMid = new Point(measurements.seat / 4, measurements.waistToUpperLeg * options.backToFrontLength)
|
||||
|
||||
points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid)
|
||||
points.backLegOpeningRight = points.backLegOpeningLeft.flipX(points.backWaistMid)
|
||||
points.backWaistBandRight = points.backWaistBandLeft.flipX(points.backWaistMid)
|
||||
|
||||
points.backWaistBandMid = points.backWaistBandLeft.shiftFractionTowards(points.backWaistBandRight, 0.5)
|
||||
.shift(270,measurements.waistToUpperLeg * options.backDip)
|
||||
|
||||
/* Middle point for label */
|
||||
points.backMidMid = points.backLegOpeningLeft.shiftFractionTowards(points.backLegOpeningRight, 0.5)
|
||||
|
||||
|
||||
// Create control points
|
||||
|
||||
/* Control point for waistband dip */
|
||||
points.backWaistBandLeftCp1 = new Point(points.backWaistBandRight.x / 3, points.backWaistBandMid.y)
|
||||
|
||||
/* Flip points to right side */
|
||||
points.backWaistBandRightCp1 = points.backWaistBandLeftCp1.flipX(points.backWaistMid)
|
||||
|
||||
// Shape back coverage
|
||||
|
||||
/* Only have to do this on one side */
|
||||
points.backLegOpeningCorner = utils.beamsIntersect(
|
||||
points.backLegOpeningLeft,
|
||||
points.backLegOpeningLeft.shift(180, points.backGussetLeft.dy(points.backLegOpeningLeft)),
|
||||
points.backGussetLeft,
|
||||
points.backGussetLeft.shift(270, points.backGussetLeft.dy(points.backLegOpeningLeft))
|
||||
)
|
||||
|
||||
if (options.backExposure >= 0) {
|
||||
/* If back exposure is high, like a thong style */
|
||||
/* This controls the hip bit */
|
||||
points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shiftFractionTowards(
|
||||
points.backLegOpeningCorner,
|
||||
options.backExposure
|
||||
)
|
||||
/* This controls the center bit */
|
||||
points.backGussetLeftCp1 = points.backGussetLeft.shiftFractionTowards(
|
||||
points.backWaistBandMid,
|
||||
options.backExposure
|
||||
)
|
||||
points.backGussetLeft = points.backGussetLeft.shiftFractionTowards(points.backGussetMid, options.backExposure) // This narrows the back of the gusset
|
||||
points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid)
|
||||
} else {
|
||||
/* If back exposure is low and flares out to cover more */
|
||||
/* This controls the hip bit */
|
||||
points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shift(
|
||||
-45,
|
||||
points.backWaistBandMid.x / 8
|
||||
)
|
||||
/* This controls the taper to gusset */
|
||||
points.backGussetLeftCp1 = points.backGussetLeft.shift(
|
||||
115,
|
||||
points.backWaistBandMid.x / 8
|
||||
)
|
||||
/* This adds a new point in the middle of the back coverage */
|
||||
points.backFlare = points.backGussetLeft.shiftFractionTowards(
|
||||
points.backLegOpeningLeft,
|
||||
0.5
|
||||
)
|
||||
points.backFlareLeft = points.backFlare.shift(
|
||||
215,
|
||||
-points.backWaistBandMid.x / 2 * options.backExposure
|
||||
)
|
||||
points.backFlareRight = points.backFlareLeft.flipX(points.backWaistBandMid)
|
||||
/* This controls the flare */
|
||||
points.backFlareLeftCp1 = points.backFlareLeft.shift(
|
||||
115,
|
||||
points.backWaistBandMid.x / 5//-150*options.backExposure
|
||||
)
|
||||
points.backFlareLeftCp2 = points.backFlareLeft.shift(
|
||||
295,
|
||||
points.backWaistBandMid.x / 5//-150*options.backExposure
|
||||
)
|
||||
points.backFlareRightCp1 = points.backFlareLeftCp1.flipX(points.backWaistMid)
|
||||
points.backFlareRightCp2 = points.backFlareLeftCp2.flipX(points.backWaistMid)
|
||||
}
|
||||
|
||||
/* Flip points to the right */
|
||||
|
||||
points.backLegOpeningRightCp1 = points.backLegOpeningLeftCp1.flipX(points.backWaistMid)
|
||||
points.backGussetRightCp1 = points.backGussetLeftCp1.flipX(points.backWaistMid)
|
||||
|
||||
// Draw paths
|
||||
|
||||
if (options.backExposure >= 0) {
|
||||
paths.seam = new Path()
|
||||
.move(points.backWaistBandMid)
|
||||
.curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip
|
||||
.line(points.backLegOpeningLeft)
|
||||
.curve(points.backLegOpeningLeftCp1, points.backGussetLeftCp1, points.backGussetLeft)
|
||||
.line(points.backGussetMid)
|
||||
.line(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
|
||||
.line(points.backWaistBandRight)
|
||||
.curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
} else {
|
||||
paths.seam = new Path()
|
||||
.move(points.backWaistBandMid)
|
||||
.curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip
|
||||
.line(points.backLegOpeningLeft)
|
||||
.curve(points.backLegOpeningLeftCp1, points.backFlareLeftCp1, points.backFlareLeft)
|
||||
.curve(points.backFlareLeftCp2, points.backGussetLeftCp1, points.backGussetLeft)
|
||||
.line(points.backGussetMid)
|
||||
.line(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
|
||||
.curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
|
||||
.line(points.backWaistBandRight)
|
||||
.curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
}
|
||||
|
||||
// Store points for use in other parts
|
||||
|
||||
/* Store gusset points for use in gusset */
|
||||
|
||||
store.set('backGussetLeft', points.backGussetLeft)
|
||||
store.set('backGussetRight', points.backGussetRight)
|
||||
|
||||
/* Store lengths for use in elastic */
|
||||
|
||||
if (options.backExposure >= 0 ) {
|
||||
store.set(
|
||||
'backLegOpeningLength',
|
||||
new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
|
||||
.length()
|
||||
)
|
||||
} else {
|
||||
store.set(
|
||||
'backLegOpeningLength',
|
||||
new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
|
||||
.curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight),
|
||||
)
|
||||
}
|
||||
|
||||
store.set(
|
||||
'backWaistBandLength',
|
||||
new Path()
|
||||
.move(points.backWaistBandRight)
|
||||
.curve(points.backWaistBandRightCp1, points.backWaistBandLeftCp1, points.backWaistBandLeft)
|
||||
.length()
|
||||
)
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
|
||||
if (sa) {
|
||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
}
|
||||
}
|
||||
|
||||
macro('title', {
|
||||
at: points.backMidMid,
|
||||
nr: 2,
|
||||
title: 'back',
|
||||
})
|
||||
|
||||
points.scaleboxAnchor = points.scalebox = points.backMidMid.shift(90, -50)
|
||||
macro('miniscale', { at: points.scalebox })
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.backWaistBandRight,
|
||||
to: points.backWaistBandLeft,
|
||||
y: points.backWaistBandRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.backLegOpeningRight,
|
||||
to: points.backLegOpeningLeft,
|
||||
y: points.backLegOpeningRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.backGussetLeft,
|
||||
to: points.backGussetRight,
|
||||
y: points.backGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.backWaistBandMid,
|
||||
to: points.backGussetMid,
|
||||
x: points.backWaistBandMid.x + sa + 15,
|
||||
})
|
||||
if (options.backExposure >= 0 ) {
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight),
|
||||
d: 15
|
||||
})
|
||||
} else {
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
|
||||
.curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight),
|
||||
d: 15
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
56
packages/ursula/src/elastic.js
Normal file
56
packages/ursula/src/elastic.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
export default function (part) {
|
||||
let {
|
||||
options,
|
||||
Point,
|
||||
Path,
|
||||
points,
|
||||
paths,
|
||||
measurements,
|
||||
// Snippet,
|
||||
// snippets,
|
||||
store,
|
||||
utils,
|
||||
units,
|
||||
complete,
|
||||
sa,
|
||||
paperless,
|
||||
macro,
|
||||
} = part.shorthand()
|
||||
|
||||
// Stretch utility method
|
||||
|
||||
store.set('elasticScale', utils.stretchToScale(options.elasticStretch))
|
||||
|
||||
// Design pattern here
|
||||
|
||||
let legOpeningLength = store.get('frontLegOpeningLength') + store.get('backLegOpeningLength') + store.get('gussetSideLength')
|
||||
let waistBandLength = store.get('frontWaistBandLength') + store.get('backWaistBandLength')
|
||||
|
||||
points.elasticInfo = new Point(0,0)
|
||||
.attr('data-text', 'cutTwoPiecesOfElasticToFinishTheLegOpenings')
|
||||
.attr('data-text', ':')
|
||||
.attr('data-text', units(legOpeningLength * store.get('elasticScale') + 2 * sa))
|
||||
.attr('data-text', '\n')
|
||||
.attr('data-text', 'cutOnePieceOfElasticToFinishTheWaistBand')
|
||||
.attr('data-text', ':')
|
||||
.attr('data-text', units(waistBandLength * store.get('elasticScale') + 2 * sa))
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
|
||||
// if (sa) {
|
||||
// paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
// }
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.elasticInfo,
|
||||
to: points.elasticInfo,
|
||||
y: points.elasticInfo.y + sa + 15,
|
||||
})
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
174
packages/ursula/src/front.js
Normal file
174
packages/ursula/src/front.js
Normal file
|
@ -0,0 +1,174 @@
|
|||
export default function (part) {
|
||||
let {
|
||||
options,
|
||||
Point,
|
||||
Path,
|
||||
points,
|
||||
paths,
|
||||
measurements,
|
||||
// Snippet,
|
||||
// snippets,
|
||||
store,
|
||||
utils,
|
||||
complete,
|
||||
sa,
|
||||
paperless,
|
||||
macro,
|
||||
} = part.shorthand()
|
||||
|
||||
// Stretch utility method
|
||||
|
||||
store.set('xScale', utils.stretchToScale(options.fabricStretch))
|
||||
|
||||
// Design pattern here
|
||||
|
||||
// Create points
|
||||
|
||||
points.frontWaistMid = new Point(measurements.seat / 4, 0)
|
||||
points.frontWaistLeft = new Point(measurements.seat / 4 - measurements.waist / 4 * store.get('xScale'), 0)
|
||||
points.frontHipLeft = new Point(measurements.seat / 4 - measurements.seat / 4 * store.get('xScale'), measurements.waistToSeat) // Consider renaming from "hip" to "seat"
|
||||
points.frontGussetLeft = new Point((measurements.seat / 4) - (measurements.waist * options.gussetWidth) * store.get('xScale') / 1.2, measurements.waistToUpperLeg)
|
||||
points.frontGussetMid = new Point(measurements.seat / 4, measurements.waistToUpperLeg)
|
||||
|
||||
/* Flip points to right side */
|
||||
points.frontGussetRight = points.frontGussetLeft.flipX(points.frontWaistMid)
|
||||
points.frontHipRight = points.frontHipLeft.flipX(points.frontWaistMid)
|
||||
points.frontWaistRight = points.frontWaistLeft.flipX(points.frontWaistMid)
|
||||
|
||||
/* Waist band is based on waist at top, hip at bottom */
|
||||
points.frontWaistBandLeft = points.frontHipLeft.shiftFractionTowards(points.frontWaistLeft, options.rise)
|
||||
points.frontWaistBandRight = points.frontWaistBandLeft.flipX(points.frontWaistMid)
|
||||
points.frontWaistBandMid = points.frontWaistBandLeft.shiftFractionTowards(points.frontWaistBandRight, 0.5)
|
||||
.shift(270,measurements.waistToUpperLeg * options.frontDip) /* Waist band dip */
|
||||
|
||||
/* Leg opening is based on waist band and hip */
|
||||
// points.frontLegOpeningLeft = points.frontHipLeft.shiftFractionTowards(points.frontWaistBandLeft, options.legOpening) // Waist band side point
|
||||
// points.frontLegOpeningRight = points.frontLegOpeningLeft.flipX(points.frontWaistMid) // Waist band side point
|
||||
|
||||
///////////// Replace the point it's shifting towards with a beamsIntersect() of the
|
||||
///////////// side (frontWaistLeft and frontHipLeft) and the lowest point of the waistband (backWaistBandMid
|
||||
///////////// and backWaistBandLeftCp1 should work)
|
||||
///////////// or maybe beamIntersectsY() of backWaistBandMid.y ??
|
||||
|
||||
points.frontLegOpeningLeft = points.frontHipLeft.shiftFractionTowards(points.frontWaistBandLeft, options.legOpening) // Waist band low point
|
||||
points.frontLegOpeningRight = points.frontLegOpeningLeft.flipX(points.frontWaistMid) // Waist band low point
|
||||
|
||||
/* Middle point for label */
|
||||
points.frontMidMid = points.frontLegOpeningLeft.shiftFractionTowards(points.frontLegOpeningRight, 0.5)
|
||||
|
||||
// Create control points
|
||||
|
||||
/* Control points for leg opening curves */
|
||||
points.frontLegOpeningLeftCp1 = points.frontLegOpeningLeft
|
||||
.shift(180, points.frontGussetLeft.dy(points.frontLegOpeningLeft)/3);
|
||||
points.frontGussetLeftCp1 = points.frontGussetLeft
|
||||
// .shift(270, points.frontGussetLeft.dy(points.frontHipLeft) * 4 * options.taperToGusset); // Consider changing this so it's relative
|
||||
.shift(270, points.frontGussetLeft.dy(points.frontWaistBandMid) * options.taperToGusset);
|
||||
|
||||
/* Control point for waistband dip */
|
||||
points.frontWaistBandLeftCp1 = new Point(points.frontWaistBandRight.x / 3, points.frontWaistBandMid.y)
|
||||
|
||||
/* Flip control points to right side */
|
||||
points.frontGussetRightCp1 = points.frontGussetLeftCp1.flipX(points.frontWaistMid)
|
||||
points.frontLegOpeningRightCp1 = points.frontLegOpeningLeftCp1.flipX(points.frontWaistMid)
|
||||
points.frontWaistBandRightCp1 = points.frontWaistBandLeftCp1.flipX(points.frontWaistMid)
|
||||
|
||||
// Draw paths
|
||||
|
||||
paths.seam = new Path()
|
||||
.move(points.frontWaistBandMid)
|
||||
.curve(points.frontWaistBandLeftCp1, points.frontWaistBandLeft, points.frontWaistBandLeft) // Waist band dip
|
||||
.line(points.frontLegOpeningLeft)
|
||||
.curve(points.frontLegOpeningLeftCp1, points.frontGussetLeftCp1, points.frontGussetLeft)
|
||||
.line(points.frontGussetMid)
|
||||
.line(points.frontGussetRight)
|
||||
.curve(points.frontGussetRightCp1, points.frontLegOpeningRightCp1, points.frontLegOpeningRight)
|
||||
.line(points.frontWaistBandRight)
|
||||
.curve(points.frontWaistBandRight, points.frontWaistBandRightCp1, points.frontWaistBandMid) // Waist band dip
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
// Store points for use in other parts
|
||||
|
||||
/* Store side seam points for use in back */
|
||||
|
||||
store.set('sideSeamWaist', points.frontWaistBandLeft)
|
||||
store.set('sideSeamHip', points.frontLegOpeningLeft)
|
||||
|
||||
/* Store gusset points for use in gusset */
|
||||
|
||||
store.set('frontGussetLeft', points.frontGussetLeft)
|
||||
store.set('frontGussetRight', points.frontGussetRight)
|
||||
store.set('frontGussetMid', points.frontGussetMid)
|
||||
|
||||
/* Store lengths for use in elastic */
|
||||
|
||||
store.set(
|
||||
'frontLegOpeningLength',
|
||||
new Path()
|
||||
.move(points.frontGussetRight)
|
||||
.curve(points.frontGussetRightCp1, points.frontLegOpeningRightCp1, points.frontLegOpeningRight)
|
||||
.length()
|
||||
)
|
||||
store.set(
|
||||
'frontWaistBandLength',
|
||||
new Path()
|
||||
.move(points.frontWaistBandRight)
|
||||
.curve(points.frontWaistBandRightCp1, points.frontWaistBandLeftCp1, points.frontWaistBandLeft)
|
||||
.length()
|
||||
)
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
|
||||
if (sa) {
|
||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
}
|
||||
}
|
||||
macro('title', {
|
||||
at: points.frontMidMid,
|
||||
nr: 1,
|
||||
title: 'front',
|
||||
})
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.frontWaistBandRight,
|
||||
to: points.frontWaistBandLeft,
|
||||
y: points.frontWaistBandRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.frontLegOpeningRight,
|
||||
to: points.frontLegOpeningLeft,
|
||||
y: points.frontLegOpeningRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.frontGussetLeft,
|
||||
to: points.frontGussetRight,
|
||||
y: points.frontGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.frontWaistBandMid,
|
||||
to: points.frontGussetMid,
|
||||
x: points.frontWaistBandMid.x + sa + 15,
|
||||
})
|
||||
macro('ld', {
|
||||
from: points.frontWaistBandLeft,
|
||||
to: points.frontLegOpeningLeft,
|
||||
d: points.frontWaistBandLeft.y + sa - 15
|
||||
})
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.frontGussetRight)
|
||||
.curve(points.frontGussetRightCp1, points.frontLegOpeningRightCp1, points.frontLegOpeningRight),
|
||||
d: 15
|
||||
})
|
||||
/* macro('vd', {
|
||||
from: points.frontWaistBandLeft,
|
||||
to: points.frontWaistBandMid,
|
||||
x: points.frontWaistBandMid.x + sa + 15,
|
||||
}) */
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
95
packages/ursula/src/gusset.js
Normal file
95
packages/ursula/src/gusset.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
export default function (part) {
|
||||
let {
|
||||
options,
|
||||
Point,
|
||||
Path,
|
||||
points,
|
||||
paths,
|
||||
measurements,
|
||||
// Snippet,
|
||||
// snippets,
|
||||
store,
|
||||
utils,
|
||||
complete,
|
||||
sa,
|
||||
paperless,
|
||||
macro,
|
||||
} = part.shorthand()
|
||||
|
||||
// Design pattern here
|
||||
|
||||
// Create points
|
||||
|
||||
points.frontGussetLeft = new Point(store.get('frontGussetLeft').x, 0)
|
||||
points.backGussetLeft = new Point(store.get('backGussetLeft').x, measurements.seat * options.gussetLength)
|
||||
points.frontGussetRight = new Point(store.get('frontGussetRight').x, 0)
|
||||
points.backGussetRight = new Point(store.get('backGussetRight').x, measurements.seat * options.gussetLength)
|
||||
|
||||
// Create control points
|
||||
|
||||
points.gussetCp1 = points.frontGussetLeft.shiftFractionTowards(points.backGussetLeft, 0.5)
|
||||
.shift(180,points.frontGussetRight.x / -15)
|
||||
|
||||
// Flip points to right side
|
||||
|
||||
points.gussetCp2 = points.gussetCp1.flipX(store.get('frontGussetMid'))
|
||||
|
||||
// Create point for title
|
||||
|
||||
points.frontMidMid = points.gussetCp1.shiftFractionTowards(points.gussetCp2, 0.5)
|
||||
|
||||
/* Store lengths for use in elastic */
|
||||
|
||||
store.set(
|
||||
'gussetSideLength',
|
||||
new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight)
|
||||
.length()
|
||||
)
|
||||
|
||||
// Draw paths
|
||||
|
||||
paths.seam = new Path()
|
||||
.move(points.frontGussetLeft)
|
||||
.curve(points.gussetCp1, points.backGussetLeft, points.backGussetLeft)
|
||||
.line(points.backGussetRight)
|
||||
.curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight)
|
||||
.line(points.frontGussetLeft) // Without this, doesn't generate seam allowance
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
|
||||
if (sa) {
|
||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
}
|
||||
}
|
||||
macro('title', {
|
||||
at: points.frontMidMid,
|
||||
nr: 3,
|
||||
title: 'gusset',
|
||||
})
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.frontGussetLeft,
|
||||
to: points.frontGussetRight,
|
||||
y: points.frontGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.backGussetLeft,
|
||||
to: points.backGussetRight,
|
||||
y: points.backGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.frontGussetRight,
|
||||
to: points.backGussetRight,
|
||||
x: points.frontGussetRight.x + sa + 15,
|
||||
})
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
18
packages/ursula/src/index.js
Normal file
18
packages/ursula/src/index.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import freesewing from '@freesewing/core'
|
||||
import plugins from '@freesewing/plugin-bundle'
|
||||
import config from '../config'
|
||||
import draftFront from './front'
|
||||
import draftBack from './back'
|
||||
import draftGusset from './gusset'
|
||||
import draftElastic from './elastic'
|
||||
|
||||
// Create new design
|
||||
const Pattern = new freesewing.Design(config, plugins)
|
||||
|
||||
// Attach the draft methods to the prototype
|
||||
Pattern.prototype.draftFront = draftFront
|
||||
Pattern.prototype.draftBack = draftBack
|
||||
Pattern.prototype.draftGusset = draftGusset
|
||||
Pattern.prototype.draftElastic = draftElastic
|
||||
|
||||
export default Pattern
|
Loading…
Add table
Add a link
Reference in a new issue