wip(charlie): First fit-test
This commit is contained in:
parent
d2fcf4e1bf
commit
b5f810e062
10 changed files with 771 additions and 102 deletions
|
@ -20,9 +20,17 @@ export default {
|
|||
'backPocketWidth',
|
||||
'backPocketDepth'
|
||||
],
|
||||
frontPockets: ['frontPocketSlantDepth', 'frontPocketSlantWidth']
|
||||
frontPockets: [
|
||||
'frontPocketSlantDepth',
|
||||
'frontPocketSlantWidth',
|
||||
'frontPocketOpening',
|
||||
'frontPocketEntry',
|
||||
'frontPocketWidth',
|
||||
'frontPocketDepth'
|
||||
]
|
||||
}
|
||||
],
|
||||
waistband: ['splitWaistband', 'waistbandWidth'],
|
||||
advanced: [
|
||||
'crossSeamCurveStart',
|
||||
'crossSeamCurveBend',
|
||||
|
@ -53,7 +61,16 @@ export default {
|
|||
hide: ['titanBack', 'titanFront'],
|
||||
inject: {
|
||||
back: 'titanBack',
|
||||
front: 'titanFront'
|
||||
front: 'titanFront',
|
||||
frontPocket: 'front'
|
||||
},
|
||||
parts: ['backPocket', 'backPocketFacing'],
|
||||
dependencies: {
|
||||
// The inheritance makes this a bit messy
|
||||
back: ['titanBack', 'titanFront', 'front'],
|
||||
waistband: ['titanBack', 'titanFront', 'front', 'back'],
|
||||
waistbandButtonSide: 'waistband',
|
||||
waistbandButtonholeSide: 'waistband'
|
||||
},
|
||||
options: {
|
||||
// Constants (from Titan)
|
||||
|
@ -67,6 +84,7 @@ export default {
|
|||
|
||||
// Charlie constants
|
||||
waistbandReduction: 0.3, // See src/index.js
|
||||
waistbandFactor: 0.1,
|
||||
|
||||
// Fit (from Titan)
|
||||
waistEase: { pct: 3, min: 0, max: 10 },
|
||||
|
@ -91,20 +109,27 @@ export default {
|
|||
backPocketVerticalPlacement: { pct: 24, min: 18, max: 30 },
|
||||
backPocketHorizontalPlacement: { pct: 55, min: 48, max: 62 },
|
||||
backPocketWidth: { pct: 55, min: 50, max: 60 },
|
||||
backPocketDepth: { pct: 20, min: 10, max: 40 },
|
||||
backPocketDepth: { pct: 60, min: 40, max: 80 },
|
||||
backPocketFacing: { bool: true },
|
||||
|
||||
// Back pockets
|
||||
// Front pockets
|
||||
frontPocketSlantDepth: { pct: 75, min: 50, max: 100 },
|
||||
frontPocketSlantWidth: { pct: 20, min: 10, max: 30 },
|
||||
frontPocketOpening: { pct: 80, min: 60, max: 90 },
|
||||
frontPocketEntry: { pct: 20, min: 10, max: 30 },
|
||||
frontPocketWidth: { pct: 55, min: 45, max: 65 },
|
||||
frontPocketDepth: { pct: 100, min: 85, max: 110 },
|
||||
|
||||
// Belt
|
||||
waistbandWidth: { mm: 25, min: 5, max: 45 },
|
||||
|
||||
// Advanced - Fly
|
||||
// Fly
|
||||
flyCurve: { pct: 66, min: 50, max: 100 },
|
||||
flyLength: { pct: 35, min: 0, max: 70 },
|
||||
flyWidth: { pct: 15, min: 10, max: 20 }
|
||||
flyWidth: { pct: 15, min: 10, max: 20 },
|
||||
|
||||
// Pockets
|
||||
// Waistband
|
||||
splitWaistband: { bool: true },
|
||||
waistbandWidth: { pct: 50, min: 25, max: 75 }
|
||||
}
|
||||
}
|
||||
|
|
73
packages/charlie/src/back-pocket-facing.js
Normal file
73
packages/charlie/src/back-pocket-facing.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
export default (part) => {
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
Point,
|
||||
paths,
|
||||
Path,
|
||||
measurements,
|
||||
options,
|
||||
complete,
|
||||
paperless,
|
||||
store,
|
||||
macro,
|
||||
utils,
|
||||
snippets,
|
||||
Snippet,
|
||||
sa
|
||||
} = part.shorthand()
|
||||
|
||||
points.leftNotch = new Point(store.get('backPocketWidth') / -2, 0)
|
||||
points.rightNotch = points.leftNotch.flipX()
|
||||
points.topLeft = new Point(points.leftNotch.x * 1.2, store.get('backPocketToWaistband') * -1)
|
||||
points.topRight = points.topLeft.flipX()
|
||||
points.bottomLeft = new Point(points.leftNotch.x * 1.2, points.rightNotch.x * 0.6)
|
||||
points.bottomRight = points.bottomLeft.flipX()
|
||||
|
||||
paths.saBase = new Path()
|
||||
.move(points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.line(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.setRender(false)
|
||||
paths.seam = paths.saBase
|
||||
.clone()
|
||||
.line(points.bottomRight)
|
||||
.close()
|
||||
.setRender(true)
|
||||
.attr('class', 'fabric')
|
||||
|
||||
if (complete) {
|
||||
paths.opening = new Path()
|
||||
.move(points.leftNotch)
|
||||
.line(points.rightNotch)
|
||||
.attr('class', 'dashed')
|
||||
points.titleAnchor = new Point(0, 0)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: '5b',
|
||||
title: 'pocketFacing'
|
||||
})
|
||||
points.grainlineTop = points.topLeft.shiftFractionTowards(points.topRight, 0.15)
|
||||
points.grainlineBottom = points.bottomLeft.shiftFractionTowards(points.bottomRight, 0.15)
|
||||
macro('grainline', {
|
||||
from: points.grainlineTop,
|
||||
to: points.grainlineBottom
|
||||
})
|
||||
|
||||
if (sa) {
|
||||
let saBase = paths.saBase.offset(sa)
|
||||
paths.sa = new Path()
|
||||
.move(points.bottomRight)
|
||||
.line(saBase.start())
|
||||
.join(saBase)
|
||||
.line(points.bottomLeft)
|
||||
.attr('class', 'sa fabric')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
79
packages/charlie/src/back-pocket.js
Normal file
79
packages/charlie/src/back-pocket.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
export default (part) => {
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
Point,
|
||||
paths,
|
||||
Path,
|
||||
measurements,
|
||||
options,
|
||||
complete,
|
||||
paperless,
|
||||
store,
|
||||
macro,
|
||||
utils,
|
||||
snippets,
|
||||
Snippet,
|
||||
sa
|
||||
} = part.shorthand()
|
||||
|
||||
//store.set('backPocketToWaistband', base * options.backPocketVerticalPlacement)
|
||||
//store.set('backPocketWidth', base * options.backPocketWidth)
|
||||
//store.set('backPocketDepth', base * options.backPocketDepth)
|
||||
|
||||
points.leftNotch = new Point(store.get('backPocketWidth') / -2, 0)
|
||||
points.rightNotch = points.leftNotch.flipX()
|
||||
points.waistbandLeft = new Point(
|
||||
points.leftNotch.x * 1.2,
|
||||
store.get('backPocketToWaistband') * -1
|
||||
)
|
||||
points.waistbandRight = points.waistbandLeft.flipX()
|
||||
points.foldLeft = new Point(
|
||||
points.waistbandLeft.x,
|
||||
points.leftNotch.y + store.get('backPocketDepth')
|
||||
)
|
||||
points.foldRight = points.foldLeft.flipX()
|
||||
points.bottomLeft = new Point(
|
||||
points.waistbandLeft.x,
|
||||
points.foldLeft.y + store.get('backPocketDepth')
|
||||
)
|
||||
points.bottomRight = points.bottomLeft.flipX()
|
||||
|
||||
paths.seam = new Path()
|
||||
.move(points.waistbandRight)
|
||||
.line(points.waistbandLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.waistbandRight)
|
||||
.close()
|
||||
.attr('class', 'lining')
|
||||
|
||||
if (complete) {
|
||||
paths.opening = new Path()
|
||||
.move(points.leftNotch)
|
||||
.line(points.rightNotch)
|
||||
.attr('class', 'dashed')
|
||||
paths.fold = new Path().move(points.foldLeft).line(points.foldRight).attr('class', 'help')
|
||||
points.titleAnchor = points.rightNotch.shiftFractionTowards(points.foldLeft, 0.5)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: 5,
|
||||
title: 'pocketBag'
|
||||
})
|
||||
points.logoAnchor = points.foldLeft.shiftFractionTowards(points.bottomRight, 0.5)
|
||||
snippets.logo = new Snippet('logo', points.logoAnchor)
|
||||
points.grainlineTop = points.waistbandLeft.shiftFractionTowards(points.waistbandRight, 0.15)
|
||||
points.grainlineBottom = points.bottomLeft.shiftFractionTowards(points.bottomRight, 0.15)
|
||||
macro('grainline', {
|
||||
from: points.grainlineTop,
|
||||
to: points.grainlineBottom
|
||||
})
|
||||
|
||||
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'lining sa')
|
||||
|
||||
if (paperless) {
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
|
@ -1,40 +1,25 @@
|
|||
export default (part) => {
|
||||
|
||||
/*
|
||||
* Helper method to draw the inseam path
|
||||
*/
|
||||
const drawInseam = () =>
|
||||
options.fitKnee
|
||||
? new Path()
|
||||
.move(points.fork)
|
||||
.curve(points.forkCp2, points.kneeInCp1, points.kneeIn)
|
||||
.line(points.floorIn)
|
||||
: new Path().move(points.fork).curve(points.forkCp2, points.kneeInCp1, points.floorIn)
|
||||
/*
|
||||
* Helper method to draw the outseam path
|
||||
*/
|
||||
// Helper method to draw the outseam path
|
||||
const drawOutseam = () => {
|
||||
let waistOut = points.styleWaistOut || points.waistOut
|
||||
if (options.fitKnee) {
|
||||
if (points.waistOut.x > points.seatOut.x)
|
||||
return new Path()
|
||||
.move(points.floorOut)
|
||||
.line(points.kneeOut)
|
||||
.curve(points.kneeOutCp2, points.seatOut, waistOut)
|
||||
else
|
||||
return new Path()
|
||||
.move(points.floorOut)
|
||||
.line(points.kneeOut)
|
||||
.curve(points.kneeOutCp2, points.seatOutCp1, points.seatOut)
|
||||
.curve_(points.seatOutCp2, points.waistOut)
|
||||
if (points.waistOut.x > points.seatOut.x) {
|
||||
let outseam = new Path()
|
||||
.move(points.styleWaistOut)
|
||||
.curve(points.seatOut, points.kneeOutCp2, points.floorOut)
|
||||
return new Path()
|
||||
.move(points.slantOut)
|
||||
.line(points.pocketOpeningTop)
|
||||
.line(points.pocketOpeningTopIn)
|
||||
.line(points.pocketOpeningBottomIn)
|
||||
.line(points.pocketOpeningBottom)
|
||||
.line(points.slantBottom)
|
||||
.join(outseam.split(points.slantBottom).pop())
|
||||
.reverse()
|
||||
} else {
|
||||
if (points.waistOut.x > points.seatOut.x)
|
||||
return new Path().move(points.floorOut).curve(points.kneeOutCp2, points.seatOut, waistOut)
|
||||
else
|
||||
return new Path()
|
||||
.move(points.floorOut)
|
||||
.curve(points.kneeOutCp2, points.seatOutCp1, points.seatOut)
|
||||
.curve_(points.seatOutCp2, waistOut)
|
||||
return new Path()
|
||||
.move(points.floorOut)
|
||||
.curve(points.kneeOutCp2, points.seatOutCp1, points.seatOut)
|
||||
.curve_(points.seatOutCp2, waistOut)
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -42,19 +27,16 @@ export default (part) => {
|
|||
*/
|
||||
const drawPath = () => {
|
||||
let waistIn = points.styleWaistIn || points.waistIn
|
||||
return drawInseam()
|
||||
.line(points.floorOut)
|
||||
.join(drawOutseam())
|
||||
return drawOutseam()
|
||||
.line(points.backDartRight)
|
||||
.noop('dart')
|
||||
.line(points.backDartLeft)
|
||||
.line(waistIn)
|
||||
.line(points.crossSeamCurveStart)
|
||||
.curve(points.crossSeamCurveCp1, points.crossSeamCurveCp2, points.fork)
|
||||
.close()
|
||||
.curve(points.forkCp2, points.kneeInCp1, points.floorIn)
|
||||
}
|
||||
|
||||
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
|
@ -75,33 +57,68 @@ export default (part) => {
|
|||
|
||||
// Mark back pocket
|
||||
let base = points.styleWaistIn.dist(points.styleWaistOut)
|
||||
let v = base * options.backPocketVerticalPlacement
|
||||
let h = base * options.backPocketHorizontalPlacement
|
||||
let w = base * options.backPocketWidth
|
||||
let d = base * options.backPocketDepth
|
||||
let a = points.styleWaistIn.angle(points.styleWaistOut)
|
||||
points.waistPocketCenter = points.styleWaistIn.shiftFractionTowards(points.styleWaistOut, options.backPocketHorizontalPlacement)
|
||||
points.pocketCenter = points.waistPocketCenter.shift(a-90, v)
|
||||
points.pocketRight = points.pocketCenter.shift(a, w/2)
|
||||
points.pocketLeft = points.pocketCenter.shift(a, w/-2)
|
||||
let angle = points.styleWaistIn.angle(points.styleWaistOut)
|
||||
store.set('backPocketToWaistband', base * options.backPocketVerticalPlacement)
|
||||
store.set('backPocketWidth', base * options.backPocketWidth)
|
||||
store.set('backPocketDepth', base * options.backPocketDepth)
|
||||
points.waistPocketCenter = points.styleWaistIn.shiftFractionTowards(
|
||||
points.styleWaistOut,
|
||||
options.backPocketHorizontalPlacement
|
||||
)
|
||||
points.pocketCenter = points.waistPocketCenter.shift(
|
||||
angle - 90,
|
||||
store.get('backPocketToWaistband')
|
||||
)
|
||||
points.pocketRight = points.pocketCenter.shift(angle, store.get('backPocketWidth') / 2)
|
||||
points.pocketLeft = points.pocketCenter.shift(angle, store.get('backPocketWidth') / -2)
|
||||
|
||||
// Back dart
|
||||
points.tmp1 = points.waistPocketCenter.rotate(6.66, points.pocketCenter)
|
||||
points.tmp2 = points.waistPocketCenter.rotate(-6.66, points.pocketCenter)
|
||||
points.backDartLeft = points.pocketCenter.shiftFractionTowards(points.tmp1, 1.05)
|
||||
points.backDartRight = points.pocketCenter.shiftFractionTowards(points.tmp2, 1.05)
|
||||
let newBase = points.styleWaistIn.dist(points.backDartLeft)
|
||||
+ points.styleWaistOut.dist(points.backDartRight)
|
||||
let newBase =
|
||||
points.styleWaistIn.dist(points.backDartLeft) + points.styleWaistOut.dist(points.backDartRight)
|
||||
let delta = base - newBase
|
||||
// Adapt waist to new darted reality
|
||||
for (let p of ['styleWaistIn', 'crossSeamCurveStart', 'crossSeamCurveCp1']) {
|
||||
points[p] = points[p].shift(a + 180, delta/2)
|
||||
points[p] = points[p].shift(angle + 180, delta / 2)
|
||||
}
|
||||
points.styleWaistOut = points.styleWaistOut.shift(a, delta/2)
|
||||
points.styleWaistOut = points.styleWaistOut.shift(angle, delta / 2)
|
||||
|
||||
// Construct pocket tab
|
||||
if (points.waistOut.x > points.seatOut.x) {
|
||||
let outseam = new Path()
|
||||
.move(points.styleWaistOut)
|
||||
.curve(points.seatOut, points.kneeOutCp2, points.floorOut)
|
||||
points.slantBottom = outseam.shiftAlong(store.get('slantLength'))
|
||||
}
|
||||
points.slantOut = points.styleWaistIn.shiftOutwards(points.styleWaistOut, store.get('slantWidth'))
|
||||
points.pocketOpeningTop = points.slantOut.shiftTowards(
|
||||
points.slantBottom,
|
||||
store.get('pocketTabStart')
|
||||
)
|
||||
points.pocketOpeningBottom = points.pocketOpeningTop.shiftTowards(
|
||||
points.slantBottom,
|
||||
store.get('pocketTabInnerLength')
|
||||
)
|
||||
let slant = points.slantOut.angle(points.slantBottom)
|
||||
points.pocketOpeningTopIn = points.pocketOpeningTop.shift(slant + 90, store.get('pocketTabWidth'))
|
||||
points.pocketOpeningBottomIn = points.pocketOpeningTopIn.shift(
|
||||
slant,
|
||||
store.get('pocketTabOuterLength')
|
||||
)
|
||||
|
||||
// Store waistband length
|
||||
store.set(
|
||||
'waistbandBack',
|
||||
points.styleWaistIn.dist(points.backDartLeft) + points.backDartRight.dist(points.styleWaistOut)
|
||||
)
|
||||
|
||||
paths.saBase = drawPath()
|
||||
paths.seam = paths.saBase
|
||||
.insop('dart', new Path().line(points.pocketCenter))
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
paths.saBase.setRender(false)
|
||||
|
||||
|
@ -110,7 +127,33 @@ export default (part) => {
|
|||
.move(points.pocketLeft)
|
||||
.line(points.pocketRight)
|
||||
.attr('class', 'fabric dashed')
|
||||
points.titleAnchor = new Point(points.knee.x, points.fork.y)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: 1,
|
||||
title: 'back'
|
||||
})
|
||||
snippets.logo = new Snippet('logo', points.titleAnchor.shiftFractionTowards(points.knee, 0.5))
|
||||
macro('sprinkle', {
|
||||
snippet: 'bnotch',
|
||||
on: ['grainlineBottom', 'slantBottom', 'styleWaistOut']
|
||||
})
|
||||
paths.fold = new Path()
|
||||
.move(points.pocketOpeningTop)
|
||||
.line(points.pocketOpeningBottom)
|
||||
.attr('class', 'help')
|
||||
|
||||
if (sa) {
|
||||
paths.sa = paths.saBase
|
||||
.offset(sa)
|
||||
.join(
|
||||
new Path()
|
||||
.move(points.floorIn)
|
||||
.line(points.floorOut)
|
||||
.offset(sa * 3)
|
||||
)
|
||||
.close()
|
||||
.attr('class', 'fabric sa')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
|
|
80
packages/charlie/src/front-pocket.js
Normal file
80
packages/charlie/src/front-pocket.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
export default (part) => {
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
Point,
|
||||
paths,
|
||||
Path,
|
||||
measurements,
|
||||
options,
|
||||
complete,
|
||||
paperless,
|
||||
store,
|
||||
macro,
|
||||
utils,
|
||||
snippets,
|
||||
Snippet,
|
||||
sa
|
||||
} = part.shorthand()
|
||||
|
||||
// Clean up
|
||||
for (let id in paths) delete paths[id]
|
||||
for (let id in snippets) delete snippets[id]
|
||||
|
||||
// Straighten part
|
||||
let slant = points.pocketbagBottomRight.angle(points.pocketbagTopRight)
|
||||
for (let id of [
|
||||
'topPleat',
|
||||
'pocketbagTopLeft',
|
||||
'mirroredPocketOpeningTopIn',
|
||||
'mirroredPocketOpeningBottomIn',
|
||||
'pocketbagBump',
|
||||
'pocketbagBottomCp',
|
||||
'pocketbagBottom',
|
||||
'pocketbagBottomRight'
|
||||
])
|
||||
points[id] = points[id].rotate(-1 * (slant - 90), points.pocketbagTopRight)
|
||||
console.log(slant)
|
||||
|
||||
paths.saBase = new Path()
|
||||
.move(points.pocketbagTopRight)
|
||||
.line(points.pocketbagTopLeft)
|
||||
.line(points.mirroredPocketOpeningBottomIn)
|
||||
.curve(points.pocketbagBump, points.pocketbagBottomCp, points.pocketbagBottom)
|
||||
.line(points.pocketbagBottomRight)
|
||||
paths.seam = paths.saBase
|
||||
.clone()
|
||||
.line(points.pocketbagTopRight)
|
||||
.close()
|
||||
.attr('class', 'lining', true)
|
||||
|
||||
if (complete) {
|
||||
points.titleAnchor = points.pocketbagTopRight.shiftFractionTowards(
|
||||
points.pocketbagBottomCp,
|
||||
0.5
|
||||
)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: 4,
|
||||
title: 'pocketBag'
|
||||
})
|
||||
macro('cutonfold', {
|
||||
from: points.pocketbagBottomRight,
|
||||
to: points.pocketbagTopRight,
|
||||
grainline: true
|
||||
})
|
||||
|
||||
if (sa) {
|
||||
paths.sa = new Path()
|
||||
.move(points.pocketbagTopRight)
|
||||
.join(paths.saBase.offset(sa))
|
||||
.line(points.pocketbagBottomRight)
|
||||
.attr('class', 'lining sa')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
|
@ -1,44 +1,20 @@
|
|||
export default (part) => {
|
||||
// Helper method to draw the outseam path
|
||||
const drawOutseam = () => {
|
||||
// Helper object holding the Titan side seam path
|
||||
let sideSeam =
|
||||
points.waistOut.x < points.seatOut.x
|
||||
? new Path()
|
||||
.move(points.styleWaistOut)
|
||||
.curve(points.seatOut, points.kneeOutCp1, points.floorOut)
|
||||
: new Path()
|
||||
.move(points.styleWaistOut)
|
||||
._curve(points.seatOutCp1, points.seatOut)
|
||||
.curve(points.seatOutCp2, points.kneeOutCp1, points.floorOut)
|
||||
// Draw in pocket slant
|
||||
points.pocketSlantTop = points.styleWaistIn.shiftFractionTowards(
|
||||
points.styleWaistOut,
|
||||
1 - options.frontPocketSlantWidth
|
||||
)
|
||||
// Find lowest possible pocket slant point
|
||||
points.pocketSlantLowest = sideSeam.intersectsY(points.fork.y).pop()
|
||||
// Length to lowest possible slant point
|
||||
store.set(
|
||||
'slantLength',
|
||||
sideSeam.split(points.pocketSlantLowest).shift().length() * options.frontPocketSlantDepth
|
||||
)
|
||||
// Create actual slant point
|
||||
points.pocketSlantBottom = sideSeam.shiftAlong(store.get('slantLength'))
|
||||
|
||||
// Handy for later
|
||||
store.set('frontSideSeam', sideSeam)
|
||||
|
||||
return new Path()
|
||||
const drawOutseam = () =>
|
||||
new Path()
|
||||
.move(points.pocketSlantTop)
|
||||
.line(points.pocketOpeningTop)
|
||||
.line(points.pocketOpeningTopIn)
|
||||
.line(points.pocketOpeningBottomIn)
|
||||
.line(points.pocketOpeningBottom)
|
||||
.line(points.pocketSlantBottom)
|
||||
.join(sideSeam.split(points.pocketSlantBottom).pop())
|
||||
}
|
||||
|
||||
// Helper method to draw the outline path
|
||||
const drawPath = () =>
|
||||
drawOutseam()
|
||||
.line(points.floorIn)
|
||||
const drawPath = () => {
|
||||
let outseam = drawOutseam()
|
||||
return new Path()
|
||||
.move(points.floorIn)
|
||||
.curve(points.kneeInCp2, points.forkCp1, points.fork)
|
||||
.join(
|
||||
new Path()
|
||||
|
@ -51,7 +27,8 @@ export default (part) => {
|
|||
.line(points.flyTop)
|
||||
.line(points.styleWaistIn)
|
||||
.line(points.pocketSlantTop)
|
||||
.close()
|
||||
.join(outseam)
|
||||
}
|
||||
|
||||
// Shorthand
|
||||
let {
|
||||
|
@ -91,8 +68,97 @@ export default (part) => {
|
|||
points.flyCurveCp1 = points.flyBottom.shiftFractionTowards(points.flyCorner, options.flyCurve)
|
||||
points.flyCurveCp2 = points.flyCurveStart.shiftFractionTowards(points.flyCorner, options.flyCurve)
|
||||
|
||||
// Helper object holding the Titan side seam path
|
||||
const sideSeam =
|
||||
points.waistOut.x < points.seatOut.x
|
||||
? new Path()
|
||||
.move(points.styleWaistOut)
|
||||
.curve(points.seatOut, points.kneeOutCp1, points.floorOut)
|
||||
: new Path()
|
||||
.move(points.styleWaistOut)
|
||||
._curve(points.seatOutCp1, points.seatOut)
|
||||
.curve(points.seatOutCp2, points.kneeOutCp1, points.floorOut)
|
||||
|
||||
// Construct pocket slant
|
||||
points.pocketSlantTop = points.styleWaistIn.shiftFractionTowards(
|
||||
points.styleWaistOut,
|
||||
1 - options.frontPocketSlantWidth
|
||||
)
|
||||
points.pocketSlantLowest = sideSeam.intersectsY(points.fork.y).pop()
|
||||
store.set('slantWidth', points.styleWaistOut.dist(points.pocketSlantTop))
|
||||
store.set(
|
||||
'slantLength',
|
||||
sideSeam.split(points.pocketSlantLowest).shift().length() * options.frontPocketSlantDepth
|
||||
)
|
||||
points.pocketSlantBottom = sideSeam.shiftAlong(store.get('slantLength'))
|
||||
|
||||
// Construct front pocket
|
||||
let slant = points.pocketSlantTop.angle(points.pocketSlantBottom)
|
||||
let base = points.pocketSlantTop.dist(points.pocketSlantBottom)
|
||||
points.pocketOpeningTop = points.pocketSlantTop.shift(
|
||||
slant,
|
||||
(base * (1 - options.frontPocketOpening)) / 2
|
||||
)
|
||||
points.pocketOpeningBottom = points.pocketSlantBottom.shift(
|
||||
slant + 180,
|
||||
(base * (1 - options.frontPocketOpening)) / 2
|
||||
)
|
||||
points.pocketOpeningTopIn = points.pocketOpeningTop.shift(
|
||||
slant - 90,
|
||||
base * options.frontPocketEntry
|
||||
)
|
||||
points.pocketOpeningBottomIn = utils.beamIntersectsY(
|
||||
points.pocketOpeningTopIn,
|
||||
points.pocketOpeningTopIn.shift(slant, 666),
|
||||
points.pocketSlantBottom.y
|
||||
)
|
||||
macro('mirror', {
|
||||
mirror: [points.pocketOpeningTop, points.pocketOpeningBottom],
|
||||
points: [points.pocketOpeningTopIn, points.pocketOpeningBottomIn]
|
||||
})
|
||||
store.set('pocketTabWidth', base * options.frontPocketEntry)
|
||||
store.set('pocketTabInnerLength', points.pocketOpeningTop.dist(points.pocketOpeningBottom))
|
||||
store.set(
|
||||
'pocketTabOuterLength',
|
||||
points.mirroredPocketOpeningTopIn.dist(points.mirroredPocketOpeningBottomIn)
|
||||
)
|
||||
store.set('pocketTabStart', points.pocketSlantTop.dist(points.pocketOpeningTop))
|
||||
|
||||
// Construct pocket bag
|
||||
points.pocketbagTopLeft = utils.beamsIntersect(
|
||||
points.mirroredPocketOpeningBottomIn,
|
||||
points.mirroredPocketOpeningTopIn,
|
||||
points.pocketSlantTop,
|
||||
points.styleWaistIn
|
||||
)
|
||||
points.pocketbagTopRight = points.pocketbagTopLeft.shiftFractionTowards(
|
||||
points.styleWaistIn,
|
||||
options.frontPocketWidth
|
||||
)
|
||||
points.pocketbagBottomRight = points.pocketbagTopRight.shift(
|
||||
points.pocketbagTopLeft.angle(points.pocketbagTopRight) - 90,
|
||||
points.styleWaistIn.dy(points.fork) * options.frontPocketDepth * 1.5
|
||||
)
|
||||
points.pocketbagBump = utils.beamIntersectsY(
|
||||
points.mirroredPocketOpeningTopIn,
|
||||
points.mirroredPocketOpeningBottomIn,
|
||||
points.pocketSlantLowest.y
|
||||
)
|
||||
points.pocketbagBottomCp = new Point(
|
||||
points.mirroredPocketOpeningBottomIn.x,
|
||||
points.pocketbagBottomRight.y
|
||||
)
|
||||
points.pocketbagBottom = points.pocketbagBottomRight.shiftFractionTowards(
|
||||
points.pocketbagBottomCp,
|
||||
0.5
|
||||
)
|
||||
|
||||
// Draw path
|
||||
paths.seam = drawPath().attr('class', 'fabric')
|
||||
paths.seam = drawPath().close().attr('class', 'fabric')
|
||||
|
||||
// Store waistband length
|
||||
store.set('waistbandFront', points.styleWaistIn.dist(points.styleWaistOut))
|
||||
store.set('waistbandFly', points.styleWaistIn.dist(points.flyTop))
|
||||
|
||||
if (complete) {
|
||||
points.titleAnchor = new Point(points.knee.x, points.fork.y)
|
||||
|
@ -101,7 +167,7 @@ export default (part) => {
|
|||
nr: 2,
|
||||
title: 'front'
|
||||
})
|
||||
snippets.logo = new Snippet('logo', points.titleAnchor.shiftFractionTowards(points.knee, 0.5))
|
||||
snippets.logo = new Snippet('logo', points.titleAnchor.shiftFractionTowards(points.knee, 0.666))
|
||||
points.topPleat = utils.beamsIntersect(
|
||||
points.styleWaistIn,
|
||||
points.styleWaistOut,
|
||||
|
@ -123,13 +189,40 @@ export default (part) => {
|
|||
.shift()
|
||||
)
|
||||
.attr('class', 'fabric stoke-sm dashed')
|
||||
paths.slantHint = new Path()
|
||||
.move(points.pocketSlantTop)
|
||||
.line(points.styleWaistOut)
|
||||
.join(store.get('frontSideSeam').split(points.pocketSlantBottom).shift())
|
||||
.attr('class', 'fabric stoke-sm dashed')
|
||||
paths.pocketEntry = new Path()
|
||||
.move(points.pocketOpeningTop)
|
||||
.line(points.mirroredPocketOpeningTopIn)
|
||||
.line(points.mirroredPocketOpeningBottomIn)
|
||||
.line(points.pocketOpeningBottom)
|
||||
.attr('class', 'fabric dashed stroke-sm')
|
||||
paths.pocketFold = new Path()
|
||||
.move(points.pocketOpeningTop)
|
||||
.line(points.pocketOpeningBottom)
|
||||
.attr('class', 'help')
|
||||
paths.pocketBag = new Path()
|
||||
.move(points.pocketbagTopRight)
|
||||
.line(points.pocketbagBottomRight)
|
||||
.line(points.pocketbagBottom)
|
||||
.curve(points.pocketbagBottomCp, points.pocketbagBump, points.mirroredPocketOpeningBottomIn)
|
||||
.line(points.pocketbagTopLeft)
|
||||
.attr('class', 'lining dashed')
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: ['pocketbagTopLeft', 'pocketbagTopRight']
|
||||
})
|
||||
|
||||
if (sa) {
|
||||
paths.sa = drawPath()
|
||||
.offset(sa)
|
||||
.join(
|
||||
new Path()
|
||||
.move(points.floorOut)
|
||||
.line(points.floorIn)
|
||||
.offset(sa * 3)
|
||||
)
|
||||
.close()
|
||||
.trim()
|
||||
.attr('class', 'fabric sa')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import freesewing from '@freesewing/core'
|
||||
import Titan from '@freesewing/titan'
|
||||
import plugins from '@freesewing/plugin-bundle'
|
||||
|
||||
import mirrorPlugin from '@freesewing/plugin-mirror'
|
||||
import config from '../config'
|
||||
// Parts
|
||||
import draftBack from './back'
|
||||
import draftFront from './front'
|
||||
import draftWaistband from './waistband'
|
||||
import draftWaistbandButtonSide from './waistband-button-side'
|
||||
import draftWaistbandButtonholeSide from './waistband-buttonhole-side'
|
||||
import draftFrontPocket from './front-pocket'
|
||||
import draftBackPocket from './back-pocket'
|
||||
import draftBackPocketFacing from './back-pocket-facing'
|
||||
|
||||
// Hack the waistHeight option to make room for waistband
|
||||
const waistbandPlugin = {
|
||||
|
@ -21,7 +27,7 @@ const waistbandPlugin = {
|
|||
}
|
||||
|
||||
// Create design
|
||||
const Pattern = new freesewing.Design(config, [plugins, waistbandPlugin])
|
||||
const Pattern = new freesewing.Design(config, [plugins, mirrorPlugin, waistbandPlugin])
|
||||
|
||||
// Attach titan draft methods to prototype
|
||||
for (let p of ['Front', 'Back']) {
|
||||
|
@ -33,5 +39,11 @@ for (let p of ['Front', 'Back']) {
|
|||
// Attach charlie draft methods to prototype
|
||||
Pattern.prototype.draftBack = (part) => draftBack(part)
|
||||
Pattern.prototype.draftFront = (part) => draftFront(part)
|
||||
Pattern.prototype.draftWaistband = (part) => draftWaistband(part)
|
||||
Pattern.prototype.draftWaistbandButtonSide = (part) => draftWaistbandButtonSide(part)
|
||||
Pattern.prototype.draftWaistbandButtonholeSide = (part) => draftWaistbandButtonholeSide(part)
|
||||
Pattern.prototype.draftFrontPocket = (part) => draftFrontPocket(part)
|
||||
Pattern.prototype.draftBackPocket = (part) => draftBackPocket(part)
|
||||
Pattern.prototype.draftBackPocketFacing = (part) => draftBackPocketFacing(part)
|
||||
|
||||
export default Pattern
|
||||
|
|
87
packages/charlie/src/waistband-button-side.js
Normal file
87
packages/charlie/src/waistband-button-side.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
export default (part) => {
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
Point,
|
||||
paths,
|
||||
Path,
|
||||
measurements,
|
||||
options,
|
||||
complete,
|
||||
paperless,
|
||||
store,
|
||||
macro,
|
||||
utils,
|
||||
snippets,
|
||||
Snippet,
|
||||
sa
|
||||
} = part.shorthand()
|
||||
|
||||
if (!options.splitWaistband) return part
|
||||
|
||||
points.topLeft = new Point(0, 0)
|
||||
points.top = new Point(measurements.waist * options.waistbandWidth * options.waistbandFactor, 0)
|
||||
points.topRight = new Point(points.top.x * 2, 0)
|
||||
points.bottomLeft = new Point(
|
||||
0,
|
||||
store.get('waistbandBack') + store.get('waistbandFront') + store.get('waistbandFly')
|
||||
)
|
||||
points.bottom = new Point(points.top.x, points.bottomLeft.y)
|
||||
points.bottomRight = new Point(points.topRight.x, points.bottomLeft.y)
|
||||
|
||||
paths.saBase = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.topRight)
|
||||
.line(points.bottomRight)
|
||||
.setRender(false)
|
||||
paths.seam = paths.saBase
|
||||
.clone()
|
||||
.line(points.bottomLeft)
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
.setRender(true)
|
||||
|
||||
if (complete) {
|
||||
points.flyNotchRight = points.topRight.shift(-90, store.get('waistbandFly'))
|
||||
points.flyNotchLeft = new Point(0, points.flyNotchRight.y)
|
||||
points.firstSideNotchRight = points.flyNotchRight.shift(-90, store.get('waistbandFront'))
|
||||
points.firstSideNotchLeft = new Point(0, points.firstSideNotchRight.y)
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: ['flyNotchRight', 'flyNotchLeft', 'firstSideNotchRight', 'firstSideNotchLeft', 'bottom']
|
||||
})
|
||||
points.titleAnchor = points.top.shiftFractionTowards(points.bottom, 0.25)
|
||||
points.logoAnchor = points.top.shiftFractionTowards(points.bottom, 0.75)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: '3a',
|
||||
title: 'waistbandButtonSide',
|
||||
rotation: 90
|
||||
})
|
||||
macro('grainline', {
|
||||
from: points.firstSideNotchLeft,
|
||||
to: points.firstSideNotchRight
|
||||
})
|
||||
snippets.logo = new Snippet('logo', points.logoAnchor)
|
||||
paths.fold = new Path().move(points.top).line(points.bottom).attr('class', 'fabric help')
|
||||
if (sa) {
|
||||
paths.sa = paths.saBase
|
||||
.offset(sa * -1)
|
||||
.join(
|
||||
new Path()
|
||||
.move(points.bottomRight)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.topLeft)
|
||||
.offset(sa * -2)
|
||||
)
|
||||
.close()
|
||||
.attr('class', 'fabric sa')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
81
packages/charlie/src/waistband-buttonhole-side.js
Normal file
81
packages/charlie/src/waistband-buttonhole-side.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
export default (part) => {
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
Point,
|
||||
paths,
|
||||
Path,
|
||||
measurements,
|
||||
options,
|
||||
complete,
|
||||
paperless,
|
||||
store,
|
||||
macro,
|
||||
utils,
|
||||
snippets,
|
||||
Snippet,
|
||||
sa
|
||||
} = part.shorthand()
|
||||
|
||||
if (!options.splitWaistband) return part
|
||||
|
||||
points.topLeft = new Point(0, 0)
|
||||
points.top = new Point(measurements.waist * options.waistbandWidth * options.waistbandFactor, 0)
|
||||
points.topRight = new Point(points.top.x * 2, 0)
|
||||
points.bottomLeft = new Point(0, store.get('waistbandFront') + store.get('waistbandBack'))
|
||||
points.bottom = new Point(points.top.x, points.bottomLeft.y)
|
||||
points.bottomRight = new Point(points.topRight.x, points.bottomLeft.y)
|
||||
|
||||
paths.saBase = new Path()
|
||||
.move(points.topRight)
|
||||
.line(points.bottomRight)
|
||||
.line(points.bottomLeft)
|
||||
.setRender(false)
|
||||
paths.seam = paths.saBase
|
||||
.clone()
|
||||
.line(points.topLeft)
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
.setRender(true)
|
||||
|
||||
if (complete) {
|
||||
points.firstSideNotchRight = points.topRight.shift(-90, store.get('waistbandBack'))
|
||||
points.firstSideNotchLeft = new Point(0, points.firstSideNotchRight.y)
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: ['firstSideNotchRight', 'firstSideNotchLeft', 'top']
|
||||
})
|
||||
points.titleAnchor = points.top.shiftFractionTowards(points.bottom, 0.25)
|
||||
points.logoAnchor = points.top.shiftFractionTowards(points.bottom, 0.75)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: '3b',
|
||||
title: 'waistbandButtonholeSide',
|
||||
rotation: 90
|
||||
})
|
||||
macro('grainline', {
|
||||
from: points.firstSideNotchLeft,
|
||||
to: points.firstSideNotchRight
|
||||
})
|
||||
snippets.logo = new Snippet('logo', points.logoAnchor)
|
||||
paths.fold = new Path().move(points.top).line(points.bottom).attr('class', 'fabric help')
|
||||
if (sa) {
|
||||
paths.sa = paths.saBase
|
||||
.offset(sa * -1)
|
||||
.join(
|
||||
new Path()
|
||||
.move(points.bottomLeft)
|
||||
.line(points.topLeft)
|
||||
.line(points.topRight)
|
||||
.offset(sa * -2)
|
||||
)
|
||||
.close()
|
||||
.attr('class', 'fabric sa')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
96
packages/charlie/src/waistband.js
Normal file
96
packages/charlie/src/waistband.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
export default (part) => {
|
||||
// Shorthand
|
||||
let {
|
||||
points,
|
||||
Point,
|
||||
paths,
|
||||
Path,
|
||||
measurements,
|
||||
options,
|
||||
complete,
|
||||
paperless,
|
||||
store,
|
||||
macro,
|
||||
utils,
|
||||
snippets,
|
||||
Snippet,
|
||||
sa
|
||||
} = part.shorthand()
|
||||
|
||||
if (options.splitWaistband) return part
|
||||
|
||||
points.topLeft = new Point(0, 0)
|
||||
points.top = new Point(measurements.waist * options.waistbandWidth * options.waistbandFactor, 0)
|
||||
points.topRight = new Point(points.top.x * 2, 0)
|
||||
points.bottomLeft = new Point(
|
||||
0,
|
||||
2 * store.get('waistbandBack') + 2 * store.get('waistbandFront') + store.get('waistbandFly')
|
||||
)
|
||||
points.bottom = new Point(points.top.x, points.bottomLeft.y)
|
||||
points.bottomRight = new Point(points.topRight.x, points.bottomLeft.y)
|
||||
|
||||
paths.saBase = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.topRight)
|
||||
.line(points.bottomRight)
|
||||
.line(points.bottomLeft)
|
||||
.setRender(false)
|
||||
paths.seam = paths.saBase.clone().close().attr('class', 'fabric').setRender(true)
|
||||
|
||||
if (complete) {
|
||||
points.flyNotchRight = points.topRight.shift(-90, store.get('waistbandFly'))
|
||||
points.flyNotchLeft = new Point(0, points.flyNotchRight.y)
|
||||
points.firstSideNotchRight = points.flyNotchRight.shift(-90, store.get('waistbandFront'))
|
||||
points.firstSideNotchLeft = new Point(0, points.firstSideNotchRight.y)
|
||||
points.cbNotchRight = points.firstSideNotchRight.shift(-90, store.get('waistbandBack'))
|
||||
points.cbNotchLeft = new Point(0, points.cbNotchRight.y)
|
||||
points.secondSideNotchRight = points.cbNotchRight.shift(-90, store.get('waistbandBack'))
|
||||
points.secondSideNotchLeft = new Point(0, points.secondSideNotchRight.y)
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: [
|
||||
'flyNotchRight',
|
||||
'flyNotchLeft',
|
||||
'firstSideNotchRight',
|
||||
'firstSideNotchLeft',
|
||||
'cbNotchRight',
|
||||
'cbNotchLeft',
|
||||
'secondSideNotchRight',
|
||||
'secondSideNotchLeft'
|
||||
]
|
||||
})
|
||||
points.titleAnchor = points.cbNotchLeft.shiftFractionTowards(points.cbNotchRight, 0.5)
|
||||
points.logoAnchor = points.secondSideNotchLeft.shiftFractionTowards(
|
||||
points.secondSideNotchRight,
|
||||
0.5
|
||||
)
|
||||
macro('title', {
|
||||
at: points.titleAnchor,
|
||||
nr: 3,
|
||||
title: 'waistband'
|
||||
})
|
||||
macro('grainline', {
|
||||
from: points.firstSideNotchLeft,
|
||||
to: points.firstSideNotchRight
|
||||
})
|
||||
snippets.logo = new Snippet('logo', points.logoAnchor)
|
||||
paths.fold = new Path().move(points.top).line(points.bottom).attr('class', 'fabric help')
|
||||
if (sa) {
|
||||
paths.sa = paths.saBase
|
||||
.offset(sa * -1)
|
||||
.join(
|
||||
new Path()
|
||||
.move(points.bottomLeft)
|
||||
.line(points.topLeft)
|
||||
.offset(sa * -2)
|
||||
)
|
||||
.close()
|
||||
.attr('class', 'fabric sa')
|
||||
}
|
||||
|
||||
if (paperless) {
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue