feat(brian): Allow shifting of the shoulder seam
This adds two new options to brian: - `s3Armhole` - `s3Collar` s3 in this case is short for: Shoulder Seam Shift. This option allows you to shift the shoulder seam forward (by increasing the option) or backward (be decreasing it). And this for the collar side and armhole/shoulder side. This is in preparation of the feature request in #642.
This commit is contained in:
parent
62ec2682e5
commit
2bf10c0f75
9 changed files with 268 additions and 52 deletions
|
@ -55,6 +55,9 @@ bent:
|
|||
breanna:
|
||||
peer:
|
||||
'@freesewing/brian': *freesewing
|
||||
brian:
|
||||
peer:
|
||||
'@freesewing/plugin-mirror': *freesewing
|
||||
carlita:
|
||||
peer:
|
||||
'@freesewing/brian': *freesewing
|
||||
|
|
|
@ -18,6 +18,7 @@ export default {
|
|||
'lengthBonus',
|
||||
'sleeveLengthBonus',
|
||||
],
|
||||
style: [ 's3Collar', 's3Armhole' ],
|
||||
advanced: [
|
||||
'acrossBackFactor',
|
||||
'armholeDepthFactor',
|
||||
|
@ -91,6 +92,9 @@ export default {
|
|||
lengthBonus: { pct: 0, min: -4, max: 60 },
|
||||
shoulderEase: { pct: 0, min: -2, max: 6 },
|
||||
shoulderSlopeReduction: { pct: 0, min: 0, max: 80 },
|
||||
// s3 is short for Shoulder Seam Shift
|
||||
s3Collar: { pct: 0, min: -100, max: 100 },
|
||||
s3Armhole: { pct: 0, min: -100, max: 100 },
|
||||
sleevecapEase: { pct: 1, min: 0, max: 10 },
|
||||
sleevecapTopFactorX: { pct: 50, min: 25, max: 75 },
|
||||
sleevecapTopFactorY: { pct: 100, min: 35, max: 165 },
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"@freesewing/core": "^2.16.2",
|
||||
"@freesewing/plugin-bundle": "^2.16.2"
|
||||
"@freesewing/plugin-bundle": "^2.16.2",
|
||||
"@freesewing/plugin-mirror": "^2.16.2"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -12,13 +12,108 @@ export default (part) => {
|
|||
complete,
|
||||
paperless,
|
||||
macro,
|
||||
options,
|
||||
Point,
|
||||
utils
|
||||
} = part.shorthand()
|
||||
|
||||
points.anchor = points.hps.clone()
|
||||
|
||||
// Adapt the shoulder seam according to the relevant options
|
||||
// Note: s3 stands for Shoulder Seam Shift
|
||||
if (options.s3Collar === 0) {
|
||||
points.s3CollarSplit = points.hps
|
||||
paths.backCollar = new Path()
|
||||
.move(points.hps)
|
||||
.curve_(points.neckCp2, points.cbNeck)
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Collar > 0) {
|
||||
// Shift shoulder seam forward on the collar side
|
||||
points.s3CollarSplit = utils.curveIntersectsY(
|
||||
points.hps,
|
||||
points.mirroredNeckCp2Front,
|
||||
points.mirroredCfNeckCp1,
|
||||
points.mirroredCfNeck,
|
||||
store.get('s3CollarMaxFront') * -1 * options.s3Collar
|
||||
)
|
||||
paths.backCollar = new Path()
|
||||
.move(points.hps)
|
||||
._curve(points.mirroredNeckCp2Front, points.mirroredCfNeckCp1, points.mirroredCfNeck)
|
||||
.split(points.s3CollarSplit)[0]
|
||||
.reverse()
|
||||
.join(new Path()
|
||||
.move(points.hps)
|
||||
.curve_(points.neckCp2, points.cbNeck)
|
||||
)
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Collar < 0) {
|
||||
// Shift shoulder seam backward on the collar side
|
||||
points.s3CollarSplit = utils.curveIntersectsY(
|
||||
points.hps, points.neckCp2, points.cbNeck, points.cbNeck,
|
||||
store.get('s3CollarMaxBack') * -1 * options.s3Collar
|
||||
)
|
||||
paths.backCollar = new Path()
|
||||
.move(points.cbNeck)
|
||||
._curve(points.neckCp2, points.neck)
|
||||
.split(points.s3CollarSplit)[0]
|
||||
.reverse()
|
||||
.setRender(false)
|
||||
}
|
||||
if (options.s3Armhole === 0) {
|
||||
points.s3ArmholeSplit = points.shoulder
|
||||
paths.backArmhole = new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Armhole > 0) {
|
||||
// Shift shoulder seam forward on the armhole side
|
||||
points.s3ArmholeSplit = utils.curveIntersectsY(
|
||||
points.shoulder,
|
||||
points.mirroredShoulderCp1,
|
||||
points.mirroredFrontArmholePitchCp2,
|
||||
points.mirroredFrontArmholePitch,
|
||||
store.get('s3ArmholeMax') * -1 * options.s3Armhole + points.shoulder.y
|
||||
)
|
||||
paths.backArmhole = new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.join(new Path()
|
||||
.move(points.shoulder)
|
||||
.curve(points.mirroredShoulderCp1, points.mirroredFrontArmholePitchCp2, points.mirroredFrontArmholePitch)
|
||||
.split(points.s3ArmholeSplit)[0]
|
||||
)
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Armhole < 0) {
|
||||
// Shift shoulder seam backward on the armhole side
|
||||
points.s3ArmholeSplit = utils.curveIntersectsY(
|
||||
points.shoulder,
|
||||
points.shoulderCp1,
|
||||
points.armholePitchCp2,
|
||||
points.armholePitch,
|
||||
store.get('s3ArmholeMax') * -1 * options.s3Armhole + points.shoulder.y
|
||||
)
|
||||
paths.backArmhole = new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.split(points.s3ArmholeSplit)[0]
|
||||
.setRender(false)
|
||||
}
|
||||
|
||||
// Seamline
|
||||
paths.saBase = shared.saBase('back', points, Path)
|
||||
paths.saBase.render = false
|
||||
paths.saBase = new Path()
|
||||
.move(points.cbHem)
|
||||
.line(points.hem)
|
||||
.line(points.armhole)
|
||||
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
|
||||
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
|
||||
.join(paths.backArmhole)
|
||||
.line(points.s3CollarSplit)
|
||||
.join(paths.backCollar)
|
||||
.setRender(false)
|
||||
paths.seam = new Path()
|
||||
.move(points.cbNeck)
|
||||
.line(points.cbHips)
|
||||
|
@ -48,11 +143,14 @@ export default (part) => {
|
|||
.move(points.cbHips)
|
||||
paths.sa.line(paths.sa.start())
|
||||
}
|
||||
|
||||
// Add notches if the shoulder seam is shifted
|
||||
shared.s3Notches(part, 'bnotch')
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
shared.dimensions(macro, points, Path, sa)
|
||||
shared.dimensions(part, 'back')
|
||||
macro('hd', {
|
||||
from: points.cbHips,
|
||||
to: points.hips,
|
||||
|
@ -70,13 +168,13 @@ export default (part) => {
|
|||
})
|
||||
macro('hd', {
|
||||
from: points.cbNeck,
|
||||
to: points.neck,
|
||||
y: points.neck.y - sa - 15,
|
||||
to: points.s3CollarSplit,
|
||||
y: points.s3CollarSplit.y - sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.cbNeck,
|
||||
to: points.shoulder,
|
||||
y: points.neck.y - sa - 30,
|
||||
to: points.s3ArmholeSplit,
|
||||
y: points.s3CollarSplit.y - sa - 30,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ export default (part) => {
|
|||
paths,
|
||||
utils,
|
||||
complete,
|
||||
macro
|
||||
} = part.shorthand()
|
||||
|
||||
store.set('shoulderEase', (measurements.shoulderToShoulder * options.shoulderEase) / 2)
|
||||
|
@ -121,13 +122,38 @@ export default (part) => {
|
|||
// Anchor point for sampling
|
||||
points.gridAnchor = points.cbHem
|
||||
|
||||
// Seamline
|
||||
paths.saBase = shared.saBase('back', points, Path)
|
||||
paths.seam = new Path()
|
||||
.move(points.cbNeck)
|
||||
.line(points.cbHem)
|
||||
.join(paths.saBase)
|
||||
.attr('class', 'fabric')
|
||||
/*
|
||||
* People would like to have the option to shift the shoulder seam
|
||||
* See https://github.com/freesewing/freesewing/issues/642
|
||||
* So let's make the people happy
|
||||
*/
|
||||
// Front armhole is a bit deeper, add those points
|
||||
let deeper = measurements.chest * options.frontArmholeDeeper
|
||||
for (const p of ['','Cp1','Cp2']) {
|
||||
points[`frontArmholePitch${p}`] = points[`armholePitch${p}`].shift(180, deeper)
|
||||
}
|
||||
// Add points needed for the mirrored front&back neck/armhole path
|
||||
macro('mirror', {
|
||||
mirror: [points.hps, points.shoulder],
|
||||
points: [
|
||||
points.neckCp2Front,
|
||||
points.cfNeckCp1,
|
||||
points.cfNeck,
|
||||
points.cbNeck,
|
||||
points.neckCp2,
|
||||
points.frontArmholePitch,
|
||||
points.frontArmholePitchCp2,
|
||||
points.shoulderCp1,
|
||||
],
|
||||
clone: true
|
||||
})
|
||||
|
||||
// How much space do we have to work with here?
|
||||
// s3 = ShoulderSeamShift
|
||||
store.set('s3CollarMaxFront', points.hps.dy(points.cfNeck)/2)
|
||||
store.set('s3CollarMaxBack', points.hps.dy(points.cbNeck)/2)
|
||||
store.set('s3ArmholeMax', points.shoulder.dy(points.frontArmholePitch)/4)
|
||||
// Let's leave the actual splitting the curves for the front/back parts
|
||||
|
||||
// Complete pattern?
|
||||
if (complete) {
|
||||
|
|
|
@ -15,13 +15,91 @@ export default (part) => {
|
|||
complete,
|
||||
paperless,
|
||||
macro,
|
||||
utils
|
||||
} = part.shorthand()
|
||||
|
||||
// Cut arm a bit deeper at the front
|
||||
// Re-use points for deeper armhole at the front
|
||||
let deeper = measurements.chest * options.frontArmholeDeeper
|
||||
points.armholePitchCp1.x -= deeper
|
||||
points.armholePitch.x -= deeper
|
||||
points.armholePitchCp2.x -= deeper
|
||||
points.armholePitchCp1 = points.frontArmholePitchCp1
|
||||
points.armholePitch = points.frontArmholePitch
|
||||
points.armholePitchCp2 = points.frontArmholePitchCp2
|
||||
|
||||
// Adapt the shoulder line according to the relevant options
|
||||
if (options.s3Collar === 0) {
|
||||
paths.frontCollar = new Path()
|
||||
.move(points.hps)
|
||||
.curve(points.neckCp2Front, points.cfNeckCp1, points.cfNeck)
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Collar > 0) {
|
||||
// Shift shoulder seam forward on the collar side
|
||||
points.s3CollarSplit = utils.curveIntersectsY(
|
||||
points.hps, points.neckCp2Front, points.cfNeckCp1, points.cfNeck,
|
||||
store.get('s3CollarMaxFront') * options.s3Collar
|
||||
)
|
||||
paths.frontCollar = new Path()
|
||||
.move(points.hps)
|
||||
.curve(points.neckCp2Front, points.cfNeckCp1, points.cfNeck)
|
||||
.split(points.s3CollarSplit)[1]
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Collar < 0) {
|
||||
// Shift shoulder seam backward on the collar side
|
||||
points.s3CollarSplit = utils.curveIntersectsY(
|
||||
points.mirroredCbNeck, points.mirroredCbNeck, points.mirroredNeckCp2, points.hps,
|
||||
store.get('s3CollarMaxBack') * options.s3Collar
|
||||
)
|
||||
paths.frontCollar = new Path()
|
||||
.move(points.hps)
|
||||
.curve_(points.mirroredNeckCp2, points.mirroredCbNeck)
|
||||
.split(points.s3CollarSplit)[0]
|
||||
.reverse()
|
||||
.join(new Path()
|
||||
.move(points.hps)
|
||||
.curve(points.neckCp2Front, points.cfNeckCp1, points.cfNeck)
|
||||
)
|
||||
.setRender(false)
|
||||
}
|
||||
if (options.s3Armhole === 0) {
|
||||
paths.frontArmhole = new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Armhole > 0) {
|
||||
// Shift shoulder seam forward on the armhole side
|
||||
points.s3ArmholeSplit = utils.curveIntersectsY(
|
||||
points.shoulder,
|
||||
points.shoulderCp1,
|
||||
points.armholePitchCp2,
|
||||
points.armholePitch,
|
||||
store.get('s3ArmholeMax') * options.s3Armhole + points.shoulder.y
|
||||
)
|
||||
paths.frontArmhole = new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.split(points.s3ArmholeSplit)[0]
|
||||
.setRender(false)
|
||||
}
|
||||
else if (options.s3Armhole < 0) {
|
||||
// Shift shoulder seam forward on the armhole side
|
||||
points.s3ArmholeSplit = utils.curveIntersectsY(
|
||||
points.shoulder,
|
||||
points.mirroredShoulderCp1,
|
||||
points.mirroredFrontArmholePitchCp2,
|
||||
points.mirroredFrontArmholePitch,
|
||||
store.get('s3ArmholeMax') * options.s3Armhole + points.shoulder.y
|
||||
)
|
||||
paths.frontArmhole = new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.join(new Path()
|
||||
.move(points.shoulder)
|
||||
.curve(points.mirroredShoulderCp1, points.mirroredFrontArmholePitchCp2, points.mirroredFrontArmholePitch)
|
||||
.split(points.s3ArmholeSplit)[0]
|
||||
)
|
||||
.setRender(false)
|
||||
}
|
||||
|
||||
// Rename cb (center back) to cf (center front)
|
||||
for (let key of ['Shoulder', 'Armhole', 'Waist', 'Hips', 'Hem']) {
|
||||
|
@ -32,7 +110,16 @@ export default (part) => {
|
|||
points.neckCp2 = new Point(points.neckCp2Front.x, points.neckCp2Front.y)
|
||||
|
||||
// Seamline
|
||||
paths.saBase = shared.saBase('front', points, Path)
|
||||
paths.saBase = new Path()
|
||||
.move(points.cfHem)
|
||||
.line(points.hem)
|
||||
.line(points.armhole)
|
||||
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
|
||||
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
|
||||
.join(paths.frontArmhole)
|
||||
.line(points.s3CollarSplit)
|
||||
.join(paths.frontCollar)
|
||||
|
||||
paths.saBase.render = false
|
||||
paths.seam = new Path()
|
||||
.move(points.cfNeck)
|
||||
|
@ -62,11 +149,14 @@ export default (part) => {
|
|||
.move(points.cfHips)
|
||||
paths.sa.line(paths.sa.start())
|
||||
}
|
||||
|
||||
// Add notches if the shoulder seam is shifted
|
||||
shared.s3Notches(part, 'notch')
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
shared.dimensions(macro, points, Path, sa)
|
||||
shared.dimensions(part, 'front')
|
||||
macro('hd', {
|
||||
from: points.cfHips,
|
||||
to: points.hips,
|
||||
|
@ -84,13 +174,13 @@ export default (part) => {
|
|||
})
|
||||
macro('hd', {
|
||||
from: points.cfNeck,
|
||||
to: points.neck,
|
||||
y: points.neck.y - sa - 15,
|
||||
to: points.s3CollarSplit,
|
||||
y: points.s3CollarSplit.y - sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.cfNeck,
|
||||
to: points.shoulder,
|
||||
y: points.neck.y - sa - 30,
|
||||
to: points.s3ArmholeSplit,
|
||||
y: points.s3CollarSplit.y - sa - 30,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import freesewing from '@freesewing/core'
|
||||
import plugins from '@freesewing/plugin-bundle'
|
||||
import mirrorPlugin from '@freesewing/plugin-mirror'
|
||||
import config from '../config'
|
||||
// Parts
|
||||
import draftBase from './base'
|
||||
|
@ -9,7 +10,7 @@ import draftSleevecap from './sleevecap'
|
|||
import draftSleeve from './sleeve'
|
||||
|
||||
// Create design
|
||||
const Pattern = new freesewing.Design(config, plugins)
|
||||
const Pattern = new freesewing.Design(config, [plugins, mirrorPlugin])
|
||||
|
||||
// Attach draft methods to prototype
|
||||
Pattern.prototype.draftBase = draftBase
|
||||
|
|
|
@ -1,21 +1,7 @@
|
|||
export function saBase(side, points, Path) {
|
||||
let path = new Path()
|
||||
if (side === 'back') path.move(points.cbHem)
|
||||
else path.move(points.cfHem)
|
||||
path
|
||||
.line(points.hem)
|
||||
.line(points.armhole)
|
||||
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
|
||||
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
|
||||
.line(points.neck)
|
||||
if (side === 'back') {
|
||||
path.curve(points.neckCp2, points.cbNeck, points.cbNeck)
|
||||
} else {
|
||||
path.curve(points.neckCp2, points.cfNeckCp1, points.cfNeck)
|
||||
}
|
||||
|
||||
return path
|
||||
export function s3Notches(part, type) {
|
||||
const { snippets, Snippet, points, options } = part.shorthand()
|
||||
if (options.s3Armhole !== 0) snippets.shoulderNotch = new Snippet(type, points.shoulder)
|
||||
if (options.s3Collar !== 0) snippets.collarNotch = new Snippet(type, points.hps)
|
||||
}
|
||||
|
||||
export function armholeLength(points, Path) {
|
||||
|
@ -34,19 +20,18 @@ export function shoulderToArmholePitch(points, Path) {
|
|||
.length()
|
||||
}
|
||||
|
||||
export function dimensions(macro, points, Path, sa) {
|
||||
export function dimensions(part, side) {
|
||||
const { macro, points, Path, sa, paths } = part.shorthand()
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.armhole)
|
||||
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
|
||||
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
|
||||
.join(paths[`${side}Armhole`]),
|
||||
d: sa + 15,
|
||||
})
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.armholePitch)
|
||||
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
|
||||
path: paths[`${side}Armhole`],
|
||||
d: -15,
|
||||
})
|
||||
macro('vd', {
|
||||
|
@ -61,13 +46,13 @@ export function dimensions(macro, points, Path, sa) {
|
|||
})
|
||||
macro('vd', {
|
||||
from: points.hem,
|
||||
to: points.shoulder,
|
||||
to: points.s3ArmholeSplit,
|
||||
x: points.hips.x + sa + 45,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.hem,
|
||||
to: points.neck,
|
||||
to: points.s3CollarSplit,
|
||||
x: points.hips.x + sa + 60,
|
||||
})
|
||||
macro('ld', { from: points.neck, to: points.shoulder, d: sa + 15 })
|
||||
macro('ld', { from: points.s3CollarSplit, to: points.s3ArmholeSplit, d: sa + 15 })
|
||||
}
|
||||
|
|
|
@ -34,6 +34,14 @@ lengthBonus:
|
|||
title: Length bonus
|
||||
description: The amount to lengthen the garment. A negative value will shorten it.
|
||||
|
||||
s3Collar:
|
||||
title: 'Shoulder seam shift: collar side'
|
||||
description: Increase this option to shift the shoulder seam forward on the collar side. Decreasing it shifts it backwards.
|
||||
|
||||
s3Armhole:
|
||||
title: 'Shoulder seam shift: armhole side'
|
||||
description: Increase this option to shift the shoulder seam forward on the armhole side. Decreasing it shifts it backwards.
|
||||
|
||||
shoulderEase:
|
||||
title: Shoulder ease
|
||||
description: The amount of ease at your shoulder. This increases the shoulder to shoulder distance to accommodate additional layers or thickness.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue