1
0
Fork 0

chore: Port FreeSewing.dev to docusaurus

The replaces the NextJS site powering FreeSewing.dev with a Docusaurus
setup. It's part of my efforts to simplify FreeSewing's setup so we can
focus on our core value proposition.
This commit is contained in:
Joost De Cock 2024-09-28 13:13:48 +02:00
parent 497633d1d3
commit ab3204f9f1
692 changed files with 11037 additions and 20674 deletions

View file

@ -0,0 +1,18 @@
---
title: utils.applyTransformToPoint()
---
The `utils.applyTransformToPoint()` function applies a specified transformation to the point's coordinates. Returns the transformed point as a [Point](/reference/api/point) object.
## Signature
```js
Point utils.applyTransformToPoint(string transform, Point A)
```
## Parameters
1st parameter is a SVG transform string. E.g.: `scale(sfx, sfy)` where `sfx` and `sfy` are the scaling factors along the x-axis and y-axis respectively.
2nd parameter is the original point that is to be transformed. It is a [Point](/reference/api/point) object.

View file

@ -0,0 +1,80 @@
---
title: utils.beamIntersectsCircle()
---
The `utils.beamIntersectsCircle()` function finds the intersection between an
endless line through points `point1` and `point2` and a circle with its center
at point `center` and a radius of `radius` mm.
## Signature
```js
array | false utils.beamIntersectsCircle(
Point center,
float radius,
Point point1,
Point point1,
string sort=x
)
```
The 5th and last parameter controls the _sorting_ of the found intersections.
This will (almost) always return 2 intersections, and you can choose how
they are ordered in the returned array:
Set sort to:
- `x` : The point with the lowest X-coordinate will go first (left to right)
- `y` : The point with the lowest Y-coordinate will go first (top to bottom)
## Example
<Example caption="A utils.beamIntersectsCircle() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.A = new Point(45, 45)
.addCircle(35, "Fabric")
points.B = new Point(5, 50)
points.C = new Point(25, 30)
points.D = new Point(5, 65)
points.E = new Point(65, 5)
points.F = new Point(15, 75)
points.G = new Point(75, 15)
paths.line1 = new Path().move(points.B).line(points.C)
paths.line2 = new Path().move(points.D).line(points.E)
paths.line3 = new Path().move(points.F).line(points.G)
let intersections1 = utils.beamIntersectsCircle(
points.A,
points.A.attributes.get("data-circle"),
points.B,
points.C
)
let intersections2 = utils.beamIntersectsCircle(
points.A,
points.A.attributes.get("data-circle"),
points.D,
points.E,
"y"
)
let intersections3 = utils.beamIntersectsCircle(
points.A,
points.A.attributes.get("data-circle"),
points.F,
points.G
)
snippets.first1 = new Snippet("bnotch", intersections1[0])
snippets.second1 = new Snippet("notch", intersections1[1])
snippets.first2 = new Snippet("bnotch", intersections2[0])
snippets.second2 = new Snippet("notch", intersections2[1])
snippets.first3 = new Snippet("bnotch", intersections3[0])
snippets.second3 = new Snippet("notch", intersections3[1])
return part
}
```
</Example>

View file

@ -0,0 +1,62 @@
---
title: utils.beamIntersectsCurve()
---
The `utils.beamIntersectsCurve()` function finds the intersection between an endless
line and a curve described by points
`start`, `cp1`, `cp2`, and `end`.
:::warning
This function can sometimes fail to find intersections in some curves
due to a limitation in an underlying Bézier library.
Please see [Bug #3367](https://github.com/freesewing/freesewing/issues/3367)
for more information.
:::
## Signature
```js
array | false utils.beamIntersectsCurve(
Point from,
Point to,
Point start,
Point cp1,
Point cp2,
Point end
)
```
## Example
<Example caption="A Utils.beamIntersectsCurve() example">
```js
({ Point, points, Path, paths, Snippet, snippets, getId, utils, part }) => {
points.A = new Point(10, 10)
points.Acp = new Point(10, 40)
points.B = new Point(110, 10)
points.Bcp = new Point(110, 40)
points.E = new Point(45, 25)
points.D = new Point(65, 25)
paths.curve = new Path()
.move(points.A)
.curve(points.Acp, points.Bcp, points.B)
paths.line = new Path().move(points.E).line(points.D)
for (let p of utils.beamIntersectsCurve(
points.D,
points.E,
points.A,
points.Acp,
points.Bcp,
points.B
)) {
snippets[getId()] = new Snippet("notch", p)
}
return part
}
```
</Example>

View file

@ -0,0 +1,40 @@
---
title: utils.beamIntersectsX()
---
The `utils.beamIntersectsX()` function finds the intersection between an endless
line and a given X-value. Returns a [Point](/reference/api/point) object for
the intersection, or `false` there is no intersection.
## Signature
```js
Point | false utils.beamIntersectsX(Point A, Point B, float X)
```
## Example
<Example caption="A Utils.beamIntersectsX() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.A = new Point(10, 10)
points.B = new Point(90, 30)
paths.AB = new Path().move(points.A).line(points.B)
snippets.x = new Snippet(
"notch",
utils.beamIntersectsX(points.A, points.B, 40)
)
paths.help = new Path()
.move(new Point(40, 5))
.line(new Point(40, 35))
.addClass("note dashed")
return part
}
```
</Example>

View file

@ -0,0 +1,40 @@
---
title: utils.beamIntersectsY()
---
The `utils.beamIntersectsY()` function finds the intersection between an endless
line and a given Y-value. Returns a [Point](/reference/api/point) object for
the intersection, or `false` there is no intersection.
## Signature
```js
Point | false utils.beamIntersectsY(Point A, Point B, float Y)
```
## Example
<Example caption="A Utils.beamIntersectsY() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.A = new Point(10, 10)
points.B = new Point(50, 40)
paths.AB = new Path().move(points.A).line(points.B)
snippets.x = new Snippet(
"notch",
utils.beamIntersectsY(points.A, points.B, 30)
)
paths.help = new Path()
.move(new Point(0, 30))
.line(new Point(50, 30))
.attr("class", "note dashed")
return part
}
```
</Example>

View file

@ -0,0 +1,43 @@
---
title: utils.beamsIntersect()
---
The `utils.beamsIntersect()` function finds the intersection between two endless
lines (beams). Returns a [Point](/reference/api/point) object for the
intersection, or `false` if the lines don't intersect.
## Signature
```js
Point | false utils.beamsIntersect(
Point A,
Point B,
Point C,
Point D
)
```
## Example
<Example caption="A Utils.beamIntersect() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.A = new Point(10, 10)
points.B = new Point(50, 40)
points.C = new Point(45, 20)
points.D = new Point(60, 15)
paths.AB = new Path().move(points.A).line(points.B)
paths.CD = new Path().move(points.C).line(points.D)
snippets.x = new Snippet(
"notch",
utils.beamsIntersect(points.A, points.B, points.C, points.D)
)
return part
}
```
</Example>

View file

@ -0,0 +1,19 @@
---
title: utils.capitalize()
---
The `utils.capitalize()` function returns the string you pass it with its first
letter turned into uppercase.
## Signature
```js
String utils.capitalize(String input)
```
## Example
```js
capitalize('hello') // returns 'Hello')
capitalize('hello there') // returns 'Hello there'
```

View file

@ -0,0 +1,66 @@
---
title: utils.circlesIntersect()
---
The `utils.circlesIntersect()` function finds the intersections between two
circles described by their center point and radius.
## Signature
```js
array | false utils.circlesIntersect(
Point centerA,
float radiusA,
Point centerB,
float radiusB,
string sort = 'x'
)
```
The 5th and last parameter controls the _sorting_ of the found intersections.
When this returns 2 intersections, you can choose how they are ordered in the returned array:
Set sort to:
- `x` : The point with the lowest X-coordinate will go first (left to right)
- `y` : The point with the lowest Y-coordinate will go first (top to bottom)
## Example
<Example caption="A Utils.circlesIntersect() example">
```js
({ Point, points, Snippet, snippets, utils, part }) => {
points.A = new Point(10, 10)
.addCircle(15, "fabric")
points.B = new Point(30, 30)
.addCircle(35, "fabric")
points.C = new Point(90, 10)
.addCircle(15, "various")
points.D = new Point(110, 30)
.addCircle(35, "various")
const intersections1 = utils.circlesIntersect(
points.A,
points.A.attributes.get("data-circle"),
points.B,
points.B.attributes.get("data-circle")
)
const intersections2 = utils.circlesIntersect(
points.C,
points.C.attributes.get("data-circle"),
points.D,
points.D.attributes.get("data-circle"),
"y"
)
snippets.first1 = new Snippet("bnotch", intersections1[0])
snippets.second1 = new Snippet("notch", intersections1[1])
snippets.first2 = new Snippet("bnotch", intersections2[0])
snippets.second2 = new Snippet("notch", intersections2[1])
return part
}
```
</Example>

View file

@ -0,0 +1,16 @@
---
title: utils.combineTransform()
---
The `utils.combineTransform()` function merges an array of SVG transformations into a single composite matrix transformation. Returns a single combined matrix transform string.
## Signature
```js
string utils.combineTransforms(string[] transforms)
```
## Parameters
The function only takes a single parameter i.e array of transform strings. Eg: `["scale(sfx, sfy)", rotate(angle), translate(tx, ty)]`

View file

@ -0,0 +1,46 @@
---
title: utils.curveEdge()
---
The `utils.curveEdge()` function finds the edge of a cubic Bézier curve,
given the curve, the edge to find ("top", "bottom", "left", or "right"),
and the number of steps to divide the curve into while walking it.
## Signature
```js
Point utils.curveEdge(
Bezier curve,
string edge,
int steps = 500)
```
## Example
<Example caption="A Utils.curveEdge() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, Bezier, part }) => {
points.A = new Point(20, 10)
points.Acp = new Point(310, 40)
points.Bcp = new Point(-210, 40)
points.B = new Point(100, 70)
paths.pathA = new Path()
.move(points.A)
.curve(points.Acp, points.Bcp, points.B)
const curveA = new Bezier(
{ x: points.A.x, y: points.A.y },
{ x: points.Acp.x, y: points.Acp.y },
{ x: points.Bcp.x, y: points.Bcp.y },
{ x: points.B.x, y: points.B.y }
)
points.edge = utils.curveEdge(curveA, "left")
snippets.edge = new Snippet("notch", points.edge)
return part
}
```
</Example>

View file

@ -0,0 +1,83 @@
---
title: utils.curveIntersectsX()
---
The `utils.curveIntersectsX()` function finds the point(s) where a curve
intersects a given X-value.
:::warning
This function can sometimes fail to find intersections in some curves
due to a limitation in an underlying Bézier library.
Please see [Bug #3367](https://github.com/freesewing/freesewing/issues/3367)
for more information.
:::
## Signature
```js
array | Point | false utils.curveIntersectsX(
Point start,
Point cp1,
Point cp2,
Point end,
float x)
```
This returns `false` if no intersections are found,
a [Point](/reference/api/point) object if
a single intersection is found, and an array
of [Point](/reference/api/point) objects if
multiple intersections are found.
## Example
<Example caption="A Utils.curveIntersectX() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.start = new Point(10, 15)
points.cp1 = new Point(80, 10)
points.cp2 = new Point(-50, 80)
points.end = new Point(110, 70)
paths.curve = new Path()
.move(points.start)
.curve(points.cp1, points.cp2, points.end)
for (let x of [30, 40]) {
points["from" + x] = new Point(x, 10)
points["to" + x] = new Point(x, 80)
paths["line" + x] = new Path()
.move(points["from" + x])
.line(points["to" + x])
.addClass("lining dashed")
}
snippets.i40 = new Snippet(
"notch",
utils.curveIntersectsX(points.start, points.cp1, points.cp2, points.end, 40)
)
for (let p of utils.curveIntersectsX(
points.start,
points.cp1,
points.cp2,
points.end,
30
))
snippets[p.y] = new Snippet("notch", p)
return part
}
```
</Example>
## Notes
This is a low-level (and faster) variant
of [`Path.intersectsX()`](/reference/api/path/intersectsx).
Instead of a path, you describe a single curve by passing the four
points that describes it.

View file

@ -0,0 +1,82 @@
---
title: utils.curveIntersectsY()
---
The `utils.curveIntersectsY()` function finds the point(s) where a curve
intersects a given Y-value.
:::warning
This function can sometimes fail to find intersections in some curves
due to a limitation in an underlying Bézier library.
Please see [Bug #3367](https://github.com/freesewing/freesewing/issues/3367)
for more information.
:::
## Signature
```js
array | Point | false utils.curveIntersectsY(
Point start,
Point cp1,
Point cp2,
Point end,
float y)
```
This returns `false` if no intersections are found,
a [Point](/reference/api/point/) object if
a single intersection is found, and an array
of [Point](/reference/api/point/) objects if
multiple intersections are found.
## Example
<Example caption="A Utils.curveIntersectY() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.start = new Point(10, 45)
points.cp1 = new Point(50, 10)
points.cp2 = new Point(0, 80)
points.end = new Point(110, 70)
paths.curve = new Path()
.move(points.start)
.curve(points.cp1, points.cp2, points.end)
for (let y of [40, 50]) {
points["from" + y] = new Point(10, y)
points["to" + y] = new Point(110, y)
paths["line" + y] = new Path()
.move(points["from" + y])
.line(points["to" + y])
.addClass("lining dashed")
}
snippets.i50 = new Snippet(
"notch",
utils.curveIntersectsY(points.start, points.cp1, points.cp2, points.end, 50)
)
for (let p of utils.curveIntersectsY(
points.start,
points.cp1,
points.cp2,
points.end,
40
))
snippets[p.x] = new Snippet("notch", p)
return part
}
```
</Example>
## Notes
This is a low-level (and faster) variant
of [`Path.intersectsY()`](/reference/api/path/intersectsy).
Instead of a path, you describe a single curve by passing the four
points that describes it.

View file

@ -0,0 +1,77 @@
---
title: utils.curveParameterFromPoint()
---
The `utils.curveParameterFromPoint()` function calculates where the point `check` lies on a
curve described by points `start`, `cp1`, `cp2`, and `end`.
For example a return value of 0 indicates that the given point is the start of the curve, a return value
of 1 indicated that the given point is identical to the end of the curve.
A return value of 0.5 indicates that the start point and the first control point had the same influence
as the end point and the second control point, to create the checked point, but this doesn't necessarily mean
that the point lies exactly half-way on the curve.
This method returns `false` if the point isn't (approximately) located on the curve.
## Signature
```js
number|false utils.curveParameterFromPoint(
Point start,
Point cp1,
Point cp2,
Point end,
Point check
)
```
## Example
<Example caption="A Utils.curveParameterFromPoint() example">
```js
({ Point, points, Path, paths, Snippet, snippets, getId, utils, part }) => {
points.start = new Point(10, 10)
points.cp1 = new Point(90, 30)
points.cp2 = new Point(10, 40)
points.end = new Point(90, 60)
const scatter = []
for (let i = 1; i < 19; i++) {
for (let j = 1; j < 14; j++) {
scatter.push(new Point(i * 10, j * 10))
}
}
let snippet
for (let point of scatter) {
let t = utils.curveParameterFromPoint(
points.start,
points.cp1,
points.cp2,
points.end,
point
)
if(t !== false) {
points[getId()] = point.addText(` ${Math.round(t * 100) / 100}`, 'text-sm')
snippets[getId()] = new Snippet('notch', point)
}
}
paths.curve = new Path()
.move(points.start)
.curve(points.cp1, points.cp2, points.end)
.addClass("fabric stroke-lg")
return part
}
```
</Example>
## Notes
Keep in mind that calculations with Bézier curves are often approximations.
This method is mostly used as internal building block for methods like
`utils.pointOnCurve()`, `Path.split()` or `Path.angleAt()` and probably is not very relevant
for direct usage from pattern code.

View file

@ -0,0 +1,82 @@
---
title: utils.curvesIntersect()
---
The `utils.curvesIntersect()` function finds the intersections between two curves
described by 4 points each.
:::warning
This function can sometimes fail to find intersections in some curves
due to a limitation in an underlying Bézier library.
Please see [Bug #3367](https://github.com/freesewing/freesewing/issues/3367)
for more information.
:::
## Signature
```js
array | Point | false utils.curvesIntersect(
Point startA,
Point Cp1A,
Point Cp2A,
Point endA,
Point startB,
Point Cp1B,
Point Cp2B,
Point endB)
```
This returns `false` if no intersections are found,
a [Point](/reference/api/point) object if
a single intersection is found, and an array
of [Point](/reference/api/point) objects if
multiple intersections are found.
## Example
<Example caption="A Utils.curvesIntersect() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, getId, part }) => {
points.A = new Point(10, 10)
points.Acp = new Point(310, 40)
points.B = new Point(110, 70)
points.Bcp = new Point(-210, 40)
points.C = new Point(20, -5)
points.Ccp = new Point(60, 300)
points.D = new Point(100, 85)
points.Dcp = new Point(70, -220)
paths.curveA = new Path()
.move(points.A)
.curve(points.Acp, points.Bcp, points.B)
paths.curveB = new Path()
.move(points.C)
.curve(points.Ccp, points.Dcp, points.D)
const intersections = utils.curvesIntersect(
points.A,
points.Acp,
points.Bcp,
points.B,
points.C,
points.Ccp,
points.Dcp,
points.D
)
if (intersections) {
if (intersections instanceof Array) {
for (const p of intersections)
snippets[getId()] = new Snippet('notch', p)
} else {
snippets[getId()] = new Snippet('notch', intersections)
}
}
return part
}
```
</Example>

View file

@ -0,0 +1,16 @@
---
title: utils.deg2rad()
---
The `utils.deg2read()` function returns the degrees you pass to it as radians.
## Signature
```js
float utils.deg2rad(float degrees)
```
## Notes
This is useful for when you use functions like `Math.cos()` that expect a corner
in radians, when we typically use degrees.

View file

@ -0,0 +1,34 @@
---
title: utils.generateStackTransform()
---
The `utils.generateStackTransform()` function will generate the SVG transform to implement a given layout configuration on [a stack](/reference/api/stack).
## Signature
```js
Array generateStackTransform(
Number x = 0,
Number y = 0,
Number rotate = 0,
Boolean flipX = false,
Boolean flipY = false,
Stack stack
)
```
## Parameters
The first and second parameters set the value of the *translate transform* along the X and Y axis in millimeter.
In other words, it moves the stack.
The third parameter sets the *rotate transform* in degrees.
In other words, it rotates the stack.
The fourth and fifth parameters flip the part along the X or Y axis respectively.
:::note
This is a low-level function to facilitate intervening in the pattern layout late in the draft process.
It is unlikely you will want to use this.
:::

View file

@ -0,0 +1,22 @@
---
title: utils.getTransformedBounds()
---
The `utils.getTransformedBounds()` function re-calculates the bounding box of an object (a stack or a part) after applying the passed-in transform(s).
The object passed in should have its `topLeft` and `bottomRight` properties set.
It will return on object that with (only) the updated `topLeft` and `bottomRight` properties set.
## Signature
```js
Object utils.getTransformedBounds(
Object stack,
Array transforms
)
```
:::note
This is a low-level function to facilitate intervening in the pattern layout late in the draft process.
It is unlikely you will want to use this.
:::

View file

@ -0,0 +1,78 @@
---
title: utils.lineIntersectsCircle()
---
The `utils.lineIntersectsCircle()` function finds the intersection between a line
segment from point `from` to point `to` and a circle with its center at point
`center` and a radius of `radius` mm.
## Signature
```js
array | false utils.lineIntersectsCircle(
Point center,
float radius,
Point from,
Point to,
string sort = 'x'
)
```
The 5th and last parameter controls the _sorting_ of the found intersections.
When this returns 2 intersections, you can choose how they are ordered in the returned array:
Set sort to:
- `x` : The point with the lowest X-coordinate will go first (left to right)
- `y` : The point with the lowest Y-coordinate will go first (top to bottom)
## Example
<Example caption="A Utils.lineIntersectsCircle() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.A = new Point(95, 45)
.addCircle(35, "fabric")
points.B = new Point(55, 50)
points.C = new Point(75, 30)
points.D = new Point(55, 65)
points.E = new Point(115, 5)
points.F = new Point(65, 75)
points.G = new Point(125, 15)
paths.line1 = new Path().move(points.B).line(points.C)
paths.line2 = new Path().move(points.D).line(points.E)
paths.line3 = new Path().move(points.F).line(points.G)
const intersections1 = utils.lineIntersectsCircle(
points.A,
points.A.attributes.get("data-circle"),
points.B,
points.C
)
const intersections2 = utils.lineIntersectsCircle(
points.A,
points.A.attributes.get("data-circle"),
points.D,
points.E,
"y"
)
const intersections3 = utils.lineIntersectsCircle(
points.A,
points.A.attributes.get("data-circle"),
points.F,
points.G
)
snippets.first1 = new Snippet("bnotch", intersections1[0])
snippets.first2 = new Snippet("bnotch", intersections2[0])
snippets.second2 = new Snippet("notch", intersections2[1])
snippets.first3 = new Snippet("bnotch", intersections3[0])
snippets.second3 = new Snippet("notch", intersections3[1])
return part
}
```
</Example>

View file

@ -0,0 +1,62 @@
---
title: utils.lineIntersectsCurve()
---
The `utils.lineIntersectsCurve()` function finds the intersection between a line
segment from point `from` to point `to` and a curve described by points
`start`, `cp1`, `cp2, and `end\`.
:::warning
This function can sometimes fail to find intersections in some curves
due to a limitation in an underlying Bézier library.
Please see [Bug #3367](https://github.com/freesewing/freesewing/issues/3367)
for more information.
:::
## Signature
```js
array | false utils.lineIntersectsCurve(
Point from,
Point to,
Point start,
Point cp1,
Point cp2,
Point end
)
```
## Example
<Example caption="A Utils.lineIntersectsCurve() example">
```js
({ Point, points, Path, paths, Snippet, snippets, getId, utils, part }) => {
points.A = new Point(10, 10)
points.Acp = new Point(310, 40)
points.B = new Point(110, 70)
points.Bcp = new Point(-210, 40)
points.E = new Point(20, -5)
points.D = new Point(100, 85)
paths.curve = new Path()
.move(points.A)
.curve(points.Acp, points.Bcp, points.B)
paths.line = new Path().move(points.E).line(points.D)
for (let p of utils.lineIntersectsCurve(
points.D,
points.E,
points.A,
points.Acp,
points.Bcp,
points.B
)) {
snippets[getId()] = new Snippet("notch", p)
}
return part
}
```
</Example>

View file

@ -0,0 +1,43 @@
---
title: utils.linesIntersect()
---
The `utils.linesIntersect()` function finds the intersection between two line
segments. Returns a [Point](/reference/api/point/) object for the intersection, or `false`
if the lines don't intersect.
## Signature
```js
Point | false utils.linesIntersect(
Point A,
Point B,
Point C,
Point D
)
```
## Example
<Example caption="A Utils.linesIntersect() example">
```js
({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
points.A = new Point(10, 10)
points.B = new Point(50, 40)
points.C = new Point(15, 30)
points.D = new Point(60, 15)
paths.AB = new Path().move(points.A).line(points.B)
paths.CD = new Path().move(points.C).line(points.D)
snippets.X = new Snippet(
"notch",
utils.linesIntersect(points.A, points.B, points.C, points.D)
)
return part
}
```
</Example>

View file

@ -0,0 +1,84 @@
---
title: utils.mergeI18n()
---
The `utils.mergeI18n()` function merges translation files from different designs.
When your design re-uses parts from other designs, it should provide
translation for those parts and any strings or options they use. Rather than
re-creating this content in your own design, you can pull it out of of the
design you are using the part from by importing the `i18n` named export, and
then use this function to merge it with your own translations.
## Signature
```js
Object mergeI18n({
Array designs,
Object options
})
```
## Use
In its simplest form, this function will receive an Array of translation data
(typically the `i18n` named export of a design) and merge them:
```js
import { i18n as brianI18n } from '@freesewing/brian'
import { i18n as simonI18n } from '../i18n/index.mjs'
// Merge translations
const i18n = mergeI18n([brianI18n, simonI18n])
```
This simple approach is typically what you want when you are extending a design
and you are keeping all the parts and options of the design you are extending.
In the example above, Simon extends Brian in this way.
## Configuration
If you don't want to keep all options or parts, you can further control how the
translation data will be merged by passing in a second parameter which is an
object holding the configuration that describes how to merge the translation
data.
The configuration object takes 3 top-level properties:
- `s`: Specifies configuration for how to merge the translation of strings (under `s` in the translation files)
- `p`: Specifies configuration for how to merge the part name translations (under `p` in the translation files)
- `o`: Specifies configuration for how to merge the option translations (under `p` in the translation files)
For **each of the `s`, `p`, and `o` keys** you can specify the following properties:
- `drop`: An Array with the keys of entries to not merge (drop). Keys that are not in this array will be merged.
- `keep`: An Array with the keys of entries to merge (keep). Keys that are not in this array will not be merged.
### Example
```js
import { i18n as brianI18n } from '@freesewing/brian'
import { i18n as otherI18n } from '../i18n/index.mjs'
// Merge translations
const i18n = mergeI18n(
[brianI18n, otherI18n],
{
p: {
keep: ['sleevecap'],
},
o: {
drop: ['waistEase', 'chestEase']
}
}
}
)
```
The function will check each key under the `s`, `p`, and `o` top-level keys in the translation files.
For each it will:
- Check whether there is a `drop` array configured. If there is, it will remove the entry if its key is included in the `drop` Array.
- Check whether there is a `keep` array configured. If there is, it will remove the entry if its key is not included in the `keep` Array.
If the entry is not explicitly removed by including it in `drop` or excluding it from a list set in `keep` it will be kept.

View file

@ -0,0 +1,30 @@
---
title: utils.mergeOptions()
---
The `utils.mergeOptions()` function merges the user-provided options with the
options from the pattern configuration.
## Signature
```js
Object utils.mergeOptions(
Object settings,
Object optionsConfig
)
```
## Notes
Typically the only options that are passed as part of settings to the pattern
are those that differ from the defaults. This means that if you want to check
an option outside a draft method, you need to check whether the option is set,
and if it's not get the default value from the pattern config. Furthermore,
where the default is stored and whether or not it should be further transformed
depends on the option type.
This function exists to facilitate this. You pass it the user-provided settings,
and the pattern config options key, and it will return an object where all
options are populated with the user-provided values, or their defaults if the
user did not provide any input.

View file

@ -0,0 +1,35 @@
---
title: utils.pctBasedOn()
---
The `utils.pctBasedOn()` function is a helper function to be used when
configuring [snapped percentage
options](/reference/api/part/config/options/pct/snap).
## Signature
```js
object utils.pctBasedOn(String measurement)
```
## Example
```js
const options = {
example: {
pct: 12,
min: 5,
max: 18,
snap: 3,
...pctBasedOn('chest')
}
}
```
## Notes
This will return an object with `toAbs` and `fromAbs` properties that calculate
the option's absolute and relative values based on a measurement. Refer to
[snapped percentage options](/reference/api/part/config/options/pct/snap) for
more details.

View file

@ -0,0 +1,80 @@
---
title: utils.pointOnBeam()
---
The `utils.pointOnBeam()` function returns `true` if the point `check` lies on
the endless line that goes through `point1` and `point2`.
## Signature
```js
bool utils.pointOnBeam(
Point point1,
Point point2,
Point check,
float precision = 1e6
)
```
The fourth parameter controls the precision. Lower numbers make the check less precise.
## Example
<Example caption="A Utils.pointOnBeam() example">
```js
({ Point, points, Path, paths, Snippet, snippets, getId, utils, part }) => {
points.from1 = new Point(10, 10)
points.to1 = new Point(90, 60)
points.from2 = new Point(10, 30)
points.to2 = new Point(90, 80)
points.b1 = new Point(170, 110)
points.b2 = new Point(170, 130)
const scatter = []
for (let i = 1; i < 36; i++) {
for (let j = 1; j < 27; j++) {
scatter.push(new Point(i * 10, j * 10))
}
}
let snippet
for (let point of scatter) {
if (utils.pointOnBeam(points.from1, points.to1, point)) snippet = "notch"
else snippet = "bnotch"
snippets[getId()] = new Snippet(snippet, point)
if (utils.pointOnBeam(points.from2, points.to2, point, 0.01)) {
snippet = "notch"
} else snippet = "bnotch"
snippets[getId()] = new Snippet(snippet, point)
}
paths.line1 = new Path()
.move(points.from1)
.line(points.to1)
.addClass("fabric stroke-lg")
paths.lne1 = new Path()
.move(points.to1)
.line(points.b1)
.addClass("fabric dashed")
paths.line2 = new Path()
.move(points.from2)
.line(points.to2)
.addClass("fabric stroke-lg")
paths.lne2 = new Path()
.move(points.to2)
.line(points.b2)
.addClass("fabric dashed")
return part
}
```
</Example>
## Notes
Typically, you don't need to worry about precision. But occasionally, you may
get unexpected results because of floating point errors, rounding errors, or
cubic Bézier juggling.
When that happens, you can lower the precision so you get what you expect.

View file

@ -0,0 +1,65 @@
---
title: utils.pointOnCurve()
---
The `utils.pointOnCurve()` function returns `true` if the point `check` lies on a
curve described by points `start`, `cp1`, `cp2`, and `end`.
## Signature
```js
bool utils.pointOnCurve(
Point start,
Point cp1,
Point cp2,
Point end,
Point check
)
```
## Example
<Example caption="A Utils.pointOnCurve() example">
```js
({ Point, points, Path, paths, Snippet, snippets, getId, utils, part }) => {
points.start = new Point(10, 10)
points.cp1 = new Point(90, 10)
points.cp2 = new Point(10, 60)
points.end = new Point(90, 60)
const scatter = []
for (let i = 1; i < 19; i++) {
for (let j = 1; j < 14; j++) {
scatter.push(new Point(i * 10, j * 10))
}
}
let snippet
for (let point of scatter) {
if (
utils.pointOnCurve(
points.start,
points.cp1,
points.cp2,
points.end,
point
)
) {
snippet = "notch"
} else snippet = "bnotch"
snippets[getId()] = new Snippet(snippet, point)
}
paths.curve = new Path()
.move(points.start)
.curve(points.cp1, points.cp2, points.end)
.addClass("fabric stroke-lg")
return part
}
```
</Example>
## Notes
Keep in mind that calculations with Bézier curves are often approximations.

View file

@ -0,0 +1,72 @@
---
title: utils.pointOnLine()
---
The `utils.pointOnLine()` function returns `true` if the point `check` lies on a
line segment from point `from` to point `to`.
## Signature
```js
bool utils.pointOnLine(
Point from,
Point to,
Point check,
float precision = 1e6
)
```
The fourth parameter controls the precision.
See [pointOnBeam](/reference/api/utils/pointonbeam).
## Example
<Example caption="A Utils.pointOnLine() example">
```js
({ Point, points, Path, paths, Snippet, snippets, getId, utils, part }) => {
points.from1 = new Point(10, 10)
points.to1 = new Point(90, 60)
points.from2 = new Point(10, 30)
points.to2 = new Point(90, 80)
points.b1 = new Point(170, 110)
points.b2 = new Point(170, 130)
const scatter = []
for (let i = 1; i < 36; i++) {
for (let j = 1; j < 27; j++) {
scatter.push(new Point(i * 10, j * 10))
}
}
let snippet
for (let point of scatter) {
if (utils.pointOnLine(points.from1, points.to1, point)) snippet = "notch"
else snippet = "bnotch"
snippets[getId()] = new Snippet(snippet, point)
if (utils.pointOnLine(points.from2, points.to2, point, 0.01)) {
snippet = "notch"
} else snippet = "bnotch"
snippets[getId()] = new Snippet(snippet, point)
}
paths.line1 = new Path()
.move(points.from1)
.line(points.to1)
.addClass("fabric stroke-lg")
paths.lne1 = new Path()
.move(points.to1)
.line(points.b1)
.addClass("fabric dashed")
paths.line2 = new Path()
.move(points.from2)
.line(points.to2)
.addClass("fabric stroke-lg")
paths.lne2 = new Path()
.move(points.to2)
.line(points.b2)
.addClass("fabric dashed")
return part
}
```
</Example>

View file

@ -0,0 +1,12 @@
---
title: utils.rad2deg()
---
The `utils.rad2dag()` function returns the radians you pass to it as degrees.
## Signature
```js
float utils.rad2deg(float radians)
```

View file

@ -0,0 +1,10 @@
---
title: utils
---
The `utils` object is a plain object that bundles utility functions to
facilitate parametric design.
The following functions are provided by the `utils` object:
<ReadMore />

View file

@ -0,0 +1,18 @@
---
title: utils.round()
---
The `utils.round()` function rounds a value to two decimals.
## Signature
```js
float utils.round(float value)
```
## Example
```js
utils.round(0.1234) // 0.12
utils.round(5.6789) // 5.68
```

View file

@ -0,0 +1,80 @@
---
title: utils.splitCurve()
---
The `utils.splitCurve()` function splits a curve defined by 4 points `start`,
`cp1`, `cp2`, and `end` on the point `split` and returns an array holding both
halves.
## Signature
```js
array utils.splitCurve(
Point start,
Point cp1,
Point cp2,
Point end,
Point check,
)
```
## Example
<Example caption="A Utils.splitCurve() example">
```js
({ Point, points, Path, paths, utils, part }) => {
points.start = new Point(10, 10)
points.cp1 = new Point(100, 80)
points.cp2 = new Point(100, 0)
points.end = new Point(10, 50)
paths.example = new Path()
.move(points.start)
.curve(points.cp1, points.cp2, points.end)
.addClass('dotted stroke-xs')
points.split = paths.example.shiftFractionAlong(0.4)
const halves = utils.splitCurve(
points.start,
points.cp1,
points.cp2,
points.end,
points.split
)
for (let i=0; i<2; i++) {
const { start, cp1, cp2, end } = halves[i]
paths[`segment${i}`] = new Path()
.move(start)
.curve(cp1, cp2, end)
.addClass('stroke-xl')
.attr('style', 'stroke-opacity: 0.5;')
}
paths.segment0.addClass('note')
paths.segment1.addClass('lining')
return part
}
```
</Example>
## Notes
The returned object has this signature:
```js
[
{
start: Point,
cp1: Point,
cp2: Point,
end: Point,
},
{
start: Point,
cp1: Point,
cp2: Point,
end: Point,
},
]

View file

@ -0,0 +1,29 @@
---
title: utils.stretchToScale()
---
The `utils.stretchToScale()` function calculates the scale for a given amount of
stretch.
## Signature
```js
float utils.stretchToScale(float stretch)
```
## Notes
The way people measure stretch intuitively is different from the way we handle stretch in code.
When people say fabric has _25% stretch_ they mean that 10 cm of fabric can
stretch to 12.5 cm.
In code that means we would need to scale non-stretch lengths by 80%
to get the correct lengths to use in patterns with 25% stretch fabric.
Pattern designers need a way to calculate the scaling factor to use for
their pattern part lengths, given a fabric stretch percentage.
This function does that by returning:
```js
1 / (1 + parseFloat(stretch))
```

View file

@ -0,0 +1,19 @@
---
title: utils.units()
---
The `utils.units()` function converts the units `value` you pass it into a
formatted string for the `format` you pass it.
## Signature
```js
string utils.units(float value, string format = 'metric')
```
Format must be either `imperial` or `metric` (the default).
## Notes
A [part's `draft()` function](/reference/api/part/draft) receives a context-aware
`unit()` function that will call this function and pass it the units requested by the user.