1
0
Fork 0

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:
Joost De Cock 2021-06-12 14:05:28 +02:00
parent 62ec2682e5
commit 2bf10c0f75
9 changed files with 268 additions and 52 deletions

View file

@ -55,6 +55,9 @@ bent:
breanna: breanna:
peer: peer:
'@freesewing/brian': *freesewing '@freesewing/brian': *freesewing
brian:
peer:
'@freesewing/plugin-mirror': *freesewing
carlita: carlita:
peer: peer:
'@freesewing/brian': *freesewing '@freesewing/brian': *freesewing

View file

@ -18,6 +18,7 @@ export default {
'lengthBonus', 'lengthBonus',
'sleeveLengthBonus', 'sleeveLengthBonus',
], ],
style: [ 's3Collar', 's3Armhole' ],
advanced: [ advanced: [
'acrossBackFactor', 'acrossBackFactor',
'armholeDepthFactor', 'armholeDepthFactor',
@ -91,6 +92,9 @@ export default {
lengthBonus: { pct: 0, min: -4, max: 60 }, lengthBonus: { pct: 0, min: -4, max: 60 },
shoulderEase: { pct: 0, min: -2, max: 6 }, shoulderEase: { pct: 0, min: -2, max: 6 },
shoulderSlopeReduction: { pct: 0, min: 0, max: 80 }, 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 }, sleevecapEase: { pct: 1, min: 0, max: 10 },
sleevecapTopFactorX: { pct: 50, min: 25, max: 75 }, sleevecapTopFactorX: { pct: 50, min: 25, max: 75 },
sleevecapTopFactorY: { pct: 100, min: 35, max: 165 }, sleevecapTopFactorY: { pct: 100, min: 35, max: 165 },

View file

@ -35,7 +35,8 @@
}, },
"peerDependencies": { "peerDependencies": {
"@freesewing/core": "^2.16.2", "@freesewing/core": "^2.16.2",
"@freesewing/plugin-bundle": "^2.16.2" "@freesewing/plugin-bundle": "^2.16.2",
"@freesewing/plugin-mirror": "^2.16.2"
}, },
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {

View file

@ -12,13 +12,108 @@ export default (part) => {
complete, complete,
paperless, paperless,
macro, macro,
options,
Point,
utils
} = part.shorthand() } = part.shorthand()
points.anchor = points.hps.clone() 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 // Seamline
paths.saBase = shared.saBase('back', points, Path) paths.saBase = new Path()
paths.saBase.render = false .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() paths.seam = new Path()
.move(points.cbNeck) .move(points.cbNeck)
.line(points.cbHips) .line(points.cbHips)
@ -48,11 +143,14 @@ export default (part) => {
.move(points.cbHips) .move(points.cbHips)
paths.sa.line(paths.sa.start()) paths.sa.line(paths.sa.start())
} }
// Add notches if the shoulder seam is shifted
shared.s3Notches(part, 'bnotch')
} }
// Paperless? // Paperless?
if (paperless) { if (paperless) {
shared.dimensions(macro, points, Path, sa) shared.dimensions(part, 'back')
macro('hd', { macro('hd', {
from: points.cbHips, from: points.cbHips,
to: points.hips, to: points.hips,
@ -70,13 +168,13 @@ export default (part) => {
}) })
macro('hd', { macro('hd', {
from: points.cbNeck, from: points.cbNeck,
to: points.neck, to: points.s3CollarSplit,
y: points.neck.y - sa - 15, y: points.s3CollarSplit.y - sa - 15,
}) })
macro('hd', { macro('hd', {
from: points.cbNeck, from: points.cbNeck,
to: points.shoulder, to: points.s3ArmholeSplit,
y: points.neck.y - sa - 30, y: points.s3CollarSplit.y - sa - 30,
}) })
} }

View file

@ -13,6 +13,7 @@ export default (part) => {
paths, paths,
utils, utils,
complete, complete,
macro
} = part.shorthand() } = part.shorthand()
store.set('shoulderEase', (measurements.shoulderToShoulder * options.shoulderEase) / 2) store.set('shoulderEase', (measurements.shoulderToShoulder * options.shoulderEase) / 2)
@ -121,13 +122,38 @@ export default (part) => {
// Anchor point for sampling // Anchor point for sampling
points.gridAnchor = points.cbHem points.gridAnchor = points.cbHem
// Seamline /*
paths.saBase = shared.saBase('back', points, Path) * People would like to have the option to shift the shoulder seam
paths.seam = new Path() * See https://github.com/freesewing/freesewing/issues/642
.move(points.cbNeck) * So let's make the people happy
.line(points.cbHem) */
.join(paths.saBase) // Front armhole is a bit deeper, add those points
.attr('class', 'fabric') 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? // Complete pattern?
if (complete) { if (complete) {

View file

@ -15,13 +15,91 @@ export default (part) => {
complete, complete,
paperless, paperless,
macro, macro,
utils
} = part.shorthand() } = 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 let deeper = measurements.chest * options.frontArmholeDeeper
points.armholePitchCp1.x -= deeper points.armholePitchCp1 = points.frontArmholePitchCp1
points.armholePitch.x -= deeper points.armholePitch = points.frontArmholePitch
points.armholePitchCp2.x -= deeper 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) // Rename cb (center back) to cf (center front)
for (let key of ['Shoulder', 'Armhole', 'Waist', 'Hips', 'Hem']) { 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) points.neckCp2 = new Point(points.neckCp2Front.x, points.neckCp2Front.y)
// Seamline // 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.saBase.render = false
paths.seam = new Path() paths.seam = new Path()
.move(points.cfNeck) .move(points.cfNeck)
@ -62,11 +149,14 @@ export default (part) => {
.move(points.cfHips) .move(points.cfHips)
paths.sa.line(paths.sa.start()) paths.sa.line(paths.sa.start())
} }
// Add notches if the shoulder seam is shifted
shared.s3Notches(part, 'notch')
} }
// Paperless? // Paperless?
if (paperless) { if (paperless) {
shared.dimensions(macro, points, Path, sa) shared.dimensions(part, 'front')
macro('hd', { macro('hd', {
from: points.cfHips, from: points.cfHips,
to: points.hips, to: points.hips,
@ -84,13 +174,13 @@ export default (part) => {
}) })
macro('hd', { macro('hd', {
from: points.cfNeck, from: points.cfNeck,
to: points.neck, to: points.s3CollarSplit,
y: points.neck.y - sa - 15, y: points.s3CollarSplit.y - sa - 15,
}) })
macro('hd', { macro('hd', {
from: points.cfNeck, from: points.cfNeck,
to: points.shoulder, to: points.s3ArmholeSplit,
y: points.neck.y - sa - 30, y: points.s3CollarSplit.y - sa - 30,
}) })
} }

View file

@ -1,5 +1,6 @@
import freesewing from '@freesewing/core' import freesewing from '@freesewing/core'
import plugins from '@freesewing/plugin-bundle' import plugins from '@freesewing/plugin-bundle'
import mirrorPlugin from '@freesewing/plugin-mirror'
import config from '../config' import config from '../config'
// Parts // Parts
import draftBase from './base' import draftBase from './base'
@ -9,7 +10,7 @@ import draftSleevecap from './sleevecap'
import draftSleeve from './sleeve' import draftSleeve from './sleeve'
// Create design // Create design
const Pattern = new freesewing.Design(config, plugins) const Pattern = new freesewing.Design(config, [plugins, mirrorPlugin])
// Attach draft methods to prototype // Attach draft methods to prototype
Pattern.prototype.draftBase = draftBase Pattern.prototype.draftBase = draftBase

View file

@ -1,21 +1,7 @@
export function saBase(side, points, Path) { export function s3Notches(part, type) {
let path = new Path() const { snippets, Snippet, points, options } = part.shorthand()
if (side === 'back') path.move(points.cbHem) if (options.s3Armhole !== 0) snippets.shoulderNotch = new Snippet(type, points.shoulder)
else path.move(points.cfHem) if (options.s3Collar !== 0) snippets.collarNotch = new Snippet(type, points.hps)
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 armholeLength(points, Path) { export function armholeLength(points, Path) {
@ -34,19 +20,18 @@ export function shoulderToArmholePitch(points, Path) {
.length() .length()
} }
export function dimensions(macro, points, Path, sa) { export function dimensions(part, side) {
const { macro, points, Path, sa, paths } = part.shorthand()
macro('pd', { macro('pd', {
path: new Path() path: new Path()
.move(points.armhole) .move(points.armhole)
.curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow) .curve(points.armholeCp2, points.armholeHollowCp1, points.armholeHollow)
.curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch) .curve(points.armholeHollowCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder), .join(paths[`${side}Armhole`]),
d: sa + 15, d: sa + 15,
}) })
macro('pd', { macro('pd', {
path: new Path() path: paths[`${side}Armhole`],
.move(points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
d: -15, d: -15,
}) })
macro('vd', { macro('vd', {
@ -61,13 +46,13 @@ export function dimensions(macro, points, Path, sa) {
}) })
macro('vd', { macro('vd', {
from: points.hem, from: points.hem,
to: points.shoulder, to: points.s3ArmholeSplit,
x: points.hips.x + sa + 45, x: points.hips.x + sa + 45,
}) })
macro('vd', { macro('vd', {
from: points.hem, from: points.hem,
to: points.neck, to: points.s3CollarSplit,
x: points.hips.x + sa + 60, 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 })
} }

View file

@ -34,6 +34,14 @@ lengthBonus:
title: Length bonus title: Length bonus
description: The amount to lengthen the garment. A negative value will shorten it. 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: shoulderEase:
title: Shoulder ease title: Shoulder ease
description: The amount of ease at your shoulder. This increases the shoulder to shoulder distance to accommodate additional layers or thickness. description: The amount of ease at your shoulder. This increases the shoulder to shoulder distance to accommodate additional layers or thickness.