🚧 Progress on Sandy
This commit is contained in:
parent
859c5f14fb
commit
dd38a36906
5 changed files with 193 additions and 113 deletions
|
@ -10,17 +10,15 @@ export default {
|
|||
difficulty: 3,
|
||||
tags: ["skirt", "top", "basics"],
|
||||
optionGroups: {
|
||||
fit: ["waistbandPosition"],
|
||||
fit: ["waistbandPosition", "waistbandShape"],
|
||||
style: [
|
||||
"lengthBonus",
|
||||
"circleRatio",
|
||||
"waistbandWidth",
|
||||
"waistbandShape",
|
||||
"waistbandOverlap",
|
||||
"gathering",
|
||||
"seamlessFullCircle",
|
||||
"hemWidth"
|
||||
]
|
||||
"gathering"
|
||||
],
|
||||
construction: ["seamlessFullCircle", "hemWidth"]
|
||||
},
|
||||
measurements: [
|
||||
"naturalWaist",
|
||||
|
@ -32,6 +30,9 @@ export default {
|
|||
waistband: "skirt"
|
||||
},
|
||||
options: {
|
||||
// Constants
|
||||
minimumOverlap: 15, // Lower than this and we don't draw a button
|
||||
|
||||
// Bool
|
||||
seamlessFullCircle: { bool: false },
|
||||
|
||||
|
@ -44,7 +45,7 @@ export default {
|
|||
circleRatio: { pct: 50, min: 20, max: 100 },
|
||||
waistbandOverlap: { pct: 3, min: 0, max: 15 },
|
||||
gathering: { pct: 0, min: 0, max: 200 },
|
||||
hemWidth: { pct: 1, min: 0, max: 5 },
|
||||
hemWidth: { pct: 2, min: 1, max: 10 },
|
||||
|
||||
// Lists
|
||||
waistbandShape: {
|
||||
|
|
|
@ -52,8 +52,61 @@ export default function(part) {
|
|||
|
||||
// Complete pattern?
|
||||
if (complete) {
|
||||
if (sa) {
|
||||
points.title = points.in1Rotated
|
||||
.shiftFractionTowards(points.ex1Rotated, 0.5)
|
||||
.shift(0, 25);
|
||||
macro("title", {
|
||||
at: points.title,
|
||||
nr: 2,
|
||||
title: "curvedWaistband",
|
||||
scale: 0.5
|
||||
});
|
||||
points.grainlineFrom = utils.curveIntersectsY(
|
||||
points.ex2FlippedRotated,
|
||||
points.ex2CFlippedRotated,
|
||||
points.ex1CFlippedRotated,
|
||||
points.ex1Rotated,
|
||||
points.title.y
|
||||
);
|
||||
points.grainlineTo = points.grainlineFrom.flipX();
|
||||
macro("grainline", {
|
||||
from: points.grainlineFrom,
|
||||
to: points.grainlineTo
|
||||
});
|
||||
|
||||
if (store.get("waistbandOverlap") >= options.minimumOverlap) {
|
||||
points.pivot = points.in2Rotated.shiftFractionTowards(
|
||||
points.ex2Rotated,
|
||||
0.5
|
||||
);
|
||||
points.button = points.pivot
|
||||
.shiftTowards(points.ex2Rotated, store.get("waistbandOverlap") / 2)
|
||||
.rotate(-90, points.pivot);
|
||||
points.buttonhole = points.button.flipX();
|
||||
snippets.button = new Snippet("button", points.button);
|
||||
snippets.buttonhole = new Snippet("buttonhole", points.buttonhole).attr(
|
||||
"data-rotate",
|
||||
-1 * points.ex2FlippedRotated.angle(points.in2FlippedRotated)
|
||||
);
|
||||
points.centerNotch = new Path()
|
||||
.move(points.ex1Rotated)
|
||||
.curve(
|
||||
points.ex1CFlippedRotated,
|
||||
points.ex2CFlippedRotated,
|
||||
points.ex2FlippedRotated
|
||||
)
|
||||
.shiftAlong(store.get("waistbandOverlap") / 2);
|
||||
points.buttonNotch = new Path()
|
||||
.move(points.ex2Rotated)
|
||||
.curve(points.ex2CRotated, points.ex1CRotated, points.ex1Rotated)
|
||||
.shiftAlong(store.get("waistbandOverlap"));
|
||||
macro("sprinkle", {
|
||||
snippet: "notch",
|
||||
on: ["centerNotch", "buttonNotch", "ex2FlippedRotated"]
|
||||
});
|
||||
}
|
||||
|
||||
if (sa) paths.sa = paths.seam.offset(sa * -1).attr("class", "fabric sa");
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const draftRingSector = (part, rot, an, radIn, radEx) => {
|
||||
const draftRingSector = (part, rot, an, radIn, radEx, rotate = false) => {
|
||||
let {
|
||||
utils,
|
||||
store,
|
||||
|
@ -101,6 +101,13 @@ const draftRingSector = (part, rot, an, radIn, radEx) => {
|
|||
])
|
||||
points[id + "Rotated"] = points[id].rotate(rot, points.center);
|
||||
|
||||
if (rotate) {
|
||||
// Rotate all points so the line from in1Rotated to ex1Rotated is vertical
|
||||
let deg = 270 - points.in1Rotated.angle(points.ex1Rotated);
|
||||
for (let id in points) {
|
||||
points[id] = points[id].rotate(deg, points.in1Rotated);
|
||||
}
|
||||
}
|
||||
// Return the path of the full ring sector
|
||||
return new Path()
|
||||
.move(points.in2Flipped)
|
||||
|
|
|
@ -18,103 +18,6 @@ export default function(part) {
|
|||
macro
|
||||
} = part.shorthand();
|
||||
|
||||
const oundExtended = (radius, angle = 90) => {
|
||||
let arg = utils.deg2rad(angle / 2);
|
||||
|
||||
return (radius * 4 * (1 - Math.cos(arg))) / Math.sin(arg) / 3;
|
||||
};
|
||||
|
||||
const raftRingSector = (rot, an, radIn, radEx) => {
|
||||
/**
|
||||
* Calculates the distance of the control point for the internal
|
||||
* and external arcs using bezierCircleExtended
|
||||
*/
|
||||
let distIn = roundExtended(radIn, an / 2);
|
||||
let distEx = roundExtended(radEx, an / 2);
|
||||
// The centre of the circles
|
||||
points.center = new Point(0, 0);
|
||||
|
||||
/**
|
||||
* This function is expected to draft ring sectors for
|
||||
* angles up to 180%. Since roundExtended works
|
||||
* best for angles until 90º, we generate the ring
|
||||
* sector using the half angle and then duplicate it
|
||||
*/
|
||||
|
||||
/**
|
||||
* The first point of the internal arc, situated at
|
||||
* a radIn distance below the centre
|
||||
*/
|
||||
points.in1 = points.center.shift(-90, radIn);
|
||||
|
||||
/**
|
||||
* The control point for 'in1'. It's situated at a
|
||||
* distance $distIn calculated with bezierCircleExtended
|
||||
* and the line between it and 'in1' is perpendicular to
|
||||
* the line between 'in1' and the centre, so it's
|
||||
* shifted in the direction 0º
|
||||
*/
|
||||
points.in1C = points.in1.shift(0, distIn);
|
||||
|
||||
/**
|
||||
* The second point of the internal arc, situated at
|
||||
* a $radIn distance of the centre in the direction
|
||||
* $an/2 - 90º
|
||||
*/
|
||||
points.in2 = points.center.shift(an / 2 - 90, radIn);
|
||||
|
||||
/**
|
||||
* The control point for 'in2'. It's situated at a
|
||||
* distance $distIn calculated with bezierCircleExtended
|
||||
* and the line between it and 'in2' is perpendicular to
|
||||
* the line between 'in2' and the centre, so it's
|
||||
* shifted in the direction $an/2 + 180º
|
||||
*/
|
||||
points.in2C = points.in2.shift(an / 2 + 180, distIn);
|
||||
|
||||
/**
|
||||
* The points for the external arc are generated in the
|
||||
* same way, using $radEx and $distEx instead
|
||||
*/
|
||||
points.ex1 = points.center.shift(-90, radEx);
|
||||
points.ex1C = points.ex1.shift(0, distEx);
|
||||
points.ex2 = points.center.shift(an / 2 - 90, radEx);
|
||||
points.ex2C = points.ex2.shift(an / 2 + 180, distEx);
|
||||
|
||||
// Flip all the points to generate the full ring sector
|
||||
for (let id of ["in2", "in2C", "in1C", "ex1C", "ex2C", "ex2"])
|
||||
points[id + "Flipped"] = points[id].flipX();
|
||||
|
||||
// Rotate all the points an angle rot
|
||||
for (let id of [
|
||||
"in1",
|
||||
"in1C",
|
||||
"in2",
|
||||
"in2C",
|
||||
"ex1",
|
||||
"ex1C",
|
||||
"ex2",
|
||||
"ex2C",
|
||||
"in2Flipped",
|
||||
"in2CFlipped",
|
||||
"in1CFlipped",
|
||||
"ex1CFlipped",
|
||||
"ex2CFlipped",
|
||||
"ex2Flipped"
|
||||
])
|
||||
points[id + "Rotated"] = points[id].rotate(rot, points.center);
|
||||
|
||||
// Return the path of the full ring sector
|
||||
return new Path()
|
||||
.move(points.in2Flipped)
|
||||
.curve(points.in2CFlipped, points.in1CFlipped, points.in1)
|
||||
.curve(points.in1C, points.in2C, points.in2)
|
||||
.line(points.ex2)
|
||||
.curve(points.ex2C, points.ex1C, points.ex1)
|
||||
.curve(points.ex1CFlipped, points.ex2CFlipped, points.ex2Flipped)
|
||||
.close();
|
||||
};
|
||||
|
||||
// Circumference of the top of the waistband, calculated from the waistbandPosition option
|
||||
store.set(
|
||||
"topCircumference",
|
||||
|
@ -155,7 +58,6 @@ export default function(part) {
|
|||
measurements.naturalWaistToHip * options.waistbandPosition
|
||||
);
|
||||
|
||||
console.log("STORE", store.data);
|
||||
let radiusWaist, an;
|
||||
if (options.seamlessFullCircle) {
|
||||
/**
|
||||
|
@ -201,17 +103,103 @@ export default function(part) {
|
|||
let rot = an / 2;
|
||||
|
||||
// Call draftRingSector to draft the part
|
||||
paths.seam = draftRingSector(part, rot, an, radiusWaist, radiusHem).attr(
|
||||
"class",
|
||||
"fabric"
|
||||
);
|
||||
paths.seam = draftRingSector(
|
||||
part,
|
||||
rot,
|
||||
an,
|
||||
radiusWaist,
|
||||
radiusHem,
|
||||
true
|
||||
).attr("class", "fabric");
|
||||
|
||||
// Anchor samples to the centre of the waist
|
||||
points.gridAnchor = points.in2Flipped.clone();
|
||||
|
||||
// Complete pattern?
|
||||
if (complete) {
|
||||
macro("cutonfold", {
|
||||
from: points.in2Flipped,
|
||||
to: points.ex2Flipped,
|
||||
grainline: true
|
||||
});
|
||||
if (options.seamlessFullCircle) {
|
||||
macro("cutonfold", {
|
||||
from: points.ex1Rotated,
|
||||
to: points.in1Rotated,
|
||||
prefix: "double"
|
||||
});
|
||||
}
|
||||
points.logo = points.in2FlippedRotated.shiftFractionTowards(
|
||||
points.ex2FlippedRotated,
|
||||
0.3
|
||||
);
|
||||
snippets.logo = new Snippet("logo", points.logo);
|
||||
|
||||
points.title = points.in2FlippedRotated.shiftFractionTowards(
|
||||
points.ex2FlippedRotated,
|
||||
0.5
|
||||
);
|
||||
macro("title", { at: points.title, nr: 1, title: "skirt" });
|
||||
|
||||
points.scalebox = points.in2FlippedRotated.shiftFractionTowards(
|
||||
points.ex2FlippedRotated,
|
||||
0.7
|
||||
);
|
||||
macro("scalebox", { at: points.scalebox });
|
||||
|
||||
macro("sprinkle", {
|
||||
snippet: "notch",
|
||||
on: ["in1Rotated", "gridAnchor"]
|
||||
});
|
||||
|
||||
if (sa) {
|
||||
paths.hemBase = new Path()
|
||||
.move(points.ex1Rotated)
|
||||
.curve(
|
||||
points.ex1CFlippedRotated,
|
||||
points.ex2CFlippedRotated,
|
||||
points.ex2FlippedRotated
|
||||
)
|
||||
.curve(points.ex1CFlipped, points.ex2CFlipped, points.ex2Flipped)
|
||||
.offset(
|
||||
store.get("fullLength") * options.lengthBonus * options.hemWidth * -1
|
||||
);
|
||||
paths.saBase = new Path()
|
||||
.move(points.in2Flipped)
|
||||
.curve(points.in2CFlipped, points.in1CFlipped, points.in2FlippedRotated)
|
||||
.curve(
|
||||
points.in2CFlippedRotated,
|
||||
points.in1CFlippedRotated,
|
||||
points.in1Rotated
|
||||
);
|
||||
if (!options.seamlessFullCircle)
|
||||
paths.saBase = paths.saBase.line(points.ex1Rotated);
|
||||
paths.saBase = paths.saBase.offset(sa * -1);
|
||||
|
||||
paths.hemBase.render = false;
|
||||
paths.saBase.render = false;
|
||||
|
||||
if (options.seamlessFullCircle) {
|
||||
paths.sa = new Path()
|
||||
.move(points.in2Flipped)
|
||||
.line(paths.saBase.start())
|
||||
.join(paths.saBase)
|
||||
.line(points.in1Rotated)
|
||||
.move(points.ex1Rotated)
|
||||
.line(paths.hemBase.start())
|
||||
.join(paths.hemBase)
|
||||
.line(points.ex2Flipped)
|
||||
.attr("class", "fabric sa");
|
||||
} else {
|
||||
paths.sa = new Path()
|
||||
.move(points.in2Flipped)
|
||||
.line(paths.saBase.start())
|
||||
.join(paths.saBase)
|
||||
.line(paths.hemBase.start())
|
||||
.join(paths.hemBase)
|
||||
.line(points.ex2Flipped)
|
||||
.attr("class", "fabric sa");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,39 @@ export default function(part) {
|
|||
|
||||
// Complete pattern?
|
||||
if (complete) {
|
||||
if (sa) {
|
||||
}
|
||||
points.title = points.center.shiftFractionTowards(points.centerRight, 0.5);
|
||||
macro("title", { at: points.title, nr: 2, title: "straightWaistband" });
|
||||
points.grainlineFrom = points.centerLeft.shiftFractionTowards(
|
||||
points.topLeft,
|
||||
0.5
|
||||
);
|
||||
points.grainlineTo = points.grainlineFrom.flipX();
|
||||
macro("grainline", {
|
||||
from: points.grainlineFrom,
|
||||
to: points.grainlineTo
|
||||
});
|
||||
points.button = points.centerRight
|
||||
.shiftFractionTowards(points.bottomRight, 0.5)
|
||||
.shift(180, store.get("waistbandOverlap") / 2);
|
||||
points.buttonhole = points.centerLeft
|
||||
.shiftFractionTowards(points.bottomLeft, 0.5)
|
||||
.shift(0, store.get("waistbandOverlap") / 2);
|
||||
snippets.button = new Snippet("button", points.button);
|
||||
snippets.buttonhole = new Snippet("buttonhole", points.buttonhole);
|
||||
points.centerNotch = new Point(
|
||||
(-1 * store.get("waistbandOverlap")) / 2,
|
||||
points.bottomLeft.y
|
||||
);
|
||||
points.buttonNotch = points.bottomRight.shift(
|
||||
180,
|
||||
store.get("waistbandOverlap")
|
||||
);
|
||||
macro("sprinkle", {
|
||||
snippet: "notch",
|
||||
on: ["centerNotch", "buttonNotch", "bottomLeft"]
|
||||
});
|
||||
|
||||
if (sa) paths.sa = paths.seam.offset(sa).attr("class", "fabric sa");
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue