Avoiding overlap
While we've only drawn the end of one strap, it's pretty obvious they overlap, which makes it impossible to cut out, so we're going to have to address that.
Specifically, we're going to rotate our strap out of the way until it no longer overlaps. The rest of our bib should stay as it is, so let's start by making a list of points we need to rotate.
However, there is a catch.
Macros and auto-generated IDs
我们提供 used the round macro to help us round the corners
of our strap, and it added a bunch of auto-generated points to our pattern. We need to
rotate these points too, but what are their names?
A macro will return the names of the things it created. So far, we have not captured that return value, but if we did, it would look like this:
{
"提示RightTop": {
"points": {
"start": "__macro_@openclothes/plugin-round_提示RightTop_start",
"cp1": "__macro_@openclothes/plugin-round_提示RightTop_cp1",
"cp2": "__macro_@openclothes/plugin-round_提示RightTop_cp2",
"end": "__macro_@openclothes/plugin-round_提示RightTop_end"
},
"paths": {
"path": "__macro_@openclothes/plugin-round_提示RightTop_path"
}
},
"提示RightBottom": {
"points": {
"start": "__macro_@openclothes/plugin-round_提示RightBottom_start",
"cp1": "__macro_@openclothes/plugin-round_提示RightBottom_cp1",
"cp2": "__macro_@openclothes/plugin-round_提示RightBottom_cp2",
"end": "__macro_@openclothes/plugin-round_提示RightBottom_end"
},
"paths": {
"path": "__macro_@openclothes/plugin-round_提示RightBottom_path"
}
}
}
Those names aren't very handy to remember. So I will rewrite this code a bit to
we'll capture these return values from the round macros and create
easy-to-remember points from them:
- 代码
- 预览
- 透视
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
utils,
macro,
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()
delta = paths.quarterNeck.length() - target
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 1)
/*
* 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)
/*
* 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.提示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,
hide: false
}),
提示RightBottom: macro("round", {
id: "提示RightBottom",
from: points.提示Right,
to: points.top,
via: points.提示RightBottom,
hide: false
})
}
/*
* 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()
}
}
/*
* Now, adapt our `rect` path so it's no longer a rectangle:
*/
paths.rect = new Path()
.move(points.edgeTop)
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
.line(points.bottomLeft)
.line(points.bottomRight)
.line(points.edgeRight)
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
.close()
return part
}
It looks the same as before, but now those macro points are accessible to us
Once we have our list of points to rotate, we can rotate them. How far? Until the strap no longer overlaps.
- 代码
- 预览
- 透视
function draftBib({
Path,
Point,
paths,
points,
measurements,
options,
utils,
macro,
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()
delta = paths.quarterNeck.length() - target
if (delta > 0) tweak = tweak * 0.99
else tweak = tweak * 1.02
} while (Math.abs(delta) > 1)
/*
* 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)
/*
* 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.提示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,
hide: false
}),
提示RightBottom: macro("round", {
id: "提示RightBottom",
from: points.提示Right,
to: points.top,
via: points.提示RightBottom,
hide: false
})
}
/*
* 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()
}
}
/*
* This is the list of points we need to rotate
* to move our strap out of the way
*/
const rotateThese = [
"edgeTopLeftCp",
"edgeTop",
"提示Right",
"提示RightTop",
"提示RightTopStart",
"提示RightTopCp1",
"提示RightTopCp2",
"提示RightTopEnd",
"提示RightBottomStart",
"提示RightBottomCp1",
"提示RightBottomCp2",
"提示RightBottomEnd",
"提示RightBottom",
"top",
"topCp2"
]
/*
* We're rotating all the points in
* the `rotateThese` array around
* the `edgeLeft` point.
*
* We're using increments of 1 degree
* until the `提示RightBottomStart` point
* is 1 mm beyond the center of our bib.
*/
while (points.提示RightBottomStart.x > -1) {
for (const p of rotateThese) points[p] = points[p].rotate(1, points.edgeLeft)
}
/*
* This is not needed
* we are merely adding it to show
* what the rotated path looks like
*/
macro("round", {
id: "showRightTop",
from: points.edgeTop,
to: points.提示Right,
via: points.提示RightTop,
hide: false,
classes: 'contrast dotted',
})
macro("round", {
id: "showRightBottom",
from: points.提示Right,
to: points.top,
via: points.提示RightBottom,
hide: false,
classes: 'contrast dotted',
})
/*
* Now, adapt our `rect` path so it's no longer a rectangle:
*/
paths.rect = new Path()
.move(points.edgeTop)
.curve(points.edgeTopLeftCp, points.edgeLeftCp, points.edgeLeft)
.line(points.bottomLeft)
.line(points.bottomRight)
.line(points.edgeRight)
.curve(points.edgeRightCp, points.edgeTopRightCp, points.edgeTop)
.close()
return part
}
It is looking pretty wonky now, but we'll deal with that next