-```design/src/bib.mjs
+```src/bib.mjs
function draftBib({
Path,
Point,
diff --git a/markdown/dev/tutorials/pattern-design/part2/drawing-the-straps/en.md b/markdown/dev/tutorials/pattern-design/part2/drawing-the-straps/en.md
index 35a7682f973..5a03fa78692 100644
--- a/markdown/dev/tutorials/pattern-design/part2/drawing-the-straps/en.md
+++ b/markdown/dev/tutorials/pattern-design/part2/drawing-the-straps/en.md
@@ -23,13 +23,16 @@ function draftBib({
points,
measurements,
options,
+ utils,
macro,
part,
}) {
- // Construct the quarter neck opening
+ /*
+ * Construct the neck opening
+ */
+ const target = (measurements.head * options.neckRatio) / 4
let tweak = 1
- let target = (measurements.head * options.neckRatio) /4
let delta
do {
points.right = new Point(tweak * measurements.head / 10, 0)
@@ -116,32 +119,47 @@ function draftBib({
points.tipRightTop = new Point(points.tipRight.x, points.edgeTop.y)
points.tipRightBottom = new Point(points.tipRight.x, points.top.y)
- macro("round", {
- from: points.edgeTop,
- to: points.tipRight,
- via: points.tipRightTop,
- prefix: "tipRightTop",
- // strikeout-start
- /* Remove this to have the macro
- * only create the points we need
- * and not draw a path
- hide: false
- */
- // strikeout-end
- })
- macro("round", {
- from: points.tipRight,
- to: points.top,
- via: points.tipRightBottom,
- prefix: "tipRightBottom",
- // strikeout-start
- /* Remove this to have the macro
- * only create the points we need
- * and not draw a path
- hide: false
- */
- // strikeout-end
- })
+ /*
+ * Macros will return the auto-generated IDs
+ */
+ const ids1 = {
+ tipRightTop: macro("round", {
+ id: "tipRightTop",
+ from: points.edgeTop,
+ to: points.tipRight,
+ via: points.tipRightTop,
+ // strikeout-start
+ /* Remove this to have the macro
+ * only create the points we need
+ * and not draw a path
+ hide: false
+ */
+ // strikeout-end
+ }),
+ tipRightBottom: macro("round", {
+ id: "tipRightBottom",
+ from: points.tipRight,
+ to: points.top,
+ via: points.tipRightBottom,
+ // strikeout-start
+ /* Remove this to have the macro
+ * only create the points we need
+ * and not draw a path
+ hide: false
+ */
+ // strikeout-end
+ })
+ }
+
+ /*
+ * Create points from them with easy names
+ */
+ for (const side in ids1) {
+ for (const id of ['start', 'cp1', 'cp2', 'end']) {
+ points[`${side}${utils.capitalize(id)}`] = points[ids1[side].points[id]].copy()
+ }
+ }
+
const rotateThese = [
"edgeTopLeftCp",
"edgeTop",
diff --git a/markdown/dev/tutorials/pattern-design/part2/en.md b/markdown/dev/tutorials/pattern-design/part2/en.md
index aa77d6d9236..1b895041497 100644
--- a/markdown/dev/tutorials/pattern-design/part2/en.md
+++ b/markdown/dev/tutorials/pattern-design/part2/en.md
@@ -2,267 +2,44 @@
title: "Part 2: Parametric design"
---
-Hello there, and welcome to this FreeSewing pattern design tutorial.
-My name is Joost, and in this tutorial I will show you
-how to design a made-to-measure sewing pattern, start to finish.
+Welcome to part 2 of this FreeSewing pattern design tutorial.
+In this part I will show you how to design a made-to-measure
+sewing pattern, start to finish.
##### Before you start
-If you haven't done so yet, read the [Before you start
-guide](/guides/prerequisites). It's very short, but covers some basic
+This tutorial assumes you are familiar with the following:
+
+- Scalable Vector Graphics
+- The coordinate system
+- Units in FreeSewing
+- Cubic Bézier curves
+
+Which is a lot to assume. So if you'd like you can take a quick detour
+via our [Before you start guide](/guides/prerequisites). \
+It's very short, but covers some basic
terminology and concepts that we'll use throughout this guide.
-I will be designing a pattern for a baby bib. It's a very simple pattern, but
-that's ok. It is a tutorial after all. This will give us plenty to work with.
+## Pick a template
-At the end of this tutorial, I will have created this pattern, and if you
-follow along, so will you:
+The FreeSewing development environment ships with several templates you
+can start from. I recommend you start **From scratch** as you'll learn the most
+that way. But you can also start from the **Tutorial** template in which case
+you will already have the end result we are aiming for today:
+
-
-```design/src/bib.mjs
-function draftBib({
- Path,
- Point,
- paths,
- points,
- measurements,
- options,
- macro,
- store,
- complete,
- snippets,
- Snippet,
- part,
-}) {
+
- /*
- * Construct the quarter neck opening
- */
- let tweak = 1
- let target = (measurements.head * options.neckRatio) /4
- let delta
- do {
- points.right = new Point(tweak * measurements.head / 10, 0)
- points.bottom = new Point(0, tweak * measurements.head / 12)
+
- points.rightCp1 = points.right.shift(90, points.bottom.dy(points.right)/2)
- points.bottomCp2 = points.bottom.shift(0, points.bottom.dx(points.right)/2)
+
- paths.quarterNeck = new Path()
- .move(points.right)
- .curve(points.rightCp1, points.bottomCp2, points.bottom)
- .hide() // Add this line
+Depending on the choice you made, you will need to edit files in a different folder.
- delta = paths.quarterNeck.length() - target
- if (delta > 0) tweak = tweak * 0.99
- else tweak = tweak * 1.02
- } while (Math.abs(delta) > 1)
+- Edit files in `design/from-scratch` if you are using the **From scratch** template
+- Edit files in `design/tutorial` if you are using the **Tutorial** template
- /*
- * Construct the complete neck opening
- */
- points.rightCp2 = points.rightCp1.flipY()
- points.bottomCp1 = points.bottomCp2.flipX()
- points.left = points.right.flipX()
- points.leftCp1 = points.rightCp2.flipX()
- points.leftCp2 = points.rightCp1.flipX()
- points.top = points.bottom.flipY()
- points.topCp1 = points.bottomCp2.flipY()
- points.topCp2 = points.bottomCp1.flipY()
-
- /*
- * Drawing the bib outline
- */
- const width = measurements.head * options.widthRatio
- const length = measurements.head * options.lengthRatio
-
- points.topLeft = new Point(
- width / -2,
- points.top.y - (width / 2 - points.right.x)
- )
- points.topRight = points.topLeft.shift(0, width)
- points.bottomLeft = points.topLeft.shift(-90, length)
- points.bottomRight = points.topRight.shift(-90, length)
-
- // Shape the straps
- points.edgeLeft = new Point(points.topLeft.x, points.left.y)
- points.edgeRight = new Point(points.topRight.x, points.right.y)
- points.edgeTop = new Point(0, points.topLeft.y)
-
- points.edgeLeftCp = points.edgeLeft.shiftFractionTowards(points.topLeft, 0.5)
- points.edgeRightCp = points.edgeLeftCp.flipX()
- points.edgeTopLeftCp = points.edgeTop.shiftFractionTowards(
- points.topLeft,
- 0.5
- )
- points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
-
- /*
- * Round the straps
- */
- const strap = points.edgeTop.dy(points.top)
-
- points.tipRight = points.edgeTop.translate(strap / 2, strap / 2)
- points.tipRightTop = new Point(points.tipRight.x, points.edgeTop.y)
- points.tipRightBottom = new Point(points.tipRight.x, points.top.y)
-
- macro("round", {
- from: points.edgeTop,
- to: points.tipRight,
- via: points.tipRightTop,
- prefix: "tipRightTop",
- })
- macro("round", {
- from: points.tipRight,
- to: points.top,
- via: points.tipRightBottom,
- prefix: "tipRightBottom",
- })
- const rotateThese = [
- "edgeTopLeftCp",
- "edgeTop",
- "tipRight",
- "tipRightTop",
- "tipRightTopStart",
- "tipRightTopCp1",
- "tipRightTopCp2",
- "tipRightTopEnd",
- "tipRightBottomStart",
- "tipRightBottomCp1",
- "tipRightBottomCp2",
- "tipRightBottomEnd",
- "tipRightBottom",
- "top",
- "topCp2"
- ]
- while (points.tipRightBottomStart.x > -1) {
- for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
- }
-
- /*
- * Snap anchor
- */
- points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
-
- /*
- * Add points for second strap
- */
- points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
- points.topCp1 = points.topCp2.flipX()
- points.tipLeftTopStart = points.tipRightTopStart.flipX()
- points.tipLeftTopCp1 = points.tipRightTopCp1.flipX()
- points.tipLeftTopCp2 = points.tipRightTopCp2.flipX()
- points.tipLeftTopEnd = points.tipRightTopEnd.flipX()
- points.tipLeftBottomStart = points.tipRightBottomStart.flipX()
- points.tipLeftBottomCp1 = points.tipRightBottomCp1.flipX()
- points.tipLeftBottomCp2 = points.tipRightBottomCp2.flipX()
- points.tipLeftBottomEnd = points.tipRightBottomEnd.flipX()
- points.snapRight = points.snapLeft.flipX()
-
- /*
- * Round the bottom corners
- */
- macro("round", {
- from: points.topLeft,
- to: points.bottomRight,
- via: points.bottomLeft,
- radius: points.bottomRight.x / 4,
- prefix: "bottomLeft"
- })
- macro("round", {
- from: points.bottomLeft,
- to: points.topRight,
- via: points.bottomRight,
- radius: points.bottomRight.x / 4,
- prefix: "bottomRight"
- })
-
- /*
- * Create one path for the bib outline
- */
- paths.seam = new Path()
- .move(points.edgeLeft)
- .line(points.bottomLeftStart)
- .curve(points.bottomLeftCp1, points.bottomLeftCp2, points.bottomLeftEnd)
- .line(points.bottomRightStart)
- .curve(points.bottomRightCp1, points.bottomRightCp2, points.bottomRightEnd)
- .line(points.edgeRight)
- .curve(points.edgeRightCp, points.edgeTopRightCp, points.tipLeftTopStart)
- .curve(points.tipLeftTopCp1, points.tipLeftTopCp2, points.tipLeftTopEnd)
- .curve(points.tipLeftBottomCp1, points.tipLeftBottomCp2, points.tipLeftBottomEnd)
- .curve(points.topCp1, points.rightCp2, points.right)
- .curve(points.rightCp1, points.bottomCp2, points.bottom)
- .curve(points.bottomCp1, points.leftCp2, points.left)
- .curve(points.leftCp1, points.topCp2, points.tipRightBottomEnd)
- .curve(points.tipRightBottomCp2, points.tipRightBottomCp1, points.tipRightBottomStart)
- .curve(points.tipRightTopCp2, points.tipRightTopCp1, points.tipRightTopStart)
- .curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
- .close()
- .addClass("fabric")
-
- /*
- * Mark the bias tape, but only if complete is set
- */
- if (complete) paths.bias = paths.seam
- .offset(-5)
- .addClass("various dashed")
- .addText("finishWithBiasTape", "center fill-various")
- /*
- * Annotations
- */
-
- // Cutlist
- store.cutlist.setCut({ cut: 1, from: 'fabric' })
-
- // Snaps
- points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
- points.snapRight = points.snapLeft.flipX()
- snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
- snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
-
- // Logo
- points.logo = new Point(0, 0)
- snippets.logo = new Snippet("logo", points.logo)
-
- // Title
- points.title = points.bottom.shift(-90, 45)
- macro("title", {
- at: points.title,
- nr: 1,
- title: "bib",
- scale: 0.7
- })
-
- // Scalbox
- points.scalebox = points.title.shift(-90, 55)
- macro("scalebox", { at: points.scalebox })
-
- return part
-}
-```
-
-
-## Prerequisites
-
-Before I can get started, I want to make sure I have the required software
-installed on my computer.
-
-FreeSewing is a JavaScript library that can run in the browser, on
-[Node.js](https://nodejs.org/), or a variety of other runtimes such as Bun,
-Deno, AWS Lambda, and so on.
-
-For development, I will use Node.js. If you don't have Node.js on our system,
-follow the link above and install it.
-
-