1
0
Fork 0

feat(breanna): Added sleevecap

This commit is contained in:
Joost De Cock 2020-01-16 19:26:59 +01:00
parent de29f8a2f7
commit 87f6728608
7 changed files with 376 additions and 86 deletions

View file

@ -20,46 +20,48 @@ export default {
'verticalEase',
'chestEase',
'collarEase',
// 'bicepsEase',
// 'cuffEase',
'bicepsEase',
'cuffEase',
'shoulderEase',
'waistEase',
'primaryBustDartLength',
'secondaryBustDartLength'
// 'lengthBonus',
// 'sleeveLengthBonus'
'waistEase'
],
style: [
'primaryBustDart',
'primaryBustDartLength',
'secondaryBustDart',
'secondaryBustDartLength',
'primaryBustDartShaping',
'sleeveLengthBonus'
],
style: ['primaryBustDart', 'secondaryBustDart', 'primaryBustDartShaping'],
advanced: [
'acrossBackFactor',
'armholeDepthFactor'
// 'frontArmholeDeeper',
// 'shoulderSlopeReduction',
// 'sleeveWidthGuarantee',
// {
// sleevecap: [
// 'sleevecapEase',
// 'sleevecapTopFactorX',
// 'sleevecapTopFactorY',
// 'sleevecapBackFactorX',
// 'sleevecapBackFactorY',
// 'sleevecapFrontFactorX',
// 'sleevecapFrontFactorY',
// 'sleevecapQ1Offset',
// 'sleevecapQ2Offset',
// 'sleevecapQ3Offset',
// 'sleevecapQ4Offset',
// 'sleevecapQ1Spread1',
// 'sleevecapQ1Spread2',
// 'sleevecapQ2Spread1',
// 'sleevecapQ2Spread2',
// 'sleevecapQ3Spread1',
// 'sleevecapQ3Spread2',
// 'sleevecapQ4Spread1',
// 'sleevecapQ4Spread2'
// ]
// }
'armholeDepthFactor',
'frontArmholeDeeper',
//'shoulderSlopeReduction',
'sleeveWidthGuarantee',
{
sleevecap: [
'sleevecapEase',
'sleevecapTopFactorX',
'sleevecapTopFactorY',
'sleevecapBackFactorX',
'sleevecapBackFactorY',
'sleevecapFrontFactorX',
'sleevecapFrontFactorY',
'sleevecapQ1Offset',
'sleevecapQ2Offset',
'sleevecapQ3Offset',
'sleevecapQ4Offset',
'sleevecapQ1Spread1',
'sleevecapQ1Spread2',
'sleevecapQ2Spread1',
'sleevecapQ2Spread2',
'sleevecapQ3Spread1',
'sleevecapQ3Spread2',
'sleevecapQ4Spread1',
'sleevecapQ4Spread2'
]
}
]
},
measurements: [
@ -76,39 +78,31 @@ export default {
'bustSpan',
'shoulderSlope',
'neckCircumference'
//'hpsToHipsFront',
//'bicepsCircumference',
//'chestCircumference',
//'hpsToWaistBack',
//'shoulderToWrist',
//'wristCircumference'
],
//dependencies: {
// back: 'base',
// front: 'back',
// sleevecap: 'front',
// sleeve: 'sleevecap'
//},
dependencies: {
back: 'base',
frontBase: 'base',
front: 'frontBase',
sleevecap: 'front'
//sleeve: 'sleevecap'
},
inject: {
back: 'base',
frontBase: 'base',
front: 'frontBase'
// sleeve: 'sleevecap'
//sleeve: 'sleevecap'
},
hide: ['frontBase'],
//parts: ['back', 'front'],
options: {
// Constants
collarFactor: 4.8,
//brianFitSleeve: true,
armholeDepthBase: 0.65,
breannaFitSleeve: true,
breannaFitCollar: true,
//collarFactor: 4.8,
//backNeckCutout: 0.05,
armholeDepthBase: 0.6,
// Percentages
acrossBackFactor: { pct: 97, min: 93, max: 100 },
armholeDepthFactor: { pct: 90, min: 80, max: 120 },
armholeDepthFactor: { pct: 100, min: 80, max: 120 },
shoulderDart: { bool: false },
shoulderDartSize: { pct: 7, min: 4, max: 10 },
shoulderDartLength: { pct: 85, min: 60, max: 100 },
@ -165,32 +159,32 @@ export default {
},
primaryBustDartShaping: { pct: 50, min: 25, max: 75 },
primaryBustDartLength: { pct: 85, min: 65, max: 95 },
secondaryBustDartLength: { pct: 85, min: 65, max: 95 }
secondaryBustDartLength: { pct: 85, min: 65, max: 95 },
//bicepsEase: { pct: 15, min: 0, max: 50 },
//cuffEase: { pct: 20, min: 0, max: 200 },
//lengthBonus: { pct: 0, min: -4, max: 60 },
//shoulderSlopeReduction: { pct: 0, min: 0, max: 100 },
//sleevecapEase: { pct: 1, min: 0, max: 10 },
//sleevecapTopFactorX: { pct: 50, min: 25, max: 75 },
//sleevecapTopFactorY: { pct: 100, min: 35, max: 165 },
//sleevecapBackFactorX: { pct: 60, min: 35, max: 65 },
//sleevecapBackFactorY: { pct: 33, min: 35, max: 65 },
//sleevecapFrontFactorX: { pct: 55, min: 35, max: 65 },
//sleevecapFrontFactorY: { pct: 33, min: 35, max: 65 },
//sleevecapQ1Offset: { pct: 3, min: 0, max: 7 },
//sleevecapQ2Offset: { pct: 5.5, min: 0, max: 7 },
//sleevecapQ3Offset: { pct: 4.5, min: 0, max: 7 },
//sleevecapQ4Offset: { pct: 1, min: 0, max: 7 },
//sleevecapQ1Spread1: { pct: 6, min: 4, max: 20 },
//sleevecapQ1Spread2: { pct: 15, min: 4, max: 20 },
//sleevecapQ2Spread1: { pct: 15, min: 4, max: 20 },
//sleevecapQ2Spread2: { pct: 10, min: 4, max: 20 },
//sleevecapQ3Spread1: { pct: 10, min: 4, max: 20 },
//sleevecapQ3Spread2: { pct: 8, min: 4, max: 20 },
//sleevecapQ4Spread1: { pct: 7, min: 4, max: 20 },
//sleevecapQ4Spread2: { pct: 7, min: 4, max: 20 },
//sleeveWidthGuarantee: { pct: 90, min: 25, max: 100 },
//sleeveLengthBonus: { pct: 0, min: -40, max: 10 }
bicepsEase: { pct: 15, min: 0, max: 50 },
cuffEase: { pct: 20, min: 0, max: 200 },
sleevecapEase: { pct: 1, min: 0, max: 10 },
sleevecapTopFactorX: { pct: 50, min: 25, max: 75 },
sleevecapTopFactorY: { pct: 100, min: 35, max: 165 },
sleevecapBackFactorX: { pct: 60, min: 35, max: 65 },
sleevecapBackFactorY: { pct: 33, min: 35, max: 65 },
sleevecapFrontFactorX: { pct: 55, min: 35, max: 65 },
sleevecapFrontFactorY: { pct: 33, min: 35, max: 65 },
sleevecapQ1Offset: { pct: 3, min: 0, max: 7 },
sleevecapQ2Offset: { pct: 5.5, min: 0, max: 7 },
sleevecapQ3Offset: { pct: 4.5, min: 0, max: 7 },
sleevecapQ4Offset: { pct: 1, min: 0, max: 7 },
sleevecapQ1Spread1: { pct: 6, min: 4, max: 20 },
sleevecapQ1Spread2: { pct: 15, min: 4, max: 20 },
sleevecapQ2Spread1: { pct: 15, min: 4, max: 20 },
sleevecapQ2Spread2: { pct: 10, min: 4, max: 20 },
sleevecapQ3Spread1: { pct: 10, min: 4, max: 20 },
sleevecapQ3Spread2: { pct: 8, min: 4, max: 20 },
sleevecapQ4Spread1: { pct: 7, min: 4, max: 20 },
sleevecapQ4Spread2: { pct: 7, min: 4, max: 20 },
sleeveWidthGuarantee: { pct: 90, min: 25, max: 100 },
sleeveLengthBonus: { pct: 0, min: -40, max: 10 }
}
}

View file

@ -275,5 +275,12 @@ export default part => {
})
}
macro('pd', {
path: new Path()
.move(points.armhole)
.curve(points.armholeCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
d: 15
})
return part
}

View file

@ -38,6 +38,12 @@ export default part => {
.length() * 2
collarDelta = front + back - target
} while (Math.abs(collarDelta) > 1)
} else {
points.hpsCp2 = utils.beamIntersectsY(
points.hps,
points.hps.shiftTowards(points.shoulder, 10).rotate(-90, points.hps),
points.cfNeck.y
)
}
// Armhole deeper at the front
@ -63,7 +69,6 @@ export default part => {
points.armhole = points.armhole.shift(0, bustDelta)
// Adjust waist down to accomodate bust
points.cfHips = new Point(0, measurements.hpsToHipsFront)
points.cfWaist = new Point(
0,
measurements.hpsToHipsFront - (measurements.hpsToHipsBack - measurements.hpsToWaistBack)
@ -89,7 +94,7 @@ export default part => {
)
points.primaryBustDart2 = points.primaryBustDart1.rotate(180, points.primaryBustDartCenter)
// Store bust dart angle
// Store bust dart angle and armhole length
store.set(
'bustDartAngle',
Math.abs(
@ -97,6 +102,14 @@ export default part => {
points.primaryBustDartTip.angle(points.primaryBustDart2)
)
)
store.set(
'frontArmholeLength',
new Path()
.move(points.armhole)
.curve(points.armholeCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder)
.length()
)
return part
}

View file

@ -246,5 +246,13 @@ export default part => {
}
}
macro('pd', {
path: new Path()
.move(points.armhole)
.curve(points.armholeCp2, points.armholePitchCp1, points.armholePitch)
.curve(points.armholePitchCp2, points.shoulderCp1, points.shoulder),
d: 15
})
return part
}

View file

@ -6,20 +6,18 @@ import draftBase from './base'
import draftBack from './back'
import draftFrontBase from './front-base'
import draftFront from './front'
//import draftBase from './base'
//import draftSleevecap from './sleevecap'
import draftSleevecap from './sleevecap'
//import draftSleeve from './sleeve'
// Create design
const Pattern = new freesewing.Design(config, plugins)
// Attach draft methods to prototype
//Pattern.prototype.draftBase = draftBase
Pattern.prototype.draftBase = draftBase
Pattern.prototype.draftBack = draftBack
Pattern.prototype.draftFrontBase = draftFrontBase
Pattern.prototype.draftFront = draftFront
//Pattern.prototype.draftSleevecap = draftSleevecap
Pattern.prototype.draftSleevecap = draftSleevecap
//Pattern.prototype.draftSleeve = draftSleeve
export default Pattern

View file

@ -0,0 +1,112 @@
export default part => {
let {
debug,
store,
units,
sa,
measurements,
options,
Point,
points,
Path,
paths,
Snippet,
snippets,
complete,
paperless,
macro
} = part.shorthand()
// Wrist
let top = paths.sleevecap.bbox().topLeft.y
debug({
style: 'info',
label: '🗸 Sleevecap height',
msg: units(Math.abs(top))
})
debug({
style: 'info',
label: '🗸 Sleevecap width',
msg: units(points.bicepsRight.x * 2)
})
points.centerWrist = new Point(
0,
top + measurements.shoulderToWrist * (1 + options.sleeveLengthBonus)
)
points.wristRight = points.centerWrist.shift(
0,
(measurements.wristCircumference * (1 + options.cuffEase)) / 2
)
points.wristLeft = points.wristRight.rotate(180, points.centerWrist)
points.sleeveTip = paths.sleevecap.shiftFractionAlong(0.5)
// Paths
paths.sleevecap.render = false
paths.seam = new Path()
.move(points.bicepsLeft)
.move(points.wristLeft)
.move(points.wristRight)
.line(points.bicepsRight)
.join(paths.sleevecap)
.close()
.attr('class', 'fabric')
// Anchor point for sampling
points.gridAnchor = new Point(0, 0)
// Complete pattern?
if (complete) {
points.logo = points.centerBiceps.shiftFractionTowards(points.centerWrist, 0.3)
snippets.logo = new Snippet('logo', points.logo)
macro('title', { at: points.centerBiceps, nr: 3, title: 'sleeve' })
macro('grainline', { from: points.centerWrist, to: points.centerBiceps })
points.scaleboxAnchor = points.scalebox = points.centerBiceps.shiftFractionTowards(
points.centerWrist,
0.5
)
macro('scalebox', { at: points.scalebox })
points.frontNotch = paths.sleevecap.shiftAlong(
paths.sleevecap.length() / 2 -
store.get('frontShoulderToArmholePitch') -
store.get('sleevecapEase') / 2
)
points.backNotch = paths.sleevecap.shiftAlong(
paths.sleevecap.length() / 2 +
store.get('backShoulderToArmholePitch') +
store.get('sleevecapEase') / 2
)
snippets.frontNotch = new Snippet('notch', points.frontNotch)
snippets.backNotch = new Snippet('bnotch', points.backNotch)
if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
}
// Paperless?
if (paperless) {
macro('vd', {
from: points.wristLeft,
to: points.bicepsLeft,
x: points.bicepsLeft.x - sa - 15
})
macro('vd', {
from: points.wristLeft,
to: points.sleeveTip,
x: points.bicepsLeft.x - sa - 30
})
macro('hd', {
from: points.bicepsLeft,
to: points.bicepsRight,
y: points.sleeveTip.y - sa - 30
})
macro('hd', {
from: points.wristLeft,
to: points.wristRight,
y: points.wristLeft.y + sa + 30
})
macro('pd', {
path: paths.sleevecap.reverse(),
d: -1 * sa - 15
})
}
return part
}

View file

@ -0,0 +1,158 @@
/** Calculates the differece between actual and optimal sleevecap length
* Positive values mean sleevecap is longer than armhole
*/
function sleevecapDelta(store) {
return store.get('sleevecapLength') - store.get('sleevecapTarget')
}
function sleevecapAdjust(store) {
let delta = sleevecapDelta(store)
let factor = store.get('sleeveFactor')
if (delta > 10) factor = factor * 0.75
else if (delta > 0) factor = factor * 0.9
else factor = factor * 1.05
store.set('sleeveFactor', factor)
}
function draftSleevecap(part, run) {
let { debug, units, store, measurements, options, Point, points, Path, paths } = part.shorthand()
// Sleeve center axis
points.centerBiceps = new Point(0, 0)
points.centerCap = points.centerBiceps.shift(
90,
options.sleevecapTopFactorY *
((measurements.bicepsCircumference / 2) *
(1 + options.bicepsEase) *
store.get('sleeveFactor'))
)
// Left and right biceps points, limit impact of sleeveFactor to 25%
let halfWidth = (measurements.bicepsCircumference * (1 + options.bicepsEase)) / 2
points.bicepsLeft = points.centerBiceps.shift(
180,
halfWidth * options.sleeveWidthGuarantee +
halfWidth * (1 - options.sleeveWidthGuarantee) * store.get('sleeveFactor')
)
points.bicepsRight = points.bicepsLeft.flipX(points.centerBiceps)
// Adapt sleeve center axis
points.capLeft = new Point(points.bicepsLeft.x, points.centerCap.y)
points.capRight = points.capLeft.flipX()
points.centerCap = points.capLeft.shiftFractionTowards(
points.capRight,
options.sleevecapTopFactorX
)
// Pitch points
let width = points.bicepsRight.x
let height = points.centerCap.y
points.backPitch = new Point(
-1 * width * options.sleevecapBackFactorX,
height * options.sleevecapBackFactorY
)
points.frontPitch = new Point(
width * options.sleevecapFrontFactorX,
height * options.sleevecapFrontFactorY
)
// 4 sleevecap quadrants
// Base points
points.capQ1Base = points.frontPitch.shiftFractionTowards(points.bicepsRight, 0.5)
points.capQ2Base = points.frontPitch.shiftFractionTowards(points.centerCap, 0.5)
points.capQ3Base = points.backPitch.shiftFractionTowards(points.centerCap, 0.5)
points.capQ4Base = points.backPitch.shiftFractionTowards(points.bicepsLeft, 0.5)
// Offset points
let baseOffset = measurements.bicepsCircumference * (1 + options.bicepsEase)
points.capQ1 = points.capQ1Base.shift(
points.bicepsRight.angle(points.frontPitch) + 90,
baseOffset * options.sleevecapQ1Offset
)
points.capQ2 = points.capQ2Base.shift(
points.centerCap.angle(points.frontPitch) + 90,
baseOffset * options.sleevecapQ2Offset
)
points.capQ3 = points.capQ3Base.shift(
points.centerCap.angle(points.backPitch) - 90,
baseOffset * options.sleevecapQ3Offset
)
points.capQ4 = points.capQ4Base.shift(
points.bicepsLeft.angle(points.backPitch) - 90,
baseOffset * options.sleevecapQ4Offset
)
// Control points
points.capQ1Cp1 = points.capQ1.shift(
points.frontPitch.angle(points.bicepsRight),
baseOffset * options.sleevecapQ1Spread1
)
points.capQ1Cp2 = points.capQ1.shift(
points.frontPitch.angle(points.bicepsRight),
baseOffset * options.sleevecapQ1Spread2 * -1
)
points.capQ2Cp1 = points.capQ2.shift(
points.centerCap.angle(points.frontPitch),
baseOffset * options.sleevecapQ2Spread1
)
points.capQ2Cp2 = points.capQ2.shift(
points.centerCap.angle(points.frontPitch),
baseOffset * options.sleevecapQ2Spread2 * -1
)
points.capQ3Cp1 = points.capQ3.shift(
points.backPitch.angle(points.centerCap),
baseOffset * options.sleevecapQ3Spread1
)
points.capQ3Cp2 = points.capQ3.shift(
points.backPitch.angle(points.centerCap),
baseOffset * options.sleevecapQ3Spread2 * -1
)
points.capQ4Cp1 = points.capQ4.shift(
points.bicepsLeft.angle(points.backPitch),
baseOffset * options.sleevecapQ4Spread1
)
points.capQ4Cp2 = points.capQ4.shift(
points.bicepsLeft.angle(points.backPitch),
baseOffset * options.sleevecapQ4Spread2 * -1
)
// Sleevecap seamline
paths.sleevecap = new Path()
.move(points.bicepsRight)
.curve(points.bicepsRight, points.capQ1Cp1, points.capQ1)
.curve(points.capQ1Cp2, points.capQ2Cp1, points.capQ2)
.curve(points.capQ2Cp2, points.capQ3Cp1, points.capQ3)
.curve(points.capQ3Cp2, points.capQ4Cp1, points.capQ4)
.curve(points.capQ4Cp2, points.bicepsLeft, points.bicepsLeft)
// Store sleevecap length
store.set('sleevecapLength', paths.sleevecap.length())
if (run === 0) {
let armholeLength = store.get('frontArmholeLength') + store.get('backArmholeLength')
let sleevecapEase = armholeLength * options.sleevecapEase
store.set('sleevecapEase', sleevecapEase)
store.set('sleevecapTarget', armholeLength + sleevecapEase)
// Uncomment this line to see all sleevecap iterations
//paths[run] = paths.sleevecap;
}
}
export default part => {
let { debug, store, units, options, Point, points, paths } = part.shorthand()
store.set('sleeveFactor', 1)
let run = 0
let delta = 0
do {
draftSleevecap(part, run)
delta = sleevecapDelta(store)
sleevecapAdjust(store)
run++
} while (options.breannaFitSleeve === true && run < 50 && Math.abs(sleevecapDelta(store)) > 2)
// Paths
paths.sleevecap.attr('class', 'fabric')
// Anchor point for sampling
points.gridAnchor = new Point(0, 0)
return part
}