2019-03-25 18:20:15 +01:00
|
|
|
/**
|
|
|
|
* This collar is the most difficult part about this pattern
|
|
|
|
* That's because slash&spread is easy with paper and scissors
|
|
|
|
* but gets complicated when doing it in code.
|
|
|
|
*/
|
|
|
|
|
2021-01-31 09:22:15 +01:00
|
|
|
export default function (part) {
|
2019-08-03 15:03:33 +02:00
|
|
|
let { paperless, sa, complete, points, options, macro, paths, Path } = part.shorthand()
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// We're going to slash and spread this collar. Slashing first:
|
|
|
|
// Divide top in 5 parts
|
2019-08-03 15:03:33 +02:00
|
|
|
points.cutTop1 = points.topLeft.shiftFractionTowards(points.topRight, 0.2)
|
|
|
|
points.cutTop2 = points.topLeft.shiftFractionTowards(points.topRight, 0.4)
|
|
|
|
points.cutTop3 = points.topLeft.shiftFractionTowards(points.topRight, 0.6)
|
|
|
|
points.cutTop4 = points.topLeft.shiftFractionTowards(points.topRight, 0.8)
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// Divide bottom in 4 parts
|
2019-08-03 15:03:33 +02:00
|
|
|
let bottom = new Path().move(points.standTop).curve_(points.standTopCp, points.standTip)
|
|
|
|
points.cutBottom1 = bottom.shiftFractionAlong(0.25)
|
|
|
|
points.cutBottom2 = bottom.shiftFractionAlong(0.5)
|
|
|
|
points.cutBottom3 = bottom.shiftFractionAlong(0.75)
|
2019-03-25 18:20:15 +01:00
|
|
|
// Split curve, extract control points from ops
|
2019-08-03 15:03:33 +02:00
|
|
|
let halves = bottom.split(points.cutBottom2)
|
|
|
|
let quarters = []
|
|
|
|
quarters.push(...halves[0].split(points.cutBottom1))
|
|
|
|
quarters.push(...halves[1].split(points.cutBottom3))
|
|
|
|
points.q1Cp1 = quarters[0].ops[1].cp1
|
|
|
|
points.q1Cp2 = quarters[0].ops[1].cp2
|
|
|
|
points.q2Cp1 = quarters[1].ops[1].cp1
|
|
|
|
points.q2Cp2 = quarters[1].ops[1].cp2
|
|
|
|
points.q3Cp1 = quarters[2].ops[1].cp1
|
|
|
|
points.q3Cp2 = quarters[2].ops[1].cp2
|
|
|
|
points.q4Cp1 = quarters[3].ops[1].cp1
|
|
|
|
points.q4Cp2 = quarters[3].ops[1].cp2
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// Collar slashed, not let's spread by rotating
|
|
|
|
let rotate = {
|
|
|
|
1: {
|
2019-08-03 15:03:33 +02:00
|
|
|
pivot: 'cutBottom1',
|
2021-04-24 10:16:31 +02:00
|
|
|
points: ['cutBottom2', 'cutTop1', 'cutTop2', 'q2Cp1', 'q2Cp2'],
|
2019-03-25 18:20:15 +01:00
|
|
|
},
|
|
|
|
2: {
|
2019-08-03 15:03:33 +02:00
|
|
|
pivot: 'cutBottom2',
|
2021-04-24 10:16:31 +02:00
|
|
|
points: ['cutBottom3', 'cutTop2', 'cutTop3', 'q3Cp1', 'q3Cp2'],
|
2019-03-25 18:20:15 +01:00
|
|
|
},
|
|
|
|
3: {
|
2019-08-03 15:03:33 +02:00
|
|
|
pivot: 'cutBottom3',
|
2021-04-24 10:16:31 +02:00
|
|
|
points: ['standTip', 'bottomRight', 'cutTop4', 'cutTop3', 'q4Cp1'],
|
2019-03-25 18:20:15 +01:00
|
|
|
},
|
|
|
|
4: {
|
2019-08-03 15:03:33 +02:00
|
|
|
pivot: 'standTip',
|
2021-04-24 10:16:31 +02:00
|
|
|
points: ['topRight', 'bottomRight', 'cutTop4'],
|
|
|
|
},
|
2019-08-03 15:03:33 +02:00
|
|
|
}
|
2019-03-25 18:20:15 +01:00
|
|
|
|
2019-08-03 15:03:33 +02:00
|
|
|
let angle = -1 * options.collarSpread
|
|
|
|
let alsoRotate = []
|
|
|
|
for (let nr of [4, 3, 2, 1]) {
|
|
|
|
let step = rotate[nr]
|
|
|
|
let pivot = step.pivot
|
|
|
|
let first = false
|
2019-03-25 18:20:15 +01:00
|
|
|
for (let pnt of step.points) {
|
2019-08-03 15:03:33 +02:00
|
|
|
if (first === false) first = pnt
|
|
|
|
let id = `rot${nr}${pnt}`
|
|
|
|
points[id] = points[pnt].rotate(angle, points[pivot])
|
|
|
|
alsoRotate.push(id)
|
2019-03-25 18:20:15 +01:00
|
|
|
}
|
2019-08-03 15:03:33 +02:00
|
|
|
if (nr < 4) for (let pnt of alsoRotate) points[pnt] = points[pnt].rotate(angle, points[pivot])
|
2019-03-25 18:20:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Shift panel 2 in place
|
2019-08-03 15:03:33 +02:00
|
|
|
angle = points.cutBottom2.angle(points.rot1cutBottom2) + 180
|
|
|
|
let distance = -1 * points.cutBottom2.dist(points.rot1cutBottom2)
|
2019-03-25 18:20:15 +01:00
|
|
|
for (let i of [
|
|
|
|
'cutBottom2',
|
|
|
|
'rot2cutTop2',
|
|
|
|
'rot2cutTop3',
|
|
|
|
'rot2cutBottom3',
|
|
|
|
'rot2q3Cp1',
|
2021-04-24 10:16:31 +02:00
|
|
|
'rot2q3Cp2',
|
2019-08-03 15:03:33 +02:00
|
|
|
])
|
|
|
|
points[i] = points[i].shift(angle, distance)
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// Shift panel 3 in place
|
2019-08-03 15:03:33 +02:00
|
|
|
angle = points.cutBottom3.angle(points.rot2cutBottom3) + 180
|
|
|
|
distance = -1 * points.cutBottom3.dist(points.rot2cutBottom3)
|
|
|
|
for (let i of ['cutBottom3', 'rot3cutTop3', 'rot3cutTop4', 'rot3standTip', 'rot3q4Cp1'])
|
|
|
|
points[i] = points[i].shift(angle, distance)
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// Shift panel 4 in place
|
2019-08-03 15:03:33 +02:00
|
|
|
angle = points.standTip.angle(points.rot3standTip) + 180
|
|
|
|
distance = -1 * points.standTip.dist(points.rot3standTip)
|
|
|
|
for (let i of ['standTip', 'rot4cutTop4', 'rot4topRight', 'rot4bottomRight'])
|
|
|
|
points[i] = points[i].shift(angle, distance)
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// Top control point
|
2019-08-03 15:03:33 +02:00
|
|
|
points.topLeftCp = points.topLeft.shift(0, points.rot4topRight.x * 0.6)
|
2019-03-25 18:20:15 +01:00
|
|
|
|
|
|
|
// Paths
|
|
|
|
/* Uncomment these paths to gain insight into what's happening here
|
|
|
|
paths.collarStand = paths.seam.clone(); // Needed because it gets overwritten later
|
|
|
|
paths.panels = new Path()
|
|
|
|
.move(points.cutTop1).line(points.cutBottom1)
|
|
|
|
.move(points.cutTop2).line(points.cutBottom2)
|
|
|
|
.move(points.cutTop3).line(points.cutBottom3)
|
|
|
|
.move(points.cutTop4).line(points.standTip)
|
|
|
|
|
|
|
|
paths.outline = new Path()
|
|
|
|
.move(points.bottomLeft)
|
|
|
|
.curve(points.bottomLeftCp, points.standTipCp, points.standTip)
|
|
|
|
._curve(points.standTopCp, points.standTop)
|
|
|
|
.curve_(points.standTopCpLeft, points.standTipLeft)
|
|
|
|
.curve(points.standTipCpLeft, points.bottomLeftCpLeft, points.bottomLeft)
|
|
|
|
.close()
|
|
|
|
.move(points.topLeft)
|
|
|
|
.line(points.topRight)
|
|
|
|
.line(points.bottomRight);
|
|
|
|
|
|
|
|
paths.panel2 = new Path()
|
|
|
|
.move(points.cutBottom1)
|
|
|
|
.line(points.rot1cutBottom2)
|
|
|
|
.line(points.rot1cutTop2)
|
|
|
|
.line(points.rot1cutTop1)
|
|
|
|
.close()
|
|
|
|
.attr("class", "dashed");
|
|
|
|
|
|
|
|
paths.panel3 = new Path()
|
|
|
|
.move(points.cutBottom2)
|
|
|
|
.line(points.rot2cutBottom3)
|
|
|
|
.line(points.rot2cutTop3)
|
|
|
|
.line(points.rot2cutTop2)
|
|
|
|
.close()
|
|
|
|
.attr("class", "dashed");
|
|
|
|
|
|
|
|
paths.panel4 = new Path()
|
|
|
|
.move(points.cutBottom3)
|
|
|
|
.line(points.rot3standTip)
|
|
|
|
.line(points.rot3cutTop4)
|
|
|
|
.line(points.rot3cutTop3)
|
|
|
|
.close()
|
|
|
|
.attr("class", "dashed");
|
|
|
|
|
|
|
|
paths.panel5 = new Path()
|
|
|
|
.move(points.standTip)
|
|
|
|
.line(points.rot4bottomRight)
|
|
|
|
.line(points.rot4topRight)
|
|
|
|
.line(points.rot4cutTop4)
|
|
|
|
.close()
|
|
|
|
.attr("class", "dashed");
|
|
|
|
*/
|
|
|
|
|
2019-03-30 11:32:32 +01:00
|
|
|
paths.saBase = new Path()
|
2019-03-25 18:20:15 +01:00
|
|
|
.move(points.standTop)
|
|
|
|
/** This is the non-slashed path. We use this instead of the slashed
|
|
|
|
* parts of the path, so that we get a smooth line
|
|
|
|
*/
|
|
|
|
.curve_(points.standTopCp, points.rot3standTip)
|
|
|
|
/** These are the slashed parts. We're not using these, but you can change that if you want
|
|
|
|
* Just uncomment this, and comment out the non-slashed curve operation above
|
|
|
|
*/
|
|
|
|
//.curve(points.q1Cp1, points.q1Cp2, points.cutBottom1)
|
|
|
|
//.curve(points.rot1q2Cp1, points.rot1q2Cp2, points.rot1cutBottom2)
|
|
|
|
//.curve(points.rot2q3Cp1, points.rot2q3Cp2, points.rot2cutBottom3)
|
|
|
|
//.curve_(points.rot3q4Cp1, points.rot3standTip)
|
|
|
|
.line(points.rot4bottomRight)
|
|
|
|
.line(points.rot4topRight)
|
2019-08-03 15:03:33 +02:00
|
|
|
._curve(points.topLeftCp, points.topLeft)
|
2021-01-31 09:22:15 +01:00
|
|
|
paths.seam = paths.saBase.clone().line(points.standTop).close().attr('class', 'fabric')
|
2019-03-25 18:20:15 +01:00
|
|
|
|
2019-03-30 11:32:32 +01:00
|
|
|
if (complete) {
|
2019-08-03 15:03:33 +02:00
|
|
|
points.title = points.standTopCp.clone()
|
|
|
|
macro('title', {
|
2019-03-30 11:32:32 +01:00
|
|
|
at: points.title,
|
|
|
|
nr: 8,
|
2021-04-24 10:16:31 +02:00
|
|
|
title: 'collar',
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
2019-03-30 11:32:32 +01:00
|
|
|
|
2021-02-01 20:52:41 +01:00
|
|
|
// Remove grainline from collarstand part
|
|
|
|
delete paths.grainline
|
|
|
|
macro('cutonfold', {
|
|
|
|
from: points.topLeft,
|
|
|
|
to: points.standTop,
|
2021-04-24 10:16:31 +02:00
|
|
|
grainline: true,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
2019-03-30 11:32:32 +01:00
|
|
|
|
|
|
|
if (sa) {
|
2019-08-03 15:03:33 +02:00
|
|
|
paths.sa = paths.saBase.offset(sa)
|
2019-03-30 11:32:32 +01:00
|
|
|
paths.sa = paths.sa
|
|
|
|
.line(points.topLeft)
|
|
|
|
.move(points.standTop)
|
|
|
|
.line(paths.sa.start())
|
2019-08-03 15:03:33 +02:00
|
|
|
.attr('class', 'fabric sa')
|
2019-03-30 11:32:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (paperless) {
|
2019-08-03 15:03:33 +02:00
|
|
|
macro('hd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.standTop,
|
|
|
|
to: points.rot3standTip,
|
2021-04-24 10:16:31 +02:00
|
|
|
y: points.rot4bottomRight.y + sa + 15,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('hd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.standTop,
|
|
|
|
to: points.rot4bottomRight,
|
2021-04-24 10:16:31 +02:00
|
|
|
y: points.rot4bottomRight.y + sa + 30,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('hd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.standTop,
|
|
|
|
to: points.rot4topRight,
|
2021-04-24 10:16:31 +02:00
|
|
|
y: points.rot4bottomRight.y + sa + 45,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('vd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.standTop,
|
|
|
|
to: points.topLeft,
|
2021-04-24 10:16:31 +02:00
|
|
|
x: points.topLeft.x - 15,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('vd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.rot3standTip,
|
|
|
|
to: points.topLeft,
|
2021-04-24 10:16:31 +02:00
|
|
|
x: points.topLeft.x - 30,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('vd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.rot4topRight,
|
|
|
|
to: points.topLeft,
|
2021-04-24 10:16:31 +02:00
|
|
|
x: points.rot4topRight.x + sa + 15,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('vd', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.rot4bottomRight,
|
|
|
|
to: points.topLeft,
|
2021-04-24 10:16:31 +02:00
|
|
|
x: points.rot4topRight.x + sa + 30,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('ld', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.rot4bottomRight,
|
|
|
|
to: points.rot4topRight,
|
2021-04-24 10:16:31 +02:00
|
|
|
d: -1 * sa - 15,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
|
|
|
macro('ld', {
|
2019-03-30 11:32:32 +01:00
|
|
|
from: points.rot3standTip,
|
|
|
|
to: points.rot4bottomRight,
|
2021-04-24 10:16:31 +02:00
|
|
|
d: -1 * sa - 15,
|
2019-08-03 15:03:33 +02:00
|
|
|
})
|
2019-03-30 11:32:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-03 15:03:33 +02:00
|
|
|
return part
|
2019-03-25 18:20:15 +01:00
|
|
|
}
|