2021-10-17 18:26:00 +02:00
|
|
|
---
|
2021-08-25 16:09:31 +02:00
|
|
|
title: Paths
|
2021-12-27 14:58:44 +01:00
|
|
|
order: 40
|
2021-10-17 18:26:00 +02:00
|
|
|
---
|
2021-08-25 16:09:31 +02:00
|
|
|
|
|
|
|
Paths are the lines and curves that make up your pattern.
|
2022-10-12 00:15:33 +02:00
|
|
|
They are made up of individual drawing operations that together make up the path.
|
2021-08-25 16:09:31 +02:00
|
|
|
|
|
|
|
FreeSewing supports the following types of drawing operations:
|
|
|
|
|
2022-02-20 14:44:38 +01:00
|
|
|
- The **move** operation moves our virtual pen but does not draw anything.
|
|
|
|
- The **line** operation draws a straight line
|
2022-04-30 14:07:54 -04:00
|
|
|
- The **curve** operation draws a [Bézier curve](/guides/prerequisites/bezier-curves)
|
2022-02-20 14:44:38 +01:00
|
|
|
- The **close** operation closes the path
|
2021-08-25 16:09:31 +02:00
|
|
|
|
|
|
|
To crucial thing to keep in mind is that, with the exception of the **move** operation,
|
|
|
|
all drawing operations start from wherever you are currently on your virtual sheet of paper.
|
|
|
|
|
2022-02-19 08:04:25 +01:00
|
|
|
For example, you might expect the **line** operation to take a start- and endpoint.
|
2022-01-15 10:38:14 -05:00
|
|
|
But in fact, it only takes an endpoint, and will draw a straight line from where our virtual pen
|
2021-08-25 16:09:31 +02:00
|
|
|
currently is to said endpoint.
|
|
|
|
|
|
|
|
Because all but the **move** drawing operations are relative to their operation preceding it,
|
|
|
|
**all Paths must start with a move operation**.
|
|
|
|
|
|
|
|
<Note>
|
|
|
|
|
|
|
|
Understanding that each drawing operation builds upon the next one is an important insight.
|
|
|
|
|
|
|
|
</Note>
|
|
|
|
|
2022-10-12 00:15:33 +02:00
|
|
|
<Example caption="A schematic overview of where paths are kept inside a FreeSewing pattern">
|
|
|
|
```mjs
|
|
|
|
({ Point, points, Path, paths, options, part }) => {
|
|
|
|
|
|
|
|
// Draws a w*h box, returns a Path object
|
|
|
|
const box = (name, origin, width, height, classes='fabric') => {
|
|
|
|
let base = height
|
|
|
|
if (width < height) base = width
|
|
|
|
let t = base
|
|
|
|
points[name + 'TopLeft'] = new Point(origin.x, origin.y)
|
|
|
|
points[name + 'BottomLeft'] = new Point(origin.x, origin.y + height)
|
|
|
|
points[name + 'BottomRight'] = new Point(
|
|
|
|
origin.x + width,
|
|
|
|
origin.y + height
|
|
|
|
)
|
|
|
|
points[name + 'TopRight'] = new Point(origin.x + width, origin.y)
|
|
|
|
points[name + 'Mid'] = points[name + 'TopLeft'].shiftFractionTowards(
|
|
|
|
points[name + 'BottomRight'],
|
|
|
|
0.5
|
|
|
|
)
|
|
|
|
points[name + 'Mid'].y += 3
|
|
|
|
|
|
|
|
return new Path()
|
|
|
|
.move(points[name + 'TopLeft'])
|
|
|
|
.line(points[name + 'BottomLeft'])
|
|
|
|
.line(points[name + 'BottomRight'])
|
|
|
|
.line(points[name + 'TopRight'])
|
|
|
|
.line(points[name + 'TopLeft'])
|
|
|
|
.close()
|
|
|
|
.addClass(classes)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draws a box and handled text placement
|
|
|
|
const drawBox = (name, x, y, width, height, text=true, classes, textClasses='') => {
|
|
|
|
points[name + 'Origin'] = new Point(x, y)
|
|
|
|
paths[name] = box(name, points[name + 'Origin'], width, height, classes)
|
|
|
|
if (text === 'b') {
|
|
|
|
paths[name+'_label'] = new Path()
|
|
|
|
.move(points[name+'BottomLeft'])
|
|
|
|
.line(points[name+'BottomRight'])
|
|
|
|
.addClass('hidden')
|
|
|
|
.addText(name, 'center ' + textClasses)
|
|
|
|
.attr('data-text-dy', -1)
|
|
|
|
}
|
|
|
|
else if (text) points[name + 'Mid'].addText(name, 'center')
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parts set 0
|
|
|
|
drawBox('Part A (set 0)', -27, -27, 44, 70, 'b', 'note', 'bold')
|
|
|
|
drawBox('points', -24, -24, 38, 12, true, 'note')
|
|
|
|
drawBox('paths', -24, -9, 38, 12, true, 'note fill-note')
|
|
|
|
paths['paths'].attr('fill-opacity', 0.2)
|
|
|
|
drawBox('snippets', -24, 6, 38, 12, true, 'note')
|
|
|
|
|
|
|
|
drawBox('Part B (set 0)', 26, -27, 44, 70, 'b', 'note', 'bold')
|
|
|
|
drawBox(' points ', 29, -24, 38, 12, true, 'note')
|
|
|
|
drawBox(' paths ', 29, -9, 38, 12, true, 'note fill-note')
|
|
|
|
paths[' paths '].attr('fill-opacity', 0.2)
|
|
|
|
drawBox(' snippets ', 29, 6, 38, 12, true, 'note')
|
|
|
|
|
|
|
|
drawBox('Part C (set 0)', 79, -27, 44, 70, 'b', 'note', 'bold')
|
|
|
|
drawBox(' points ', 82, -24, 38, 12, true, 'note')
|
|
|
|
drawBox(' paths ', 82, -9, 38, 12, true, 'note fill-note')
|
|
|
|
paths[' paths '].attr('fill-opacity', 0.2)
|
|
|
|
drawBox(' snippets ', 82, 6, 38, 12, true, 'note')
|
|
|
|
|
|
|
|
drawBox('setStore 0', -24, 21, 144, 12, true, 'lining dashed')
|
|
|
|
paths['setStore 0'].attr('fill-opacity', 0.2)
|
|
|
|
|
|
|
|
// Pattern
|
|
|
|
drawBox('Pattern Store', -30, -45, 155, 15, true, 'lining')
|
|
|
|
paths['Pattern Store'].attr('fill-opacity', 0.2)
|
|
|
|
drawBox('Pattern', -34, -49, 163, 106, 'b', 'fabric stroke-lg', 'text-lg bold')
|
|
|
|
|
|
|
|
return part
|
|
|
|
}
|
|
|
|
```
|
|
|
|
</Example>
|
|
|
|
|
2021-08-25 16:09:31 +02:00
|
|
|
<Tip>
|
|
|
|
|
2022-02-19 08:04:25 +01:00
|
|
|
Our example image (which, if you hadn't realized was created with FreeSewing) has a lot of
|
2021-08-25 16:09:31 +02:00
|
|
|
paths in it. Each box, the arrows, the lines in the React logo, and so on.
|
|
|
|
|
2022-10-12 00:15:33 +02:00
|
|
|
Click the **X-Ray** tab to reveal them.
|
|
|
|
|
2021-08-25 16:09:31 +02:00
|
|
|
</Tip>
|
2022-10-12 00:15:33 +02:00
|
|
|
|
|
|
|
|