2018-09-23 13:14:25 +02:00
|
|
|
import * as shared from "./shared";
|
2018-07-19 13:14:50 +00:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
export default part => {
|
2019-02-16 08:56:20 +01:00
|
|
|
let {
|
|
|
|
units,
|
|
|
|
debug,
|
|
|
|
measurements,
|
|
|
|
options,
|
|
|
|
store,
|
|
|
|
points,
|
|
|
|
snippets,
|
|
|
|
Point,
|
|
|
|
Snippet,
|
|
|
|
Path,
|
|
|
|
paths,
|
|
|
|
utils,
|
|
|
|
complete
|
|
|
|
} = part.shorthand();
|
2018-08-10 16:43:08 +02:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
store.set(
|
|
|
|
"shoulderEase",
|
|
|
|
(measurements.shoulderToShoulder * options.shoulderEase) / 2
|
|
|
|
);
|
2018-07-19 13:14:50 +00:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Center back (cb) vertical axis
|
|
|
|
points.cbNeck = new Point(
|
|
|
|
0,
|
|
|
|
options.backNeckCutout * measurements.neckCircumference
|
|
|
|
);
|
|
|
|
points.cbShoulder = new Point(
|
|
|
|
0,
|
|
|
|
(measurements.shoulderSlope -
|
|
|
|
measurements.shoulderToShoulder * options.shoulderSlopeReduction) /
|
|
|
|
2
|
|
|
|
);
|
|
|
|
points.cbArmhole = new Point(
|
|
|
|
0,
|
|
|
|
points.cbShoulder.y +
|
2018-12-19 07:39:10 +01:00
|
|
|
(measurements.shoulderToShoulder * options.shoulderSlopeReduction) / 2 +
|
2018-12-17 14:42:28 +01:00
|
|
|
measurements.bicepsCircumference *
|
|
|
|
(1 + options.bicepsEase) *
|
|
|
|
options.armholeDepthFactor
|
|
|
|
);
|
|
|
|
points.cbWaist = new Point(
|
|
|
|
0,
|
|
|
|
points.cbNeck.y + measurements.centerBackNeckToWaist
|
|
|
|
);
|
|
|
|
points.cbHips = new Point(
|
2018-12-21 12:55:50 +01:00
|
|
|
0,
|
|
|
|
points.cbWaist.y + measurements.naturalWaistToHip
|
|
|
|
);
|
|
|
|
points.cbHem = new Point(
|
2018-12-17 14:42:28 +01:00
|
|
|
0,
|
|
|
|
points.cbWaist.y +
|
|
|
|
measurements.naturalWaistToHip +
|
|
|
|
(measurements.centerBackNeckToWaist + measurements.naturalWaistToHip) *
|
|
|
|
options.lengthBonus
|
|
|
|
);
|
2018-07-19 13:14:50 +00:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Side back (cb) vertical axis
|
|
|
|
points.armhole = new Point(
|
|
|
|
(measurements.chestCircumference * (1 + options.chestEase)) / 4,
|
|
|
|
points.cbArmhole.y
|
|
|
|
);
|
|
|
|
points.waist = new Point(points.armhole.x, points.cbWaist.y);
|
|
|
|
points.hips = new Point(points.armhole.x, points.cbHips.y);
|
2018-12-21 12:55:50 +01:00
|
|
|
points.hem = new Point(points.armhole.x, points.cbHem.y);
|
2018-07-19 13:14:50 +00:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Shoulder line
|
|
|
|
points.neck = new Point(
|
|
|
|
(measurements.neckCircumference * (1 + options.collarEase)) /
|
|
|
|
options.collarFactor,
|
|
|
|
0
|
|
|
|
);
|
|
|
|
points.shoulder = new Point(
|
|
|
|
measurements.shoulderToShoulder / 2 + store.get("shoulderEase"),
|
|
|
|
points.cbShoulder.y
|
|
|
|
);
|
2018-07-19 13:14:50 +00:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Armhhole
|
|
|
|
points.armholePitch = new Point(
|
|
|
|
(measurements.shoulderToShoulder * options.acrossBackFactor) / 2 +
|
|
|
|
store.get("shoulderEase") / 2,
|
|
|
|
points.shoulder.y + points.shoulder.dy(points.armhole) / 2
|
|
|
|
);
|
|
|
|
points._tmp1 = new Point(points.armholePitch.x, points.armhole.y);
|
|
|
|
points._tmp2 = points._tmp1.shift(45, 10);
|
|
|
|
points._tmp3 = utils.beamsIntersect(
|
|
|
|
points._tmp1,
|
|
|
|
points._tmp2,
|
|
|
|
points.armhole,
|
|
|
|
points.armholePitch
|
|
|
|
);
|
|
|
|
points.armholeHollow = points._tmp1.shiftFractionTowards(points._tmp3, 0.5);
|
|
|
|
points.armholeCp2 = points.armhole.shift(
|
|
|
|
180,
|
|
|
|
points._tmp1.dx(points.armhole) / 4
|
|
|
|
);
|
|
|
|
points.armholeHollowCp1 = points.armholeHollow.shift(
|
|
|
|
-45,
|
|
|
|
points.armholeHollow.dy(points.armhole) / 2
|
|
|
|
);
|
|
|
|
points.armholeHollowCp2 = points.armholeHollow.shift(
|
|
|
|
135,
|
|
|
|
points.armholePitch.dx(points.armholeHollow)
|
|
|
|
);
|
|
|
|
points.armholePitchCp1 = points.armholePitch.shift(
|
|
|
|
-90,
|
|
|
|
points.armholePitch.dy(points.armholeHollow) / 2
|
|
|
|
);
|
|
|
|
points.armholePitchCp2 = points.armholePitch.shift(
|
|
|
|
90,
|
|
|
|
points.shoulder.dy(points.armholePitch) / 2
|
|
|
|
);
|
|
|
|
points.shoulderCp1 = points.shoulder
|
|
|
|
.shiftTowards(points.neck, points.shoulder.dy(points.armholePitch) / 5)
|
|
|
|
.rotate(90, points.shoulder);
|
2018-08-05 16:32:19 +02:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Neck opening (back)
|
|
|
|
points._tmp4 = points.neck
|
|
|
|
.shiftTowards(points.shoulder, 10)
|
|
|
|
.rotate(-90, points.neck);
|
|
|
|
points.neckCp2 = utils.beamIntersectsY(
|
|
|
|
points.neck,
|
|
|
|
points._tmp4,
|
|
|
|
points.cbNeck.y
|
|
|
|
);
|
2018-09-23 13:14:25 +02:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Fit collar
|
|
|
|
points.cfNeck = points.neck.rotate(-90, new Point(0, 0));
|
|
|
|
let target = measurements.neckCircumference * (1 + options.collarEase);
|
|
|
|
let delta = 0;
|
|
|
|
let run = 0;
|
|
|
|
do {
|
|
|
|
run++;
|
|
|
|
points.cfNeck = points.cfNeck.shift(90, delta / 3);
|
|
|
|
points.frontNeckCpEdge = utils.beamsIntersect(
|
|
|
|
points.neck,
|
|
|
|
points.neckCp2,
|
|
|
|
points.cfNeck,
|
|
|
|
new Point(20, points.cfNeck.y)
|
|
|
|
);
|
|
|
|
points.cfNeckCp1 = points.cfNeck.shiftFractionTowards(
|
|
|
|
points.frontNeckCpEdge,
|
|
|
|
0.55
|
|
|
|
);
|
|
|
|
points.neckCp2Front = points.neck.shiftFractionTowards(
|
|
|
|
points.frontNeckCpEdge,
|
|
|
|
0.65
|
|
|
|
);
|
|
|
|
paths.neckOpening = new Path()
|
|
|
|
.move(points.cfNeck)
|
|
|
|
.curve(points.cfNeckCp1, points.neckCp2Front, points.neck)
|
|
|
|
.curve(points.neckCp2, points.cbNeck, points.cbNeck)
|
|
|
|
.attr("class", "dashed stroke-xl various");
|
|
|
|
delta = paths.neckOpening.length() * 2 - target;
|
|
|
|
} while (Math.abs(delta) > 1 && options.brianFitCollar && run < 10);
|
|
|
|
delete paths.neckOpening;
|
|
|
|
if (options.brianFitCollar) {
|
2018-12-21 19:00:52 +01:00
|
|
|
debug({
|
|
|
|
style: "success",
|
|
|
|
label: "🏁 Collar fitted",
|
|
|
|
msg: `Target was ${units(target)}, delta of ${units(
|
|
|
|
delta
|
|
|
|
)} reached in ${run} attempts.`
|
|
|
|
});
|
2018-12-17 14:42:28 +01:00
|
|
|
} else
|
2018-12-21 19:00:52 +01:00
|
|
|
debug({
|
|
|
|
style: "warning",
|
|
|
|
label: "🚫 Not fittingcollar",
|
|
|
|
msg: "(in Brian)"
|
|
|
|
});
|
2018-08-05 16:32:19 +02:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Anchor point for sampling
|
2018-12-21 12:55:50 +01:00
|
|
|
points.gridAnchor = points.cbHem;
|
2018-09-23 13:14:25 +02:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Seamline
|
|
|
|
paths.saBase = shared.saBase("back", points, Path);
|
|
|
|
paths.seam = new Path()
|
|
|
|
.move(points.cbNeck)
|
2018-12-21 12:55:50 +01:00
|
|
|
.line(points.cbHem)
|
2018-12-17 14:42:28 +01:00
|
|
|
.join(paths.saBase)
|
|
|
|
.attr("class", "fabric");
|
2018-08-05 16:32:19 +02:00
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
// Complete pattern?
|
|
|
|
if (complete) {
|
|
|
|
points.title = new Point(points.armholePitch.x / 2, points.armholePitch.y);
|
|
|
|
points.logo = points.title.shift(-90, 100);
|
|
|
|
snippets.logo = new Snippet("logo", points.logo);
|
2018-07-19 13:14:50 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 14:42:28 +01:00
|
|
|
return part;
|
|
|
|
};
|