From 2d5cdf5806eb35a722b58443d16d25f028b046fc Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Mon, 10 Oct 2022 04:50:43 +0200 Subject: [PATCH] wip(markdown): Work on tutorial --- .../completing-the-neck-opening/en.md | 148 +++++++++++++----- .../constructing-the-neck-opening/en.md | 134 ++++++++++------ .../pattern-design/draft-structure/en.md | 19 ++- .../drawing-the-bib-outline/en.md | 101 +++++++++--- markdown/dev/tutorials/pattern-design/en.md | 8 + .../fitting-the-neck-opening/en.md | 82 ++++++---- 6 files changed, 339 insertions(+), 153 deletions(-) diff --git a/markdown/dev/tutorials/pattern-design/completing-the-neck-opening/en.md b/markdown/dev/tutorials/pattern-design/completing-the-neck-opening/en.md index b930fb06bc0..a49c71027d2 100644 --- a/markdown/dev/tutorials/pattern-design/completing-the-neck-opening/en.md +++ b/markdown/dev/tutorials/pattern-design/completing-the-neck-opening/en.md @@ -3,67 +3,129 @@ title: Completing the neck opening order: 180 --- -## Hiding our quarter neck - We've constructed the perfectly sized quarter neck, and we're going to use this to create our complete neck path by flipping and mirroring it. +## Hiding our quarter neck opening + To make our code easier to understand, we're going to leave the `quarterNeck` path as it is, and simply chose to not show it. -To accomplish this, update the code and add this one line: +To accomplish this, we'll call the `hide()` method on our path: + ```js -paths.quarterNeck = new Path() - .move(points.right) - .curve(points.rightCp1, points.bottomCp2, points.bottom) - .setRender(false) // <== Add this line -``` +function draftBib({ + Path, + Point, + paths, + points, + measurements, + options, + part, +}) { -We're saying: don't render this path. In other words, don't show it. -The path is now known, and we can still use it to calculate the length of the neck opening. + // 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 + + delta = paths.quarterNeck.length() - target + if (delta > 0) tweak = tweak * 0.99 + else tweak = tweak * 1.02 + } while (Math.abs(delta) > 1) + + return part +} +``` + + +We're saying: _hide this path_. In other words, don't show it. +The path is still known, and we can still use it to calculate the length of the neck opening. But it won't show up on screen or on the page. -## Create the complete neck path +## Create the complete neck opening Now that we've hidden our homework, let's create the complete neck path. As the neck opening is symmetrical, there's no need to re-calculate the points -on the other side. You can just flip them over, so to speak. And that's exactly what you'll do. +on the other side. You can just flip them over, so to speak. And that's exactly +what you'll do. -Below your code (under the line with `while` on it), let's add some more points: +Let's add some more points, and then construct the complete path for the neck +opening. + ```js -points.rightCp2 = points.rightCp1.flipY() -points.bottomCp1 = points.bottomCp2.flipX() +function draftBib({ + Path, + Point, + paths, + points, + measurements, + options, + part, +}) { -points.left = points.right.flipX() -points.leftCp1 = points.rightCp2.flipX() -points.leftCp2 = points.rightCp1.flipX() + // 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 + + delta = paths.quarterNeck.length() - target + if (delta > 0) tweak = tweak * 0.99 + else tweak = tweak * 1.02 + } while (Math.abs(delta) > 1) -points.top = points.bottom.flipY() -points.topCp1 = points.bottomCp2.flipY() -points.topCp2 = points.bottomCp1.flipY() + // 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() + + paths.neck = new Path() + .move(points.top) + .curve(points.topCp2, points.leftCp1, points.left) + .curve(points.leftCp2, points.bottomCp1, points.bottom) + .curve(points.bottomCp2, points.rightCp1, points.right) + .curve(points.rightCp2, points.topCp1, points.top) + .close() + .addClass('fabric') + + return part +} ``` - - - -We're using the `Point.flipX()` and `Point.flipY()` methods here. -Perhaps you can figure out what they do? If not, check [the API documentation](/reference/api/point/). - - - -Then, below those new points, and the following code to create your path for the neck opening: - -```js -paths.neck = new Path() - .move(points.top) - .curve(points.topCp2, points.leftCp1, points.left) - .curve(points.leftCp2, points.bottomCp1, points.bottom) - .curve(points.bottomCp2, points.rightCp1, points.right) - .curve(points.rightCp2, points.topCp1, points.top) - .close() -``` - - -And now you have a complete neck opening + +To add the points, we're using the `Point.flipX()` and `Point.flipY()` methods +here. There's a few new Path methods to, like `close()` and `addClass()`. + +Perhaps you can figure out what they do? If not, both [the Point +documentation](/reference/api/point/) and [the Path +documentation](/reference/api/path) have detailed info on all the methods +available, including these. diff --git a/markdown/dev/tutorials/pattern-design/constructing-the-neck-opening/en.md b/markdown/dev/tutorials/pattern-design/constructing-the-neck-opening/en.md index 54ab0a9606d..d7ee97789dc 100644 --- a/markdown/dev/tutorials/pattern-design/constructing-the-neck-opening/en.md +++ b/markdown/dev/tutorials/pattern-design/constructing-the-neck-opening/en.md @@ -3,83 +3,119 @@ title: Constructing the neck opening order: 160 --- -Your goal is to construct a slightly oval neck opening that has a circumference that is -the `head` measurements multiplied by the `neckRatio` option. +Our goal is to construct an oval neck opening that has a circumference +that is the `head` measurements multiplied by the `neckRatio` option. That might involve some trial and error. But since the neck opening will be symetric -both horizontal and vertical, you only need to construct one quadrant. +both horizontal and vertical, we only need to construct one quadrant. -We'll be adding some points to our pattern to do just that. But we want to have access -to our measurements and options to do so. For this, you first update the shorthand call -to indicate you also want access to `measurements` and `options`: +## Desructuring measurements and options -```js -const { - Point, - points, - Path, - paths, - complete, - sa, - paperless, +We'll be adding some points to our pattern to do just that. But we want to have +access to our measurements and options to do so. For this, we first destructure +`measurements` and `options` so we can access them: + +```design/src/bib.mjs +function draftBib({ + Path, + Point, + paths, + points, + // Add the following two lines: measurements, options -} = part.shorthand() + part, +}) { + + return part +} ``` -Great. Now let's get to work: +Great. Now let's get to work. +## Drawing our first path + +Let's add some points, and use them to draw our first curve: + + ```js -// Design pattern here -points.right = new Point(measurements.head / 10, 0) -points.bottom = new Point(0, measurements.head / 12) +function draftBib({ + Path, + Point, + paths, + points, + measurements, + options, + part, +}) { -points.rightCp1 = points.right - .shift(90, points.bottom.dy(points.right)/2) -points.bottomCp2 = points.bottom - .shift(0, points.bottom.dx(points.right)/2) + // Construct the quarter neck opening + points.right = new Point(measurements.head / 10, 0) + points.bottom = new Point(0, 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) -paths.quarterNeck = new Path() - .move(points.right) - .curve(points.rightCp1, points.bottomCp2, points.bottom) + return part +} ``` + -You've added some points to your part, and drawn your first path. Let's look at each line in detail: +You've added some points to your part, and drawn your first path. +Let's look at each line in detail. + +## Adding points ```js points.right = new Point(measurements.head / 10, 0) ``` -- We're adding a point named `right` to `points` which holds our part's points -- We're using the Point constructor, which takes two arguments: The point's X and Y values +- We're adding a point named `right` to the `points` object which holds our + part's points +- We're using the Point constructor, which takes two arguments: The point's X + and Y values - The X value is `measurements.head / 10` - The Y value is `0` -The `bottom` part is very similar, so let's skip to the next line: +The creation of `points.bottom` is very similar, so let's skip to the next line: ```js points.rightCp1 = points.right .shift(90, points.bottom.dy(points.right)/2) ``` -- We're adding a point named `rightCp1`, which will become the _control point_ of the right part -- Instead of using the Point constructor, we're calling the `Point.shift()` method on an existing point +- We're adding a point named `rightCp1`, which will become the _control point_ + of the right part +- Instead of using the Point constructor, we're calling the `Point.shift()` + method on an existing point - It takes two arguments: The angle to shift towards, and the distance -- You can see that we're shifting 90 degrees (that means up) but the distance uses another method -- The `Point.dy()` method returns the delta along the Y axis between the point you call it on and the point you pass it +- You can see that we're shifting 90 degrees (that means up) but the distance + uses another method +- The `Point.dy()` method returns the delta along the Y axis between the point + you call it on and the point you pass it - We shift half of the Y-delta -The next point is very similar again, except that this time we're shifting to the right (0 degrees) for half of -the X-delta between points `bottom` and `right`. +The next point is very similar again, except that this time we're shifting to +the right (0 degrees) for half of the X-delta between points `bottom` and +`right`. - +##### Further reading +The `Point.shift()` and `Point.dy()` are just the tip of the iceberg. Points come with a bunch of these methods. You can find them all in [the Point API docs](/reference/api/point/). - -The next line introduces you to something new: Paths: +## Adding paths + +Adding points is typically merely a means to an end. And that end gets +introduced on the next line: Paths. ```js paths.quarterNeck = new Path() @@ -87,20 +123,20 @@ paths.quarterNeck = new Path() .curve(points.rightCp1, points.bottomCp2, points.bottom) ``` -- We're adding a path named `quarterNeck` to `paths` which holds our part's paths +- We're adding a path named `quarterNeck` to the `paths` object which holds our + part's paths - We're using the Path constructor, which takes no arguments - We're following up with a `Path.move()` call that takes one Point as argument - Then, there's a `Path.curve()` call that takes 3 points as arguments -If you've read through the high-level [Pattern guide](/guides/patterns/) you will have learned that paths -always start with a `move()` operation. In this case, we moved to our `right` points. +If you've read through the high-level [Pattern guide](/guides/patterns) you +will have learned that paths always start with a `move()` operation. In this +case, we moved to our `right` points. -From there, we drew a Bezier curve to our `bottom` point by using `rightCp1` and `bottomCp2` as control points. - -When all is said and done, we now have a quarter of our neck opening: - -You have drawn your first path +From there, we drew a cubic Bezier curve to our `bottom` point by using +`rightCp1` and `bottomCp2` as control points. +When all is said and done, we now have a quarter of our neck opening. The only problem is, we have no guarantee whatsoever that this opening is the correct size. -Rather than hope it is the correct size, you'll make sure it is next. +Rather than hope it is the correct size, we'll make sure it is next. diff --git a/markdown/dev/tutorials/pattern-design/draft-structure/en.md b/markdown/dev/tutorials/pattern-design/draft-structure/en.md index 08f48f78f6f..955c8edf58a 100644 --- a/markdown/dev/tutorials/pattern-design/draft-structure/en.md +++ b/markdown/dev/tutorials/pattern-design/draft-structure/en.md @@ -28,6 +28,16 @@ need to draft your method. Destructuring is a way to *pull things out of the object into their own variable*. It saves us a bunch of typing as these two are equivalent: + + +```design/src/bib.mjs +function draftBib({ part }) { + + return part +} +``` + + ```design/src/bib.mjs function draftBib(props) { @@ -35,13 +45,8 @@ function draftBib(props) { } ``` - -```design/src/bib.mjs -function draftBib({ part }) { - - return part -} -``` + + As we'll make our way through this tutorial, we'll need more and more stuff, so we'll be pulling it out of the object passed to the draft method via diff --git a/markdown/dev/tutorials/pattern-design/drawing-the-bib-outline/en.md b/markdown/dev/tutorials/pattern-design/drawing-the-bib-outline/en.md index 8954c686550..c31b6085161 100644 --- a/markdown/dev/tutorials/pattern-design/drawing-the-bib-outline/en.md +++ b/markdown/dev/tutorials/pattern-design/drawing-the-bib-outline/en.md @@ -3,35 +3,92 @@ title: Drawing the bib outline order: 190 --- -With our neck opening in place, let's draw the basic outline of our bib: +With our neck opening in place, let us draw the basic outline of our bib. + ```js -let width = measurements.head * options.widthRatio -let length = measurements.head * options.lengthRatio +function draftBib({ + Path, + Point, + paths, + points, + measurements, + options, + part, +}) { -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) + // 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 + + delta = paths.quarterNeck.length() - target + if (delta > 0) tweak = tweak * 0.99 + else tweak = tweak * 1.02 + } while (Math.abs(delta) > 1) -paths.rect = new Path() - .move(points.topLeft) - .line(points.bottomLeft) - .line(points.bottomRight) - .line(points.topRight) - .line(points.topLeft) - .close() + // 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() + + paths.neck = new Path() + .move(points.top) + .curve(points.topCp2, points.leftCp1, points.left) + .curve(points.leftCp2, points.bottomCp1, points.bottom) + .curve(points.bottomCp2, points.rightCp1, points.right) + .curve(points.rightCp2, points.topCp1, points.top) + .close() + .addClass('fabric') + + // 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) + + paths.rect = new Path() + .move(points.topLeft) + .line(points.bottomLeft) + .line(points.bottomRight) + .line(points.topRight) + .line(points.topLeft) + .close() + .addClass('fabric') + + return part +} ``` + First thing we did was create the `width` and `length` variables to save ourselves some typing: ```js -let width = measurements.head * options.widthRatio -let length = measurements.head * options.lengthRatio +const width = measurements.head * options.widthRatio +const length = measurements.head * options.lengthRatio ``` Both the length and width of your bib are a factor of the head circumference. @@ -56,13 +113,11 @@ paths.rect = new Path() .line(points.topRight) .line(points.topLeft) .close() + .addClass('fabric') ``` We're calculating the `topLeft` point so that the top edge of our bib and the sides are equidistant from the neck neck opening. -You didn't have to do that. But it looks nicely balanced this way: +We didn't have to do that. But it looks nicely balanced this way. - -Note how the neck opening is the same distance from the left, right, and top edge - diff --git a/markdown/dev/tutorials/pattern-design/en.md b/markdown/dev/tutorials/pattern-design/en.md index 5af9132c11b..6bee3dfd84f 100644 --- a/markdown/dev/tutorials/pattern-design/en.md +++ b/markdown/dev/tutorials/pattern-design/en.md @@ -5,6 +5,14 @@ title: Pattern design tutorial Welcome to the FreeSewing pattern design tutorial, where you'll learn 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 +terminology and concepts that we'll use throughout this guide. + + You will be designing a pattern for a baby bib. It's a very simple pattern, but that's the point. Your focus today is on learning FreeSewing and how to translate your designs into code. diff --git a/markdown/dev/tutorials/pattern-design/fitting-the-neck-opening/en.md b/markdown/dev/tutorials/pattern-design/fitting-the-neck-opening/en.md index 1f7e12b8efb..760f3659897 100644 --- a/markdown/dev/tutorials/pattern-design/fitting-the-neck-opening/en.md +++ b/markdown/dev/tutorials/pattern-design/fitting-the-neck-opening/en.md @@ -3,48 +3,68 @@ title: Fitting the neck opening order: 170 --- -Here's how we'll make sure the neck opening is _just right_: +We are not going to create some opening that we _hope_ is the right size, we're +going to make sure it is. Here's how we'll make sure the neck opening is _just +right_: + ```js -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) +function draftBib({ + Path, + Point, + paths, + points, + measurements, + options, + part, +}) { - points.rightCp1 = points.right.shift(90, points.bottom.dy(points.right)/2) - points.bottomCp2 = points.bottom.shift(0, points.bottom.dx(points.right)/2) + // 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) + + delta = paths.quarterNeck.length() - target + if (delta > 0) tweak = tweak * 0.99 + else tweak = tweak * 1.02 + } while (Math.abs(delta) > 1) - paths.quarterNeck = new Path() - .move(points.right) - .curve(points.rightCp1, points.bottomCp2, points.bottom) - - delta = paths.quarterNeck.length() - target - if (delta > 0) tweak = tweak * 0.99 - else tweak = tweak * 1.02 -} while (Math.abs(delta) > 1) + return part +} ``` + We've added a few new variables: -- `tweak`: A _tweak factor_ that we'll use to increase or decrease the neck opening by making it more or less than 1 +- `tweak`: A _tweak factor_ that we'll use to increase or decrease the neck + opening by making it more or less than 1 - `target`: How long our (quarter) neck opening should be -- `delta`: How far we're off. Positive numbers mean it's too long, negative means too short +- `delta`: How far we're off. Positive numbers mean it's too long, negative + means too short -Now that we know what `target` is, we construct our path as we did before. -But this time around, we multiply our point coordinates with our `tweak` variable (1 at the start). +Now that we know what `target` is, we construct our path as we did before. But +this time around, we multiply our point coordinates with our `tweak` variable +(1 at the start). -Then, we compare our `target` to the result of `paths.neck.length()` which — you guessed it — returns the -length of our neck path. +Then, we compare our `target` to the result of `paths.neck.length()` which — +you guessed it — returns the length of our neck path. -If the delta is positive, our path is too long and we reduce the tweak factor. -If the delta is negative, our path is too short and we increase the tweak factor. +If the delta is positive, our path is too long and we reduce the tweak factor. +If the delta is negative, our path is too short and we increase the tweak +factor. -We keep on doing this until `Math.abs(delta)` is less than 1. Meaning that we are within 1mm of our target value. +We keep on doing this until `Math.abs(delta)` is less than 1. Meaning that we +are within 1mm of our target value. - -It might look the same as before, but now it's just right - - -Now that we're happy with the length of our quarter neck opening, let's construct the entire neck opening. +Now that we're happy with the length of our quarter neck opening, let's +construct the entire neck opening.