Dealing with laser cutters
Laser cutters is merely an example of a situation where your user wants not the complete detailed pattern with all annotations, but just the outlines. Essentially what we had at the end of part 2 of this tutorial.
Since then, we've added a bunch of embellishments, and perhaps the user does not want those.
Well, good news: there is a setting for that too. That setting is complete,
and more annotations will automatically take it into account.
For example, if you put a logo or title on the pattern, it will check the
complete setting and if it is false it will do nothing.
When we say we're going to complete our pattern, we mean we're going to add
things like a title and a scalebox and so on.
So while in most scenarios you don't have to worry about complete, you
should keep it in mind when you are adding text or paths to the design
that should not be shown on a non-complete pattern.
An example will make this more clear:
Adding an indicator for bias tape
- 预览
- 代码
- 透视
function draftBib({
Point,
points,
Path,
paths,
utils,
measurements,
options,
macro,
Snippet,
snippets,
store,
complete,
part,
}) {
/*
* Construct the neck opening
*/
const target = (measurements.head * options.neckRatio) / 4
let tweak = 1
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.neck = new Path()
.move(points.right)
.curve(points.rightCp1, points.bottomCp2, points.bottom)
delta = paths.neck.length() - target
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 1)
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()
/*
* Construct the outline
*/
let width = measurements.head * options.widthRatio
let 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)
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 end of the straps
*/
let strap = points.edgeTop.dy(points.top)
points.提示Right = points.edgeTop.translate(strap / 2, strap / 2)
points.提示RightTop = new Point(points.提示Right.x, points.edgeTop.y)
points.提示RightBottom = new Point(points.提示Right.x, points.top.y)
/*
* Macros will return the auto-generated IDs
*/
const ids1 = {
提示RightTop: macro('round', {
id: '提示RightTop',
from: points.edgeTop,
to: points.提示Right,
via: points.提示RightTop,
}),
提示RightBottom: macro('round', {
id: '提示RightBottom',
from: points.提示Right,
to: points.top,
via: points.提示RightBottom,
}),
}
/*
* 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()
}
}
/*
* Rotate straps so they don't overlap
*/
let rotateThese = [
'edgeTopLeftCp',
'edgeTop',
'提示Right',
'提示RightTop',
'提示RightTopStart',
'提示RightTopCp1',
'提示RightTopCp2',
'提示RightTopEnd',
'提示RightBottomStart',
'提示RightBottomCp1',
'提示RightBottomCp2',
'提示RightBottomEnd',
'提示RightBottom',
'top',
'topCp2',
]
while (points.提示RightBottomStart.x > -1) {
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
}
/*
* Add points to anchor snaps on
*/
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
/*
* Mirror points to the other side
*/
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
points.topCp1 = points.topCp2.flipX()
points.提示LeftTopStart = points.提示RightTopStart.flipX()
points.提示LeftTopCp1 = points.提示RightTopCp1.flipX()
points.提示LeftTopCp2 = points.提示RightTopCp2.flipX()
points.提示LeftTopEnd = points.提示RightTopEnd.flipX()
points.提示LeftBottomStart = points.提示RightBottomStart.flipX()
points.提示LeftBottomCp1 = points.提示RightBottomCp1.flipX()
points.提示LeftBottomCp2 = points.提示RightBottomCp2.flipX()
points.提示LeftBottomEnd = points.提示RightBottomEnd.flipX()
points.snapRight = points.snapLeft.flipX()
/*
* Round the bottom of the bib
* Radius is fixed, but you could use an option for it)
*
* Macros will return the auto-generated IDs
*/
const ids2 = {
bottomLeft: macro('round', {
id: 'bottomLeft',
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
radius: points.bottomRight.x / 4,
}),
bottomRight: macro('round', {
id: 'bottomRight',
from: points.bottomLeft,
to: points.topRight,
via: points.bottomRight,
radius: points.bottomRight.x / 4,
}),
}
/*
* Create points from them with easy names
*/
for (const side in ids2) {
for (const id of ['start', 'cp1', 'cp2', 'end']) {
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
}
}
/*
* Construct the path
*/
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.提示LeftTopStart)
.curve(points.提示LeftTopCp1, points.提示LeftTopCp2, points.提示LeftTopEnd)
.curve(points.提示LeftBottomCp1, points.提示LeftBottomCp2, points.提示LeftBottomEnd)
.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.提示RightBottomEnd)
.curve(points.提示RightBottomCp2, points.提示RightBottomCp1, points.提示RightBottomStart)
.curve(points.提示RightTopCp2, points.提示RightTopCp1, points.提示RightTopStart)
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
.close()
.attr('class', 'fabric')
/*
*
* Annotations
*
*/
/*
* Cut list
*/
store.cutlist.addCut({ cut: 1, from: 'fabric' })
/*
* Add the snaps
*/
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
/*
* Add the bias tape
*/
if (complete)
paths.bias = paths.seam
.offset(-5)
.addClass('注意 dashed')
.addText('tutorial:finishWithBiasTape', 'center fill-注意')
/*
* Add the title
*/
points.title = points.bottom.shift(-90, 45)
macro('title', {
at: points.title,
nr: 1,
title: 'bib',
align: 'center',
scale: 0.8,
})
/*
* Add the scalebox
*/
points.scalebox = points.title.shift(-90, 65)
macro('scalebox', { at: points.scalebox })
/*
* Add the logo
*/
points.logo = new Point(0, 0)
snippets.logo = new Snippet('logo', points.logo)
return part
}
A nice 注意 about bias tape
And here is the exact same thing, but withe complete setting set to false:
- 预览
- 代码
- 透视
function draftBib({
Point,
points,
Path,
paths,
utils,
measurements,
options,
macro,
Snippet,
snippets,
store,
complete,
part,
}) {
/*
* Construct the neck opening
*/
const target = (measurements.head * options.neckRatio) / 4
let tweak = 1
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.neck = new Path()
.move(points.right)
.curve(points.rightCp1, points.bottomCp2, points.bottom)
delta = paths.neck.length() - target
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 1)
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()
/*
* Construct the outline
*/
let width = measurements.head * options.widthRatio
let 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)
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 end of the straps
*/
let strap = points.edgeTop.dy(points.top)
points.提示Right = points.edgeTop.translate(strap / 2, strap / 2)
points.提示RightTop = new Point(points.提示Right.x, points.edgeTop.y)
points.提示RightBottom = new Point(points.提示Right.x, points.top.y)
/*
* Macros will return the auto-generated IDs
*/
const ids1 = {
提示RightTop: macro('round', {
id: '提示RightTop',
from: points.edgeTop,
to: points.提示Right,
via: points.提示RightTop,
}),
提示RightBottom: macro('round', {
id: '提示RightBottom',
from: points.提示Right,
to: points.top,
via: points.提示RightBottom,
}),
}
/*
* 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()
}
}
/*
* Rotate straps so they don't overlap
*/
let rotateThese = [
'edgeTopLeftCp',
'edgeTop',
'提示Right',
'提示RightTop',
'提示RightTopStart',
'提示RightTopCp1',
'提示RightTopCp2',
'提示RightTopEnd',
'提示RightBottomStart',
'提示RightBottomCp1',
'提示RightBottomCp2',
'提示RightBottomEnd',
'提示RightBottom',
'top',
'topCp2',
]
while (points.提示RightBottomStart.x > -1) {
for (let p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
}
/*
* Add points to anchor snaps on
*/
points.snapLeft = points.top.shiftFractionTowards(points.edgeTop, 0.5)
/*
* Mirror points to the other side
*/
points.edgeTopRightCp = points.edgeTopLeftCp.flipX()
points.topCp1 = points.topCp2.flipX()
points.提示LeftTopStart = points.提示RightTopStart.flipX()
points.提示LeftTopCp1 = points.提示RightTopCp1.flipX()
points.提示LeftTopCp2 = points.提示RightTopCp2.flipX()
points.提示LeftTopEnd = points.提示RightTopEnd.flipX()
points.提示LeftBottomStart = points.提示RightBottomStart.flipX()
points.提示LeftBottomCp1 = points.提示RightBottomCp1.flipX()
points.提示LeftBottomCp2 = points.提示RightBottomCp2.flipX()
points.提示LeftBottomEnd = points.提示RightBottomEnd.flipX()
points.snapRight = points.snapLeft.flipX()
/*
* Round the bottom of the bib
* Radius is fixed, but you could use an option for it)
*
* Macros will return the auto-generated IDs
*/
const ids2 = {
bottomLeft: macro('round', {
id: 'bottomLeft',
from: points.topLeft,
to: points.bottomRight,
via: points.bottomLeft,
radius: points.bottomRight.x / 4,
}),
bottomRight: macro('round', {
id: 'bottomRight',
from: points.bottomLeft,
to: points.topRight,
via: points.bottomRight,
radius: points.bottomRight.x / 4,
}),
}
/*
* Create points from them with easy names
*/
for (const side in ids2) {
for (const id of ['start', 'cp1', 'cp2', 'end']) {
points[`${side}${utils.capitalize(id)}`] = points[ids2[side].points[id]].copy()
}
}
/*
* Construct the path
*/
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.提示LeftTopStart)
.curve(points.提示LeftTopCp1, points.提示LeftTopCp2, points.提示LeftTopEnd)
.curve(points.提示LeftBottomCp1, points.提示LeftBottomCp2, points.提示LeftBottomEnd)
.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.提示RightBottomEnd)
.curve(points.提示RightBottomCp2, points.提示RightBottomCp1, points.提示RightBottomStart)
.curve(points.提示RightTopCp2, points.提示RightTopCp1, points.提示RightTopStart)
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
.close()
.attr('class', 'fabric')
/*
*
* Annotations
*
*/
/*
* Cut list
*/
store.cutlist.addCut({ cut: 1, from: 'fabric' })
/*
* Add the snaps
*/
snippets.snapStud = new Snippet('snap-stud', points.snapLeft)
snippets.snapSocket = new Snippet('snap-socket', points.snapRight).attr('opacity', 0.5)
/*
* Add the bias tape
*/
if (complete)
paths.bias = paths.seam
.offset(-5)
.addClass('注意 dashed')
.addText('tutorial:finishWithBiasTape', 'center fill-注意')
/*
* Add the title
*/
points.title = points.bottom.shift(-90, 45)
macro('title', {
at: points.title,
nr: 1,
title: 'bib',
align: 'center',
scale: 0.8,
})
/*
* Add the scalebox
*/
points.scalebox = points.title.shift(-90, 65)
macro('scalebox', { at: points.scalebox })
/*
* Add the logo
*/
points.logo = new Point(0, 0)
snippets.logo = new Snippet('logo', points.logo)
return part
}
Same code, but with complete disabled