Merge branch 'develop' into more-lint
This commit is contained in:
commit
c0ede14d74
118 changed files with 2870 additions and 4892 deletions
35
CHANGELOG.md
35
CHANGELOG.md
|
@ -649,6 +649,12 @@
|
|||
|
||||
- Migrated from Rollup to Esbuild for all builds
|
||||
|
||||
### unice
|
||||
|
||||
#### Added
|
||||
|
||||
- Unice is an underwear pattern
|
||||
|
||||
### ursula
|
||||
|
||||
#### Changed
|
||||
|
@ -679,12 +685,6 @@
|
|||
|
||||
### yuri
|
||||
|
||||
#### Changed
|
||||
|
||||
- Migrated from Rollup to Esbuild for all builds
|
||||
|
||||
### examples
|
||||
|
||||
#### Changed
|
||||
|
||||
- Migrated from Rollup to Esbuild for all builds
|
||||
|
@ -1272,16 +1272,6 @@
|
|||
|
||||
### yuri
|
||||
|
||||
#### Changed
|
||||
|
||||
- Switched to default import for version from package.json
|
||||
|
||||
### examples
|
||||
|
||||
#### Added
|
||||
|
||||
- Added plugin_gore example
|
||||
|
||||
#### Changed
|
||||
|
||||
- Switched to default import for version from package.json
|
||||
|
@ -2537,13 +2527,6 @@
|
|||
- Added the (disabled) waistbandHeight option from Titan
|
||||
- Changed to Titan's waistbandWidth option
|
||||
|
||||
### examples
|
||||
|
||||
#### Added
|
||||
|
||||
- Added examples for bartack plugin
|
||||
- Added examples for new buttonhole-start/end snippets
|
||||
|
||||
### plugin-buttons
|
||||
|
||||
#### Added
|
||||
|
@ -4029,12 +4012,6 @@
|
|||
|
||||
### wahid
|
||||
|
||||
#### Added
|
||||
|
||||
- Initial release
|
||||
|
||||
### examples
|
||||
|
||||
#### Added
|
||||
|
||||
- Initial release
|
||||
|
|
|
@ -65,10 +65,6 @@ diana:
|
|||
peer:
|
||||
'@freesewing/brian': *freesewing
|
||||
'@freesewing/plugin-bust': *freesewing
|
||||
examples:
|
||||
peer:
|
||||
'@freesewing/plugin-mirror': *freesewing
|
||||
'@freesewing/plugin-gore': *freesewing
|
||||
holmes:
|
||||
_:
|
||||
'@freesewing/plugin-gore': *freesewing
|
||||
|
|
|
@ -24,10 +24,6 @@ design:
|
|||
- pattern
|
||||
- sewing
|
||||
- sewing pattern
|
||||
examples:
|
||||
- documentation
|
||||
- example
|
||||
- parametric design
|
||||
i18n:
|
||||
- i18n
|
||||
- internationalisation
|
||||
|
|
|
@ -284,6 +284,13 @@
|
|||
"difficulty": 1,
|
||||
"tags": [ "tops", "historic" ]
|
||||
},
|
||||
"unice": {
|
||||
"description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
|
||||
"code": [ "Anna Puk", "Natalia Sayang" ],
|
||||
"design": [ "Anna Puk", "Natalia Sayang" ],
|
||||
"difficulty": 1,
|
||||
"tags": [ "bottoms", "underwear" ]
|
||||
},
|
||||
"ursula": {
|
||||
"description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
|
||||
"code": "Natalia Sayang",
|
||||
|
@ -321,10 +328,6 @@
|
|||
}
|
||||
},
|
||||
"utilities": {
|
||||
"examples": {
|
||||
"description": "A FreeSewing pattern holding examples for our documentation",
|
||||
"code": "Joost De Cock"
|
||||
},
|
||||
"legend": {
|
||||
"description": "A FreeSewing pattern to document pattern notation",
|
||||
"code": "Joost De Cock"
|
||||
|
|
|
@ -6,52 +6,52 @@ const crossBox = {
|
|||
name: 'crossbox',
|
||||
version,
|
||||
macros: {
|
||||
crossBox: function (so) {
|
||||
let id = this.getId()
|
||||
crossBox: function (so, { points, Point, paths, Path, getId }) {
|
||||
let id = getId()
|
||||
let shiftFraction = 0.1
|
||||
this.points[id + '_boxTopLeft'] = so.from.copy()
|
||||
this.points[id + '_boxBottomRight'] = so.to.copy()
|
||||
this.points[id + '_boxTopRight'] = new this.Point(so.to.x, so.from.y)
|
||||
this.points[id + '_boxBottomLeft'] = new this.Point(so.from.x, so.to.y)
|
||||
points[id + '_boxTopLeft'] = so.from.copy()
|
||||
points[id + '_boxBottomRight'] = so.to.copy()
|
||||
points[id + '_boxTopRight'] = new Point(so.to.x, so.from.y)
|
||||
points[id + '_boxBottomLeft'] = new Point(so.from.x, so.to.y)
|
||||
|
||||
this.points[id + '_topCrossTL'] = this.points[id + '_boxTopLeft'].shiftFractionTowards(
|
||||
this.points[id + '_boxBottomRight'],
|
||||
points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards(
|
||||
points[id + '_boxBottomRight'],
|
||||
shiftFraction
|
||||
)
|
||||
this.points[id + '_topCrossTR'] = this.points[id + '_boxTopRight'].shiftFractionTowards(
|
||||
this.points[id + '_boxBottomLeft'],
|
||||
points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards(
|
||||
points[id + '_boxBottomLeft'],
|
||||
shiftFraction
|
||||
)
|
||||
this.points[id + '_topCrossBL'] = this.points[id + '_boxBottomLeft'].shiftFractionTowards(
|
||||
this.points[id + '_boxTopRight'],
|
||||
points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards(
|
||||
points[id + '_boxTopRight'],
|
||||
shiftFraction
|
||||
)
|
||||
this.points[id + '_topCrossBR'] = this.points[id + '_boxBottomRight'].shiftFractionTowards(
|
||||
this.points[id + '_boxTopLeft'],
|
||||
points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards(
|
||||
points[id + '_boxTopLeft'],
|
||||
shiftFraction
|
||||
)
|
||||
|
||||
this.paths[id + 'crossBox'] = new this.Path()
|
||||
.move(this.points[id + '_boxTopLeft'])
|
||||
.line(this.points[id + '_boxTopRight'])
|
||||
.line(this.points[id + '_boxBottomRight'])
|
||||
.line(this.points[id + '_boxBottomLeft'])
|
||||
.line(this.points[id + '_boxTopLeft'])
|
||||
paths[id + 'crossBox'] = new Path()
|
||||
.move(points[id + '_boxTopLeft'])
|
||||
.line(points[id + '_boxTopRight'])
|
||||
.line(points[id + '_boxBottomRight'])
|
||||
.line(points[id + '_boxBottomLeft'])
|
||||
.line(points[id + '_boxTopLeft'])
|
||||
.close()
|
||||
.attr('class', 'lining dotted stroke-sm')
|
||||
this.paths[id + '_topCross'] = new this.Path()
|
||||
.move(this.points[id + '_topCrossTL'])
|
||||
.line(this.points[id + '_topCrossBR'])
|
||||
.line(this.points[id + '_topCrossTR'])
|
||||
.line(this.points[id + '_topCrossBL'])
|
||||
.line(this.points[id + '_topCrossTL'])
|
||||
.line(this.points[id + '_topCrossTR'])
|
||||
.move(this.points[id + '_topCrossBR'])
|
||||
.line(this.points[id + '_topCrossBL'])
|
||||
paths[id + '_topCross'] = new Path()
|
||||
.move(points[id + '_topCrossTL'])
|
||||
.line(points[id + '_topCrossBR'])
|
||||
.line(points[id + '_topCrossTR'])
|
||||
.line(points[id + '_topCrossBL'])
|
||||
.line(points[id + '_topCrossTL'])
|
||||
.line(points[id + '_topCrossTR'])
|
||||
.move(points[id + '_topCrossBR'])
|
||||
.line(points[id + '_topCrossBL'])
|
||||
.attr('class', 'lining dotted stroke-sm')
|
||||
if (typeof so.text === 'string') {
|
||||
this.points.textAnchor = this.points[id + '_boxTopLeft']
|
||||
.shiftFractionTowards(this.points[id + '_boxBottomRight'], 0.5)
|
||||
points.textAnchor = points[id + '_boxTopLeft']
|
||||
.shiftFractionTowards(points[id + '_boxBottomRight'], 0.5)
|
||||
.attr('data-text', so.text)
|
||||
.attr('data-text-class', 'center')
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ function draftCharlieFlyExtension({ points, paths, Path, complete, macro, sa, pa
|
|||
.line(points.styleWaistIn)
|
||||
.line(points.flyTop)
|
||||
.hide()
|
||||
paths.seam = paths.saBase.clone().line(points.flyCorner).close().hide().attr('class', 'fabric')
|
||||
paths.seam = paths.saBase.clone().line(points.flyCorner).close().unhide().attr('class', 'fabric')
|
||||
|
||||
if (complete) {
|
||||
macro('cutonfold', {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
# Change log for: @freesewing/examples
|
||||
|
||||
|
||||
## 2.21.0 (2022-06-27)
|
||||
|
||||
### Changed
|
||||
|
||||
- Migrated from Rollup to Esbuild for all builds
|
||||
|
||||
## 2.20.0 (2022-01-24)
|
||||
|
||||
### Added
|
||||
|
||||
- Added plugin_gore example
|
||||
|
||||
### Changed
|
||||
|
||||
- Switched to default import for version from package.json
|
||||
|
||||
## 2.15.0 (2021-04-15)
|
||||
|
||||
### Added
|
||||
|
||||
- Added examples for bartack plugin
|
||||
- Added examples for new buttonhole-start/end snippets
|
||||
|
||||
## 2.0.0 (2019-08-25)
|
||||
|
||||
### Added
|
||||
|
||||
- Initial release
|
||||
|
||||
|
||||
This is the **initial release**, and the start of this change log.
|
||||
|
||||
> Prior to version 2, FreeSewing was not a JavaScript project.
|
||||
> As such, that history is out of scope for this change log.
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
import pkg from '../package.json' assert { type: 'json' }
|
||||
|
||||
const { version } = pkg
|
||||
|
||||
export default {
|
||||
version,
|
||||
name: 'examples',
|
||||
design: 'Joost De Cock',
|
||||
code: 'Joost De Cock',
|
||||
department: 'womenswear',
|
||||
type: 'pattern',
|
||||
difficulty: 1,
|
||||
tags: ['example'],
|
||||
optionGroups: {
|
||||
fit: ['fixme'],
|
||||
},
|
||||
measurements: [],
|
||||
dependencies: {
|
||||
//point_attr: 'path_attr'
|
||||
},
|
||||
parts: [
|
||||
'point_attr',
|
||||
'path_move',
|
||||
'path_line',
|
||||
'path_curve',
|
||||
'path__curve',
|
||||
'path_curve_',
|
||||
'path_close',
|
||||
'path_ops',
|
||||
'path_attr',
|
||||
'path_clone',
|
||||
'path_divide',
|
||||
'path_edge',
|
||||
'path_end',
|
||||
'path_intersects',
|
||||
'path_intersectsx',
|
||||
'path_intersectsy',
|
||||
'path_join',
|
||||
'path_length',
|
||||
'path_noop',
|
||||
'path_offset',
|
||||
'path_reverse',
|
||||
'path_shiftalong',
|
||||
'path_shiftfractionalong',
|
||||
'path_split',
|
||||
'path_start',
|
||||
'path_translate',
|
||||
'path_trim',
|
||||
'plugin_banner',
|
||||
'plugin_bartack',
|
||||
'plugin_bartackalong',
|
||||
'plugin_bartackfractionalong',
|
||||
'plugin_buttons',
|
||||
'plugin_cutonfold',
|
||||
'plugin_dimension',
|
||||
'plugin_gore',
|
||||
'plugin_grainline',
|
||||
'plugin_logo',
|
||||
'plugin_mirror',
|
||||
'plugin_notches',
|
||||
'plugin_round',
|
||||
'plugin_scalebox',
|
||||
'plugin_sprinkle',
|
||||
'plugin_title',
|
||||
'point_angle',
|
||||
'point_attr',
|
||||
'point_clone',
|
||||
'point_copy',
|
||||
'point_dist',
|
||||
'point_dx',
|
||||
'point_dy',
|
||||
'point_flipx',
|
||||
'point_flipy',
|
||||
'point_shift',
|
||||
'point_shiftfractiontowards',
|
||||
'point_shifttowards',
|
||||
'point_shiftoutwards',
|
||||
'point_sitson',
|
||||
'point_sitsroughlyon',
|
||||
'point_rotate',
|
||||
'point_translate',
|
||||
'settings_sa',
|
||||
'snippet',
|
||||
'snippet_attr',
|
||||
'snippet_clone',
|
||||
'snippets_bnotch',
|
||||
'snippets_notch',
|
||||
'snippets_button',
|
||||
'snippets_buttonhole',
|
||||
'snippets_buttonhole_start',
|
||||
'snippets_buttonhole_end',
|
||||
'snippets_snapsocket',
|
||||
'snippets_snapstud',
|
||||
'snippets_logo',
|
||||
'utils_linesintersect',
|
||||
'utils_beamsintersect',
|
||||
'utils_beamintersectsx',
|
||||
'utils_beamintersectsy',
|
||||
'utils_lineintersectscurve',
|
||||
'utils_curvesintersect',
|
||||
'utils_pointonbeam',
|
||||
'utils_pointonline',
|
||||
'utils_pointoncurve',
|
||||
'utils_circlesintersect',
|
||||
'utils_beamintersectscircle',
|
||||
'utils_lineintersectscircle',
|
||||
'utils_curveintersectsy',
|
||||
'utils_curveintersectsx',
|
||||
'utils_splitcurve',
|
||||
'docs_overview',
|
||||
'docs_coords',
|
||||
],
|
||||
options: {
|
||||
focus: '',
|
||||
// Optiongroups are needed for now, because workbench
|
||||
fixme: {
|
||||
pct: 50,
|
||||
min: 0,
|
||||
max: 100,
|
||||
},
|
||||
},
|
||||
}
|
|
@ -1,321 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const docs_coords = {
|
||||
name: 'examples.box_coords',
|
||||
draft: ({ Point, points, paths, Path, part }) => {
|
||||
points.origin = new Point(10, 10)
|
||||
points.x = new Point(100, 10)
|
||||
points.y = new Point(10, 50)
|
||||
points.textX = points.x.shift(135, 2).attr('data-text', 'X')
|
||||
points.textY = points.y.shift(180, 5).attr('data-text', 'Y')
|
||||
paths.coords = new Path()
|
||||
.move(points.y)
|
||||
.line(points.origin)
|
||||
.line(points.x)
|
||||
.attr('class', 'mark')
|
||||
.attr('marker-start', 'url(#dimensionFrom)')
|
||||
.attr('marker-end', 'url(#dimensionTo)')
|
||||
|
||||
return box(part, 100, 50)
|
||||
},
|
||||
}
|
||||
|
||||
export const docs_overview = {
|
||||
name: 'examples.docs_overview',
|
||||
draft: ({ Point, points, Path, paths, options, part }) => {
|
||||
/**
|
||||
* Returs the value passed to it randomized with a given tolerance
|
||||
*/
|
||||
const about = (value, tolerance = 5) => {
|
||||
let randomized = (tolerance / 100) * Math.random() * value
|
||||
let fixed = (1 - tolerance / 100) * value
|
||||
|
||||
return fixed + randomized
|
||||
}
|
||||
|
||||
/**
|
||||
* like about, but also randomly makes value negative
|
||||
* This is for degrees
|
||||
*/
|
||||
const nabout = (value, tolerance = 5) => {
|
||||
if (Math.random() > 0.5) return about(value, tolerance)
|
||||
else return -1 * about(value, tolerance)
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a w*h box that's randomized by tolerance to give it
|
||||
* that hand-drawn look.
|
||||
*
|
||||
* Returns a Path object
|
||||
*/
|
||||
const box = (name, origin, width, height, tolerance = 10) => {
|
||||
let base = height
|
||||
if (width < height) base = width
|
||||
let t = base * (tolerance / 100)
|
||||
points[name + 'TopLeft'] = new Point(about(origin.x, t), about(origin.y, t))
|
||||
points[name + 'BottomLeft'] = new Point(about(origin.x, t), about(origin.y + height, t))
|
||||
points[name + 'BottomRight'] = new Point(
|
||||
about(origin.x + width, t),
|
||||
about(origin.y + height, t)
|
||||
)
|
||||
points[name + 'TopRight'] = new Point(about(origin.x + width, t), about(origin.y, t))
|
||||
points[name + 'Mid'] = points[name + 'TopLeft'].shiftFractionTowards(
|
||||
points[name + 'BottomRight'],
|
||||
0.5
|
||||
)
|
||||
points[name + 'Mid'].y += 3
|
||||
|
||||
let f = 0.3
|
||||
let r = tolerance / 2
|
||||
points[name + 'TopLeftCp1'] = points[name + 'TopLeft']
|
||||
.shiftFractionTowards(points[name + 'BottomLeft'], about(f))
|
||||
.rotate(nabout(r), points[name + 'TopLeft'])
|
||||
points[name + 'TopLeftCp2'] = points[name + 'TopLeft']
|
||||
.shiftFractionTowards(points[name + 'TopRight'], about(f))
|
||||
.rotate(nabout(r), points[name + 'TopLeft'])
|
||||
points[name + 'BottomLeftCp1'] = points[name + 'BottomLeft']
|
||||
.shiftFractionTowards(points[name + 'TopLeft'], about(f))
|
||||
.rotate(nabout(r), points[name + 'BottomLeft'])
|
||||
points[name + 'BottomLeftCp2'] = points[name + 'BottomLeft']
|
||||
.shiftFractionTowards(points[name + 'BottomRight'], about(f))
|
||||
.rotate(nabout(r), points[name + 'BottomLeft'])
|
||||
points[name + 'BottomRightCp1'] = points[name + 'BottomRight']
|
||||
.shiftFractionTowards(points[name + 'BottomLeft'], about(f))
|
||||
.rotate(nabout(r), points[name + 'BottomRight'])
|
||||
points[name + 'BottomRightCp2'] = points[name + 'BottomRight']
|
||||
.shiftFractionTowards(points[name + 'TopRight'], about(f))
|
||||
.rotate(nabout(r), points[name + 'BottomRight'])
|
||||
points[name + 'TopRightCp1'] = points[name + 'TopRight']
|
||||
.shiftFractionTowards(points[name + 'BottomRight'], about(f))
|
||||
.rotate(nabout(r), points[name + 'TopRight'])
|
||||
points[name + 'TopRightCp2'] = points[name + 'TopRight']
|
||||
.shiftFractionTowards(points[name + 'TopLeft'], about(f))
|
||||
.rotate(nabout(r), points[name + 'TopRight'])
|
||||
|
||||
return new Path()
|
||||
.move(points[name + 'TopLeft'])
|
||||
.curve(
|
||||
points[name + 'TopLeftCp1'],
|
||||
points[name + 'BottomLeftCp1'],
|
||||
points[name + 'BottomLeft']
|
||||
)
|
||||
.curve(
|
||||
points[name + 'BottomLeftCp2'],
|
||||
points[name + 'BottomRightCp1'],
|
||||
points[name + 'BottomRight']
|
||||
)
|
||||
.curve(
|
||||
points[name + 'BottomRightCp2'],
|
||||
points[name + 'TopRightCp1'],
|
||||
points[name + 'TopRight']
|
||||
)
|
||||
.curve(points[name + 'TopRightCp2'], points[name + 'TopLeftCp2'], points[name + 'TopLeft'])
|
||||
.close()
|
||||
.attr('class', options.focus === name ? 'note' : 'fabric')
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws an arrow from to
|
||||
* Returns a Path object
|
||||
*/
|
||||
const arrow = (name, text = '', tolerance = 10) => {
|
||||
let from = points[name + 'From']
|
||||
let to = points[name + 'To']
|
||||
from = from.shiftTowards(to, 3)
|
||||
to = to.shiftTowards(from, 3)
|
||||
let base = from.dist(to)
|
||||
let t = base * (tolerance / 100)
|
||||
from.x = about(from.x, t)
|
||||
from.x = about(from.x, t)
|
||||
to.x = about(to.x, t)
|
||||
to.x = about(to.x, t)
|
||||
let f = 0.3
|
||||
let r = tolerance / 2
|
||||
points[name + 'FromCp'] = from.shiftFractionTowards(to, about(f)).rotate(nabout(r), from)
|
||||
points[name + 'ToCp'] = to.shiftFractionTowards(from, about(f)).rotate(nabout(r), to)
|
||||
points[name + 'Tip1'] = to.shiftTowards(from, about(3.8)).rotate(about(15), to)
|
||||
points[name + 'Tip2'] = to.shiftTowards(from, about(3.5)).rotate(about(-15), to)
|
||||
let path = new Path()
|
||||
.move(from)
|
||||
.curve(points[name + 'FromCp'], points[name + 'ToCp'], to)
|
||||
.move(points[name + 'Tip1'])
|
||||
.line(to)
|
||||
.line(points[name + 'Tip2'])
|
||||
.attr('class', 'fabric')
|
||||
if (options.focus === name) path = path.attr('class', 'note')
|
||||
if (text)
|
||||
return path
|
||||
.attr('data-text', ' ' + text)
|
||||
.attr('data-text-class', 'scribble')
|
||||
.attr('data-text-class', options.focus === name ? 'fill-note' : '')
|
||||
else return path
|
||||
}
|
||||
|
||||
const drawBox = (name, x, y, width, height, tolerance = 5, text = true) => {
|
||||
points[name + 'Origin'] = new Point(x, y)
|
||||
paths[name] = box(name, points[name + 'Origin'], width, height, tolerance)
|
||||
if (text) {
|
||||
points[name + 'Mid'].attr('data-text', name).attr('data-text-class', 'center scribble')
|
||||
if (options.focus === name) points[name + 'Mid'].attr('data-text-class', 'fill-note')
|
||||
}
|
||||
}
|
||||
|
||||
const svgLogo = (anchor, size = 1) => {
|
||||
points.svg15 = anchor
|
||||
.shift(45, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg3 = anchor
|
||||
.shift(0, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg45 = anchor
|
||||
.shift(-45, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg6 = anchor
|
||||
.shift(-90, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg75 = anchor
|
||||
.shift(-135, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg9 = anchor
|
||||
.shift(180, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg105 = anchor
|
||||
.shift(135, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svg12 = anchor
|
||||
.shift(90, 4 * size)
|
||||
.attr('data-circle', 1.2 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.svgText = anchor
|
||||
.clone()
|
||||
.attr('data-text', 'SVG')
|
||||
.attr('data-text-class', 'text-xl scribble')
|
||||
points.svgText.x += size * 7
|
||||
points.svgText.y += 6
|
||||
paths.svgLogo = new Path()
|
||||
.move(points.svg15)
|
||||
.line(points.svg75)
|
||||
.move(points.svg3)
|
||||
.line(points.svg9)
|
||||
.move(points.svg45)
|
||||
.line(points.svg105)
|
||||
.move(points.svg6)
|
||||
.line(points.svg12)
|
||||
.attr('class', 'stroke-l')
|
||||
}
|
||||
const reactLogo = (anchor, size = 1) => {
|
||||
h = 3 * size
|
||||
w = 6 * size
|
||||
points.reactTop1 = anchor.shift(45, w)
|
||||
points.reactBottom1 = anchor.shift(-135, w)
|
||||
points.reactTop1Cp1 = points.reactTop1.shift(135, h)
|
||||
points.reactTop1Cp2 = points.reactTop1.shift(-45, h)
|
||||
points.reactBottom1Cp1 = points.reactBottom1.shift(135, h)
|
||||
points.reactBottom1Cp2 = points.reactBottom1.shift(-45, h)
|
||||
points.reactTop2 = points.reactTop1.rotate(60, anchor)
|
||||
points.reactBottom2 = points.reactBottom1.rotate(60, anchor)
|
||||
points.reactTop2Cp1 = points.reactTop1Cp1.rotate(60, anchor)
|
||||
points.reactTop2Cp2 = points.reactTop1Cp2.rotate(60, anchor)
|
||||
points.reactBottom2Cp1 = points.reactBottom1Cp1.rotate(60, anchor)
|
||||
points.reactBottom2Cp2 = points.reactBottom1Cp2.rotate(60, anchor)
|
||||
points.reactTop3 = points.reactTop1.rotate(-60, anchor)
|
||||
points.reactBottom3 = points.reactBottom1.rotate(-60, anchor)
|
||||
points.reactTop3Cp1 = points.reactTop1Cp1.rotate(-60, anchor)
|
||||
points.reactTop3Cp2 = points.reactTop1Cp2.rotate(-60, anchor)
|
||||
points.reactBottom3Cp1 = points.reactBottom1Cp1.rotate(-60, anchor)
|
||||
points.reactBottom3Cp2 = points.reactBottom1Cp2.rotate(-60, anchor)
|
||||
points.svgLogo = anchor
|
||||
.clone()
|
||||
.attr('data-circle', 1 * size)
|
||||
.attr('data-circle-class', 'fill-fabric')
|
||||
points.reactText = anchor
|
||||
.clone()
|
||||
.attr('data-text', 'React')
|
||||
.attr('data-text-class', 'text-xl scribble')
|
||||
points.reactText.x += size * 7
|
||||
points.reactText.y += 6
|
||||
|
||||
paths.reactLogo = new Path()
|
||||
.move(points.reactTop1)
|
||||
.curve(points.reactTop1Cp1, points.reactBottom1Cp1, points.reactBottom1)
|
||||
.curve(points.reactBottom1Cp2, points.reactTop1Cp2, points.reactTop1)
|
||||
.close()
|
||||
.move(points.reactTop2)
|
||||
.curve(points.reactTop2Cp1, points.reactBottom2Cp1, points.reactBottom2)
|
||||
.curve(points.reactBottom2Cp2, points.reactTop2Cp2, points.reactTop2)
|
||||
.close()
|
||||
.move(points.reactTop3)
|
||||
.curve(points.reactTop3Cp1, points.reactBottom3Cp1, points.reactBottom3)
|
||||
.curve(points.reactBottom3Cp2, points.reactTop3Cp2, points.reactTop3)
|
||||
.close()
|
||||
}
|
||||
|
||||
// Other parts first so they're behind
|
||||
drawBox('Part4', 4, -19, 40, 65, 5, false)
|
||||
drawBox('Part3', 1, -16, 40, 65, 5, false)
|
||||
drawBox('Part2', -2, -13, 40, 65, 5, false)
|
||||
drawBox('Part', -5, -10, 40, 65, 5)
|
||||
paths.Part4.attr('class', 'fill-bg')
|
||||
paths.Part3.attr('class', 'fill-bg')
|
||||
paths.Part2.attr('class', 'fill-bg')
|
||||
paths.Part.attr('class', 'fill-bg')
|
||||
points.PartMid.y = points.PartTopLeft.y + 9
|
||||
let x = 0
|
||||
let y = 0
|
||||
let w = 30
|
||||
let h = 15
|
||||
drawBox('Points', x, y, w, h)
|
||||
y += 18
|
||||
drawBox('Paths', x, y, w, h)
|
||||
y += 18
|
||||
drawBox('Snippets', x, y, w, h)
|
||||
x = -35
|
||||
y = -3
|
||||
w = 25
|
||||
h = 20
|
||||
drawBox('config', x, y, w, h)
|
||||
y += 23
|
||||
drawBox('Store', x, y, w, h)
|
||||
x = -40
|
||||
y = -30
|
||||
drawBox('Pattern', x, y, 90, 90)
|
||||
points.PatternMid.y = points.PatternTopLeft.y + 9
|
||||
|
||||
drawBox('settings', -100, 6, 40, 20)
|
||||
drawBox('draft', 80, 3, 20, 25)
|
||||
|
||||
points.arrow1From = points.settingsTopRight.shiftFractionTowards(
|
||||
points.settingsBottomRight,
|
||||
0.5
|
||||
)
|
||||
points.arrow1To = points.PatternTopLeft.shiftFractionTowards(points.PatternBottomLeft, 0.5)
|
||||
paths.arrow1 = arrow('arrow1')
|
||||
points.arrow2From = points.PatternTopRight.shiftFractionTowards(points.PatternBottomRight, 0.5)
|
||||
points.arrow2To = points.draftTopLeft.shiftFractionTowards(points.draftBottomLeft, 0.5)
|
||||
paths.arrow2 = arrow('arrow2', 'draft()')
|
||||
|
||||
svgLogo(points.draftMid.shift(70, 50))
|
||||
reactLogo(points.draftMid.shift(-80, 36))
|
||||
|
||||
points.arrow3From = points.draftTopLeft.shiftFractionTowards(points.draftTopRight, 0.5)
|
||||
points.arrow3To = points.svgText.clone()
|
||||
paths.arrow3 = arrow('arrow3', 'render()')
|
||||
points.arrow4From = points.draftBottomLeft.shiftFractionTowards(points.draftBottomRight, 0.5)
|
||||
points.arrow4To = points.reactText.clone().shift(40, 15)
|
||||
paths.arrow4 = arrow('arrow4')
|
||||
|
||||
paths.extend = new Path()
|
||||
.move(points.draftTopRight)
|
||||
.line(points.draftTopRight.shift(0, 40))
|
||||
.attr('class', 'hidden')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
|
@ -1,384 +0,0 @@
|
|||
import { Design } from '@freesewing/core'
|
||||
import { pluginBundle } from '@freesewing/plugin-bundle'
|
||||
import { gorePlugin } from '@freesewing/plugin-gore'
|
||||
import { data } from '../data.mjs'
|
||||
|
||||
// Path API
|
||||
import {
|
||||
path__curve,
|
||||
path_addclass,
|
||||
path_attr,
|
||||
path_move,
|
||||
path_line,
|
||||
path_curve,
|
||||
path_curve_,
|
||||
path_close,
|
||||
path_ops,
|
||||
path_clone,
|
||||
path_divide,
|
||||
path_edge,
|
||||
path_end,
|
||||
path_intersects,
|
||||
path_intersectsx,
|
||||
path_intersectsy,
|
||||
path_join,
|
||||
path_length,
|
||||
path_noop,
|
||||
path_offset,
|
||||
path_reverse,
|
||||
path_shiftalong,
|
||||
path_shiftfractionalong,
|
||||
path_smurve,
|
||||
path_smurve_,
|
||||
path_split,
|
||||
path_start,
|
||||
path_translate,
|
||||
path_trim,
|
||||
} from './path.mjs'
|
||||
|
||||
// Point API
|
||||
import {
|
||||
point_addcircle,
|
||||
point_addtext,
|
||||
point_angle,
|
||||
point_attr,
|
||||
point_clone,
|
||||
point_copy,
|
||||
point_dist,
|
||||
point_dx,
|
||||
point_dy,
|
||||
point_flipx,
|
||||
point_flipy,
|
||||
point_setcircle,
|
||||
point_settext,
|
||||
point_shift,
|
||||
point_shiftfractiontowards,
|
||||
point_shifttowards,
|
||||
point_shiftoutwards,
|
||||
point_sitson,
|
||||
point_sitsroughlyon,
|
||||
point_rotate,
|
||||
point_translate,
|
||||
} from './point.mjs'
|
||||
|
||||
// Snippet API
|
||||
import { snippet, snippet_attr, snippet_clone } from './snippet.mjs'
|
||||
|
||||
// Utils API
|
||||
import {
|
||||
utils_linesintersect,
|
||||
utils_beamsintersect,
|
||||
utils_beamintersectsx,
|
||||
utils_beamintersectsy,
|
||||
utils_lineintersectscurve,
|
||||
utils_curvesintersect,
|
||||
utils_pointonbeam,
|
||||
utils_pointonline,
|
||||
utils_pointoncurve,
|
||||
utils_circlesintersect,
|
||||
utils_beamintersectscircle,
|
||||
utils_lineintersectscircle,
|
||||
utils_curveintersectsx,
|
||||
utils_curveintersectsy,
|
||||
utils_splitcurve,
|
||||
} from './utils.mjs'
|
||||
|
||||
// Plugins
|
||||
import {
|
||||
plugin_banner,
|
||||
plugin_bartack,
|
||||
plugin_bartackalong,
|
||||
plugin_bartackfractionalong,
|
||||
plugin_buttons,
|
||||
plugin_cutonfold,
|
||||
plugin_dimension,
|
||||
plugin_gore,
|
||||
plugin_grainline,
|
||||
plugin_logo,
|
||||
plugin_mirror,
|
||||
plugin_notches,
|
||||
plugin_round,
|
||||
plugin_sprinkle,
|
||||
plugin_scalebox,
|
||||
plugin_title,
|
||||
} from './plugins.mjs'
|
||||
|
||||
// Snippets
|
||||
import {
|
||||
snippet_bnotch,
|
||||
snippet_notch,
|
||||
snippet_button,
|
||||
snippet_buttonhole,
|
||||
snippet_buttonholestart,
|
||||
snippet_buttonholeend,
|
||||
snippet_snapsocket,
|
||||
snippet_snapstud,
|
||||
snippet_logo,
|
||||
} from './snippets.mjs'
|
||||
|
||||
// Stacks
|
||||
import {
|
||||
stacks_top,
|
||||
stacks_left,
|
||||
stacks_right,
|
||||
stacks_bottom,
|
||||
stacks_leftEye,
|
||||
stacks_rightEye,
|
||||
stacks_mouth,
|
||||
} from './stacks.mjs'
|
||||
|
||||
// Settings
|
||||
import { settings_sa } from './settings.mjs'
|
||||
|
||||
// Docs illustrations
|
||||
import { docs_coords, docs_overview } from './docs.mjs'
|
||||
|
||||
// Setup our new design
|
||||
const Examples = new Design({
|
||||
data,
|
||||
parts: [
|
||||
// Path API
|
||||
path__curve,
|
||||
path_addclass,
|
||||
path_attr,
|
||||
path_move,
|
||||
path_line,
|
||||
path_curve,
|
||||
path_curve_,
|
||||
path_close,
|
||||
path_ops,
|
||||
path_clone,
|
||||
path_divide,
|
||||
path_edge,
|
||||
path_end,
|
||||
path_intersects,
|
||||
path_intersectsx,
|
||||
path_intersectsy,
|
||||
path_join,
|
||||
path_length,
|
||||
path_noop,
|
||||
path_offset,
|
||||
path_reverse,
|
||||
path_shiftalong,
|
||||
path_shiftfractionalong,
|
||||
path_smurve,
|
||||
path_smurve_,
|
||||
path_split,
|
||||
path_start,
|
||||
path_translate,
|
||||
path_trim,
|
||||
|
||||
// Point API
|
||||
point_addcircle,
|
||||
point_addtext,
|
||||
point_angle,
|
||||
point_attr,
|
||||
point_clone,
|
||||
point_copy,
|
||||
point_dist,
|
||||
point_dx,
|
||||
point_dy,
|
||||
point_flipx,
|
||||
point_flipy,
|
||||
point_setcircle,
|
||||
point_settext,
|
||||
point_shift,
|
||||
point_shiftfractiontowards,
|
||||
point_shifttowards,
|
||||
point_shiftoutwards,
|
||||
point_sitson,
|
||||
point_sitsroughlyon,
|
||||
point_rotate,
|
||||
point_translate,
|
||||
|
||||
// Snippet API
|
||||
snippet,
|
||||
snippet_attr,
|
||||
snippet_clone,
|
||||
|
||||
// Utils API
|
||||
utils_linesintersect,
|
||||
utils_beamsintersect,
|
||||
utils_beamintersectsx,
|
||||
utils_beamintersectsy,
|
||||
utils_lineintersectscurve,
|
||||
utils_curvesintersect,
|
||||
utils_pointonbeam,
|
||||
utils_pointonline,
|
||||
utils_pointoncurve,
|
||||
utils_circlesintersect,
|
||||
utils_beamintersectscircle,
|
||||
utils_lineintersectscircle,
|
||||
utils_curveintersectsx,
|
||||
utils_curveintersectsy,
|
||||
utils_splitcurve,
|
||||
|
||||
// Plugins
|
||||
plugin_banner,
|
||||
plugin_bartack,
|
||||
plugin_bartackalong,
|
||||
plugin_bartackfractionalong,
|
||||
plugin_buttons,
|
||||
plugin_cutonfold,
|
||||
plugin_dimension,
|
||||
plugin_gore,
|
||||
plugin_grainline,
|
||||
plugin_logo,
|
||||
plugin_mirror,
|
||||
plugin_notches,
|
||||
plugin_round,
|
||||
plugin_sprinkle,
|
||||
plugin_scalebox,
|
||||
plugin_title,
|
||||
|
||||
// Snippets
|
||||
snippet_bnotch,
|
||||
snippet_notch,
|
||||
snippet_button,
|
||||
snippet_buttonhole,
|
||||
snippet_buttonholestart,
|
||||
snippet_buttonholeend,
|
||||
snippet_snapsocket,
|
||||
snippet_snapstud,
|
||||
snippet_logo,
|
||||
|
||||
// Stacks
|
||||
stacks_top,
|
||||
stacks_left,
|
||||
stacks_right,
|
||||
stacks_bottom,
|
||||
stacks_leftEye,
|
||||
stacks_rightEye,
|
||||
stacks_mouth,
|
||||
|
||||
// Settings
|
||||
settings_sa,
|
||||
|
||||
// Docs
|
||||
docs_coords,
|
||||
docs_overview,
|
||||
],
|
||||
plugins: [pluginBundle, gorePlugin],
|
||||
})
|
||||
|
||||
// Named exports
|
||||
export {
|
||||
// Path API
|
||||
path__curve,
|
||||
path_addclass,
|
||||
path_attr,
|
||||
path_move,
|
||||
path_line,
|
||||
path_curve,
|
||||
path_curve_,
|
||||
path_close,
|
||||
path_ops,
|
||||
path_clone,
|
||||
path_divide,
|
||||
path_edge,
|
||||
path_end,
|
||||
path_intersects,
|
||||
path_intersectsx,
|
||||
path_intersectsy,
|
||||
path_join,
|
||||
path_length,
|
||||
path_noop,
|
||||
path_offset,
|
||||
path_reverse,
|
||||
path_shiftalong,
|
||||
path_shiftfractionalong,
|
||||
path_smurve,
|
||||
path_smurve_,
|
||||
path_split,
|
||||
path_start,
|
||||
path_translate,
|
||||
path_trim,
|
||||
|
||||
// Point API
|
||||
point_addcircle,
|
||||
point_addtext,
|
||||
point_angle,
|
||||
point_attr,
|
||||
point_clone,
|
||||
point_copy,
|
||||
point_dist,
|
||||
point_dx,
|
||||
point_dy,
|
||||
point_flipx,
|
||||
point_flipy,
|
||||
point_setcircle,
|
||||
point_settext,
|
||||
point_shift,
|
||||
point_shiftfractiontowards,
|
||||
point_shifttowards,
|
||||
point_shiftoutwards,
|
||||
point_sitson,
|
||||
point_sitsroughlyon,
|
||||
point_rotate,
|
||||
point_translate,
|
||||
|
||||
// Snippet API
|
||||
snippet,
|
||||
snippet_attr,
|
||||
snippet_clone,
|
||||
|
||||
// Utils API
|
||||
utils_linesintersect,
|
||||
utils_beamsintersect,
|
||||
utils_beamintersectsx,
|
||||
utils_beamintersectsy,
|
||||
utils_lineintersectscurve,
|
||||
utils_curvesintersect,
|
||||
utils_pointonbeam,
|
||||
utils_pointonline,
|
||||
utils_pointoncurve,
|
||||
utils_circlesintersect,
|
||||
utils_beamintersectscircle,
|
||||
utils_lineintersectscircle,
|
||||
utils_curveintersectsx,
|
||||
utils_curveintersectsy,
|
||||
utils_splitcurve,
|
||||
|
||||
// Plugins
|
||||
plugin_banner,
|
||||
plugin_bartack,
|
||||
plugin_bartackalong,
|
||||
plugin_bartackfractionalong,
|
||||
plugin_buttons,
|
||||
plugin_cutonfold,
|
||||
plugin_dimension,
|
||||
plugin_gore,
|
||||
plugin_grainline,
|
||||
plugin_logo,
|
||||
plugin_mirror,
|
||||
plugin_notches,
|
||||
plugin_round,
|
||||
plugin_sprinkle,
|
||||
plugin_scalebox,
|
||||
plugin_title,
|
||||
|
||||
// Snippets
|
||||
snippet_bnotch,
|
||||
snippet_notch,
|
||||
snippet_button,
|
||||
snippet_buttonhole,
|
||||
snippet_buttonholestart,
|
||||
snippet_buttonholeend,
|
||||
snippet_snapsocket,
|
||||
snippet_snapstud,
|
||||
snippet_logo,
|
||||
|
||||
// Stacks
|
||||
stacks_top,
|
||||
stacks_left,
|
||||
stacks_right,
|
||||
stacks_bottom,
|
||||
stacks_leftEye,
|
||||
stacks_rightEye,
|
||||
stacks_mouth,
|
||||
|
||||
// Docs
|
||||
docs_coords,
|
||||
docs_overview,
|
||||
Examples,
|
||||
}
|
|
@ -1,745 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const path__curve = {
|
||||
name: 'examples.path__curve',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(5, 20)
|
||||
points.cp2 = new Point(60, 30)
|
||||
points.to = new Point(90, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
._curve(points.cp2, points.to)
|
||||
.attr('data-text', 'Path._curve()')
|
||||
.attr('data-text-class', 'text-sm center fill-note')
|
||||
|
||||
return box(part, 100, 25)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_addclass = {
|
||||
name: 'examples.path_addclass',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(5, 10)
|
||||
points.to = new Point(95, 10)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.addClass('note dashed')
|
||||
|
||||
return box(part, 100, 20)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_attr = {
|
||||
name: 'examples.path_attr',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.B = new Point(10, 50)
|
||||
points.BCp2 = new Point(40, 10)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, 90)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr('class', 'canvas')
|
||||
.attr('data-text', 'supportFreesewingBecomeAPatron')
|
||||
.attr('data-text-class', 'text-xs center')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_clone = {
|
||||
name: 'examples.path_clone',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
paths.clone = paths.example
|
||||
.clone()
|
||||
.attr('class', 'note lashed stroke-l')
|
||||
.attr('style', 'stroke-opacity: 0.5')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_close = {
|
||||
name: 'examples.path_close',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.cp2 = new Point(60, 30)
|
||||
points.to = new Point(90, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
._curve(points.cp2, points.to)
|
||||
.close()
|
||||
.reverse() // To keep text from being upside-down
|
||||
.attr('data-text', 'Path._close()')
|
||||
.attr('data-text-class', 'text-sm right fill-note')
|
||||
|
||||
return box(part, 100, 25)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_curve = {
|
||||
name: 'examples.path_curve',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.cp1 = new Point(40, 0)
|
||||
points.cp2 = new Point(60, 30)
|
||||
points.to = new Point(90, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve(points.cp1, points.cp2, points.to)
|
||||
.attr('data-text', 'Path.curve()')
|
||||
.attr('data-text-class', 'text-sm center fill-note')
|
||||
|
||||
return box(part, 100, 25)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_curve_ = {
|
||||
name: 'examples.path_curve_',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.cp1 = new Point(40, 0)
|
||||
points.to = new Point(90, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve_(points.cp1, points.to)
|
||||
.attr('data-text', 'Path.curve_()')
|
||||
.attr('data-text-class', 'text-sm center fill-note')
|
||||
|
||||
return box(part, 100, 25)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_divide = {
|
||||
name: 'examples.path_divide',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.A = new Point(55, 40)
|
||||
points.B = new Point(10, 70)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 60)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(50, 80)
|
||||
points.DCp1 = new Point(140, 50)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D)
|
||||
.close()
|
||||
|
||||
let style = 'stroke-width: 4; stroke-opacity: 0.5;'
|
||||
let i = 0
|
||||
for (let p of paths.example.divide()) {
|
||||
i++
|
||||
paths[i] = p.attr('style', style).attr('style', `stroke: hsl(${i * 70}, 100%, 50%)`)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_edge = {
|
||||
name: 'examples.path_edge',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(-60, 90)
|
||||
points.E = new Point(90, 190)
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.E, points.D, points.A)
|
||||
.close()
|
||||
|
||||
for (let i of [
|
||||
'topLeft',
|
||||
'topRight',
|
||||
'bottomLeft',
|
||||
'bottomRight',
|
||||
'top',
|
||||
'left',
|
||||
'bottom',
|
||||
'right',
|
||||
])
|
||||
snippets[i] = new Snippet('notch', paths.demo.edge(i))
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_end = {
|
||||
name: 'examples.path_end',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.demo = new Path().move(points.A).line(points.B).curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
snippets.end = new Snippet('notch', paths.demo.end())
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_intersects = {
|
||||
name: 'examples.path_intersects',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(50, 130)
|
||||
points.DCp1 = new Point(150, 30)
|
||||
|
||||
points._A = new Point(55, 40)
|
||||
points._B = new Point(0, 55)
|
||||
points._BCp2 = new Point(40, -20)
|
||||
points._C = new Point(90, 40)
|
||||
points._CCp1 = new Point(50, -30)
|
||||
points._D = new Point(40, 120)
|
||||
points._DCp1 = new Point(180, 40)
|
||||
|
||||
paths.demo1 = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D)
|
||||
paths.demo2 = new Path()
|
||||
.move(points._A)
|
||||
.line(points._B)
|
||||
.curve(points._BCp2, points._CCp1, points._C)
|
||||
.curve(points._DCp1, points._DCp1, points._D)
|
||||
|
||||
for (let p of paths.demo1.intersects(paths.demo2)) {
|
||||
snippets[part.getId()] = new Snippet('notch', p)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_intersectsx = {
|
||||
name: 'examples.path_intersectsx',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(95, 50)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(50, 130)
|
||||
points.DCp1 = new Point(150, 30)
|
||||
|
||||
points.top = new Point(60, -10)
|
||||
points.bot = new Point(60, 140)
|
||||
|
||||
paths.line = new Path().move(points.top).line(points.bot).attr('class', 'lining dashed')
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D)
|
||||
|
||||
for (let p of paths.demo.intersectsX(60)) {
|
||||
snippets[part.getId()] = new Snippet('notch', p)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_intersectsy = {
|
||||
name: 'examples.path_intersectsy',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(55, 40)
|
||||
points.B = new Point(10, 70)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 60)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(50, 80)
|
||||
points.DCp1 = new Point(140, 50)
|
||||
|
||||
points.top = new Point(10, 58)
|
||||
points.bot = new Point(130, 58)
|
||||
|
||||
paths.line = new Path().move(points.top).line(points.bot).attr('class', 'lining dashed')
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D)
|
||||
for (let p of paths.demo.intersectsY(58)) {
|
||||
snippets[part.getId()] = new Snippet('notch', p)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_join = {
|
||||
name: 'examples.path_join',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.path1 = new Path().move(points.A).line(points.B).attr('class', 'various')
|
||||
|
||||
paths.path2 = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr('class', 'canvas')
|
||||
|
||||
paths.joint = paths.path1
|
||||
.join(paths.path2)
|
||||
.attr('class', 'note lashed stroke-l')
|
||||
.attr('style', 'stroke-opacity: 0.5')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_length = {
|
||||
name: 'examples.path_length',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
macro('pd', {
|
||||
path: paths.example,
|
||||
d: -20,
|
||||
})
|
||||
|
||||
macro('pd', {
|
||||
path: new Path().move(points.B).line(points.A),
|
||||
d: 10,
|
||||
})
|
||||
|
||||
macro('pd', {
|
||||
path: new Path().move(points.B).curve(points.BCp2, points.CCp1, points.C),
|
||||
d: -10,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_line = {
|
||||
name: 'examples.path_line',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(90, 10)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.attr('data-text', 'Path.line()')
|
||||
.attr('data-text-class', 'text-sm center fill-note')
|
||||
|
||||
return box(part, 100, 15)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_move = {
|
||||
name: 'examples.path_move',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.to = new Point(50, 10)
|
||||
.attr('data-text', 'Path.move()')
|
||||
.attr('data-text-class', 'fill-note center')
|
||||
|
||||
paths.noline = new Path().move(points.to)
|
||||
|
||||
return box(part, 100, 15)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_noop = {
|
||||
name: 'examples.path_noop',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.left = new Point(10, 10)
|
||||
points.dartLeft = new Point(40, 10)
|
||||
points.dartTip = new Point(50, 50)
|
||||
points.dartRight = new Point(60, 10)
|
||||
points.right = new Point(90, 10)
|
||||
|
||||
paths.without = new Path()
|
||||
.move(points.left)
|
||||
.line(points.dartLeft)
|
||||
.noop('dart')
|
||||
.line(points.right)
|
||||
|
||||
paths.withDart = paths.without
|
||||
.insop('dart', new Path().line(points.dartTip).line(points.dartRight))
|
||||
.attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_offset = {
|
||||
name: 'examples.path_offset',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.line(points.A)
|
||||
.close()
|
||||
|
||||
paths.offset = paths.example.offset(-10).attr('class', 'interfacing')
|
||||
|
||||
paths.lineOffset = new Path().move(points.A).line(points.B).offset(-5).attr('class', 'various')
|
||||
|
||||
paths.curveOffset = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.offset(-5)
|
||||
.attr('class', 'canvas')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_ops = {
|
||||
name: 'examples.path_ops',
|
||||
draft: ({ Point, points, Path, paths, options, part }) => {
|
||||
const textClasses = (label) =>
|
||||
options.focus === label ? 'center text-xs fill-note' : 'center text-xs'
|
||||
|
||||
points.A = new Point(10, 10)
|
||||
.attr('data-text', 'Path.move()')
|
||||
.attr('data-text-class', textClasses('move'))
|
||||
points.B = new Point(70, 30)
|
||||
points.BCp2 = new Point(40, 10)
|
||||
points.C = new Point(90, -50)
|
||||
points.CCp1 = new Point(125, -30)
|
||||
points.D = new Point(20, -50)
|
||||
points.DCp = new Point(40, 0)
|
||||
points.E = new Point(-20, -20)
|
||||
points.ECp = new Point(-20, -50)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.attr('data-text', 'Path.line()')
|
||||
.attr('data-text-class', textClasses('line'))
|
||||
|
||||
paths.curve = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr('data-text', 'Path.curve()')
|
||||
.attr('data-text-class', textClasses('curve'))
|
||||
|
||||
paths._curve = new Path()
|
||||
.move(points.C)
|
||||
._curve(points.DCp, points.D)
|
||||
.attr('data-text', 'Path._curve()')
|
||||
.attr('data-text-class', textClasses('_curve'))
|
||||
|
||||
paths.curve_ = new Path()
|
||||
.move(points.D)
|
||||
.curve_(points.ECp, points.E)
|
||||
.attr('data-text', 'Path.curve_()')
|
||||
.attr('data-text-class', textClasses('curve_'))
|
||||
|
||||
paths.close = new Path()
|
||||
.move(points.E)
|
||||
.line(points.A)
|
||||
.attr('data-text', 'Path.close()')
|
||||
.attr('data-text-class', textClasses('close'))
|
||||
|
||||
paths.example = paths.line.join(paths.curve).join(paths._curve).join(paths.curve_).close()
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_reverse = {
|
||||
name: 'examples.path_reverse',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr('data-text', 'freesewingIsMadeByJoostDeCockAndContributors')
|
||||
.attr('data-text-class', 'text-xs fill-note')
|
||||
|
||||
paths.reverse = paths.example
|
||||
.reverse()
|
||||
.attr('data-text', 'freesewingIsMadeByJoostDeCockAndContributors')
|
||||
.attr('data-text-class', 'text-xs fill-lining')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_shiftalong = {
|
||||
name: 'examples.path_shiftalong',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
points.x1 = paths.example
|
||||
.shiftAlong(20)
|
||||
.attr('data-text', '2cm')
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
.attr('data-text-lineheight', 6)
|
||||
points.x2 = paths.example
|
||||
.shiftAlong(90)
|
||||
.attr('data-text', '9cm')
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
snippets.x1 = new Snippet('notch', points.x1)
|
||||
snippets.x2 = new Snippet('notch', points.x2)
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_shiftfractionalong = {
|
||||
name: 'examples.path_shiftfractionalong',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
points.x1 = paths.example
|
||||
.shiftFractionAlong(0.2)
|
||||
.attr('data-text', '20%')
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
.attr('data-text-lineheight', 6)
|
||||
points.x2 = paths.example
|
||||
.shiftFractionAlong(0.9)
|
||||
.attr('data-text', '90%')
|
||||
.attr('data-text-class', 'center fill-note')
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
snippets.xl = new Snippet('notch', points.x1)
|
||||
snippets.x2 = new Snippet('notch', points.x2)
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_smurve = {
|
||||
name: 'examples.path_smurve',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.cp1 = new Point(40, 10)
|
||||
points.cp2 = new Point(60, 30)
|
||||
points.to = new Point(90, 20)
|
||||
points.scp2 = new Point(140, 30)
|
||||
points.sto = new Point(170, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve(points.cp1, points.cp2, points.to)
|
||||
.smurve(points.scp2, points.sto)
|
||||
.attr('data-text', 'Path.smurve()')
|
||||
.attr('data-text-class', 'text-sm center fill-note')
|
||||
|
||||
return box(part, 180, 40)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_smurve_ = {
|
||||
name: 'examples.path_smurve_',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.cp1 = new Point(40, 10)
|
||||
points.cp2 = new Point(60, 30)
|
||||
points.to = new Point(90, 20)
|
||||
points.sto = new Point(170, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve(points.cp1, points.cp2, points.to)
|
||||
.smurve_(points.sto)
|
||||
.attr('data-text', 'Path.smurve_()')
|
||||
.attr('data-text-class', 'text-sm center fill-note')
|
||||
|
||||
return box(part, 180, 40)
|
||||
},
|
||||
}
|
||||
|
||||
export const path_split = {
|
||||
name: 'examples.path_split',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(50, 130)
|
||||
points.DCp1 = new Point(150, 30)
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.D)
|
||||
.curve(points.DCp1, points.DCp1, points.C)
|
||||
.curve(points.CCp1, points.BCp2, points.B)
|
||||
.line(points.A)
|
||||
|
||||
points.split = paths.demo.shiftFractionAlong(0.75)
|
||||
snippets.x = new Snippet('x', points.split)
|
||||
|
||||
let style = 'stroke-width: 3; stroke-opacity: 0.5;'
|
||||
let halves = paths.demo.split(points.split)
|
||||
for (let i in halves) {
|
||||
paths[i] = halves[i].attr('style', style).attr('style', `stroke: hsl(${i * 70}, 100%, 50%)`)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_start = {
|
||||
name: 'examples.path_start',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
snippets.start = new Snippet('notch', paths.example.start())
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_translate = {
|
||||
name: 'examples.path_translate',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.A = new Path().move(points.A).line(points.B).curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
paths.B = paths.A.translate(60, 30)
|
||||
|
||||
points.step1 = points.B.shift(0, 60)
|
||||
points.step2 = points.step1.shift(-90, 30)
|
||||
macro('ld', {
|
||||
from: points.B,
|
||||
to: points.step1,
|
||||
noStartMarker: true,
|
||||
})
|
||||
macro('ld', {
|
||||
from: points.step1,
|
||||
to: points.step2,
|
||||
noStartMarker: true,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const path_trim = {
|
||||
name: 'examples.path_trim',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.center = new Point(0, 0)
|
||||
points.base = new Point(0, 10)
|
||||
points.tip = new Point(0, 50)
|
||||
points.tipCpRight = new Point(30, 50)
|
||||
points.tipCpLeft = new Point(-30, 50)
|
||||
paths.example = new Path().move(points.base)
|
||||
for (let i = 0; i < 4; i++) {
|
||||
points['base' + i] = points.base.rotate(60 * i, points.center)
|
||||
points['tip' + i] = points.tip.rotate(60 * i, points.center)
|
||||
points['tipCpRight' + i] = points.tipCpRight.rotate(60 * i, points.center)
|
||||
points['tipCpLeft' + i] = points.tipCpLeft.rotate(60 * i, points.center)
|
||||
if (i < 2) {
|
||||
paths.example
|
||||
.line(points['base' + i])
|
||||
.curve(points['base' + i], points['tipCpLeft' + i], points['tip' + i])
|
||||
.curve(points['tipCpRight' + i], points['base' + i], points['base' + i])
|
||||
} else {
|
||||
paths.example
|
||||
.line(points['base' + i])
|
||||
.line(points['tip' + i])
|
||||
.line(points['tipCpRight' + i])
|
||||
.line(points['base' + i])
|
||||
}
|
||||
}
|
||||
|
||||
paths.offset = paths.example.offset(10).attr('class', 'lining dotted stroke-sm')
|
||||
|
||||
paths.trimmed = paths.offset
|
||||
.trim()
|
||||
.attr('class', 'various stroke-xl')
|
||||
.attr('style', 'stroke-opacity: 0.5;')
|
||||
return part
|
||||
},
|
||||
}
|
|
@ -1,342 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const plugin_banner = {
|
||||
name: 'examples.plugin_banner',
|
||||
draft: ({ points, Point, paths, Path, macro, part }) => {
|
||||
points.from = new Point(0, 0)
|
||||
points.to = new Point(320, 0)
|
||||
|
||||
paths.banner = new Path().move(points.from).line(points.to)
|
||||
|
||||
macro('banner', {
|
||||
path: paths.banner,
|
||||
text: 'banner plugin',
|
||||
})
|
||||
|
||||
// Prevent clipping of text
|
||||
paths.box = new Path().move(new Point(0, -20)).line(new Point(0, 20)).attr('class', 'hidden')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_bartack = {
|
||||
name: 'examples.plugin_bartack',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.a = new Point(15, 15)
|
||||
|
||||
macro('bartack', {
|
||||
anchor: points.a,
|
||||
angle: 30,
|
||||
length: 15,
|
||||
})
|
||||
|
||||
return box(part, 60, 30)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_bartackalong = {
|
||||
name: 'examples.plugin_bartackalong',
|
||||
draft: ({ Point, Path, points, paths, macro, part }) => {
|
||||
points.a = new Point(15, 15)
|
||||
points.b = new Point(20, 20)
|
||||
points.c = new Point(30, 20)
|
||||
points.d = new Point(35, 15)
|
||||
points.e = new Point(20, 10)
|
||||
points.f = new Point(30, 10)
|
||||
|
||||
paths.a = new Path().move(points.a).curve(points.b, points.c, points.d).hide()
|
||||
|
||||
macro('bartackAlong', {
|
||||
path: paths.a,
|
||||
})
|
||||
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: ['e', 'f'],
|
||||
})
|
||||
|
||||
return box(part, 60, 30)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_bartackfractionalong = {
|
||||
name: 'examples.plugin_bartackfractionalong',
|
||||
draft: ({ Point, Path, points, paths, macro, part }) => {
|
||||
points.a = new Point(15, 15)
|
||||
points.b = new Point(20, 20)
|
||||
points.c = new Point(30, 20)
|
||||
points.d = new Point(35, 15)
|
||||
points.e = new Point(20, 10)
|
||||
points.f = new Point(30, 10)
|
||||
|
||||
paths.a = new Path().move(points.a).curve(points.b, points.c, points.d).hide()
|
||||
|
||||
macro('bartackFractionAlong', {
|
||||
path: paths.a,
|
||||
start: 0.2,
|
||||
end: 0.8,
|
||||
})
|
||||
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: ['e', 'f'],
|
||||
})
|
||||
|
||||
return box(part, 60, 30)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_buttons = {
|
||||
name: 'examples.plugin_buttons',
|
||||
draft: ({ Point, snippets, Snippet, part }) => {
|
||||
snippets.button = new Snippet('button', new Point(20, 10))
|
||||
snippets.buttonhole = new Snippet('buttonhole', new Point(40, 10))
|
||||
snippets.buttonholeStart = new Snippet('buttonhole-start', new Point(60, 10))
|
||||
snippets.buttonholeEnd = new Snippet('buttonhole-end', new Point(80, 10))
|
||||
snippets.snapMale = new Snippet('snap-stud', new Point(100, 10))
|
||||
snippets.snapFemale = new Snippet('snap-socket', new Point(120, 10))
|
||||
|
||||
return box(part, 140, 20)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_cutonfold = {
|
||||
name: 'examples.plugin_cutonfold',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.topLeft = new Point(0, 0)
|
||||
points.topRight = new Point(150, 0)
|
||||
points.bottomRight = new Point(150, 30)
|
||||
points.bottomLeft = new Point(0, 30)
|
||||
|
||||
paths.box = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.topRight)
|
||||
.line(points.bottomRight)
|
||||
.line(points.bottomLeft)
|
||||
.close()
|
||||
|
||||
macro('cutonfold', {
|
||||
from: points.bottomLeft,
|
||||
to: points.bottomRight,
|
||||
grainline: true,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_dimension = {
|
||||
name: 'examples.plugin_dimension',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.A = new Point(0, 0)
|
||||
points.B = new Point(0, 100)
|
||||
points.C = new Point(50, 100)
|
||||
points.D = new Point(100, 50)
|
||||
points.DCp1 = new Point(100, 0)
|
||||
|
||||
paths.box = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.line(points.C)
|
||||
.line(points.D)
|
||||
.curve(points.DCp1, points.A, points.A)
|
||||
.close()
|
||||
|
||||
macro('vd', {
|
||||
from: points.A,
|
||||
to: points.B,
|
||||
x: points.A.x - 15,
|
||||
})
|
||||
|
||||
macro('hd', {
|
||||
from: points.B,
|
||||
to: points.C,
|
||||
y: points.B.y + 15,
|
||||
})
|
||||
|
||||
macro('ld', {
|
||||
from: points.C,
|
||||
to: points.D,
|
||||
d: -15,
|
||||
})
|
||||
|
||||
macro('ld', {
|
||||
from: points.C,
|
||||
to: points.D,
|
||||
d: -30,
|
||||
text: 'Custom text',
|
||||
})
|
||||
|
||||
macro('pd', {
|
||||
path: new Path().move(points.A).curve(points.A, points.DCp1, points.D),
|
||||
d: -15,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_gore = {
|
||||
name: 'examples.plugin_gore',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchor = new Point(0, 0)
|
||||
|
||||
macro('gore', {
|
||||
from: points.anchor,
|
||||
radius: 60,
|
||||
gores: 5,
|
||||
extraLength: 20,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_grainline = {
|
||||
name: 'examples.plugin_grainline',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.grainlineFrom = new Point(10, 10)
|
||||
points.grainlineTo = new Point(100, 10)
|
||||
|
||||
macro('grainline', {
|
||||
from: points.grainlineFrom,
|
||||
to: points.grainlineTo,
|
||||
})
|
||||
|
||||
return box(part, 110, 15)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_logo = {
|
||||
name: 'examples.plugin_logo',
|
||||
draft: ({ points, Point, snippets, Snippet, part }) => {
|
||||
points.anchor = new Point(50, 25)
|
||||
|
||||
snippets.logo = new Snippet('logo', points.anchor).attr('data-scale', 0.666)
|
||||
|
||||
return box(part, 100, 35)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_mirror = {
|
||||
name: 'examples.plugin_mirror',
|
||||
draft: ({ Point, Path, points, paths, macro, part }) => {
|
||||
points.a = new Point(5, 5)
|
||||
points.b = new Point(45, 30)
|
||||
points.c = new Point(5, 30)
|
||||
points.d = new Point(45, 5)
|
||||
points.mid = new Point(25, 15)
|
||||
|
||||
paths.a = new Path().move(points.a).curve(points.b, points.c, points.d)
|
||||
|
||||
macro('mirror', {
|
||||
mirror: [points.b, points.d],
|
||||
points: [points.mid],
|
||||
paths: [paths.a],
|
||||
})
|
||||
|
||||
macro('sprinkle', {
|
||||
snippet: 'notch',
|
||||
on: ['mid', 'mirroredMid'],
|
||||
})
|
||||
|
||||
return box(part, 100, 40)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_notches = {
|
||||
name: 'examples.plugin_notches',
|
||||
draft: ({ Point, snippets, Snippet, part }) => {
|
||||
snippets.notch = new Snippet('notch', new Point(60, 10))
|
||||
snippets.bnotch = new Snippet('bnotch', new Point(80, 10))
|
||||
|
||||
return box(part, 140, 20)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_round = {
|
||||
name: 'examples.plugin_round',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.topLeft = new Point(0, 0)
|
||||
points.bottomLeft = new Point(0, 30)
|
||||
points.topRight = new Point(100, 0)
|
||||
points.bottomRight = new Point(100, 30)
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.topLeft)
|
||||
.line(points.bottomLeft)
|
||||
.line(points.bottomRight)
|
||||
.line(points.topRight)
|
||||
.close()
|
||||
.attr('class', 'note dashed')
|
||||
|
||||
macro('round', {
|
||||
from: points.topLeft,
|
||||
to: points.bottomRight,
|
||||
via: points.bottomLeft,
|
||||
radius: 10,
|
||||
prefix: 'bl',
|
||||
})
|
||||
macro('round', {
|
||||
from: points.bottomRight,
|
||||
to: points.topLeft,
|
||||
via: points.topRight,
|
||||
radius: 20,
|
||||
prefix: 'tr',
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_scalebox = {
|
||||
name: 'examples.plugin_scalebox',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchor1 = new Point(0, 0)
|
||||
points.anchor2 = new Point(70, 0)
|
||||
|
||||
macro('scalebox', { at: points.anchor1 })
|
||||
macro('miniscale', { at: points.anchor2 })
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_sprinkle = {
|
||||
name: 'examples.plugin_sprinkle',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.a = new Point(10, 10)
|
||||
points.b = new Point(20, 15)
|
||||
points.c = new Point(30, 10)
|
||||
points.d = new Point(40, 15)
|
||||
points.e = new Point(50, 10)
|
||||
points.f = new Point(60, 15)
|
||||
points.g = new Point(70, 10)
|
||||
points.h = new Point(80, 15)
|
||||
points.i = new Point(90, 10)
|
||||
|
||||
macro('sprinkle', {
|
||||
snippet: 'button',
|
||||
on: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
})
|
||||
|
||||
return box(part, 100, 25)
|
||||
},
|
||||
}
|
||||
|
||||
export const plugin_title = {
|
||||
name: 'examples.plugin_title',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.title = new Point(90, 45)
|
||||
|
||||
macro('title', {
|
||||
at: points.title,
|
||||
nr: 4,
|
||||
title: 'sleeve',
|
||||
prefix: 'test',
|
||||
})
|
||||
|
||||
return box(part, 200, 70)
|
||||
},
|
||||
}
|
|
@ -1,457 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const point_addcircle = {
|
||||
name: 'examples.point_addcircle',
|
||||
draft: ({ Point, points, part }) => {
|
||||
points.a = new Point(30, 10).addCircle(3, 'lining dashed').addCircle(7, 'mark dashed')
|
||||
|
||||
points.b = new Point(50, 10)
|
||||
.addCircle(1, 'interfacing')
|
||||
.addCircle(3, 'fabric')
|
||||
.addCircle(5, 'lining')
|
||||
.addCircle(7, 'mark')
|
||||
.addCircle(9, 'note')
|
||||
|
||||
points.c = new Point(70, 10).addCircle(3, 'interfacing').addCircle(7, 'mark lashed')
|
||||
return box(part, 100, 20)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_addtext = {
|
||||
name: 'examples.point_addtext',
|
||||
draft: ({ Point, points, part }) => {
|
||||
points.anchor = new Point(100, 25)
|
||||
.addText('supportFreesewingBecomeAPatron', 'center')
|
||||
.addText('please?')
|
||||
|
||||
return box(part, 200, 50)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_angle = {
|
||||
name: 'examples.point_angle',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.sun = new Point(10, 5)
|
||||
points.moon = points.sun.shift(-15, 70)
|
||||
points.text = points.sun
|
||||
.shiftFractionTowards(points.moon, 0.8)
|
||||
.attr('data-text', points.sun.angle(points.moon) + '°')
|
||||
.attr('data-text-class', 'text-sm fill-note center')
|
||||
|
||||
paths.line = new Path().move(points.sun).line(points.moon).attr('class', 'dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_attr = {
|
||||
name: 'examples.point_attr',
|
||||
draft: ({ Point, points, part }) => {
|
||||
points.anchor = new Point(100, 25)
|
||||
.attr('data-text', 'supportFreesewingBecomeAPatron')
|
||||
.attr('data-text-class', 'center')
|
||||
|
||||
return box(part, 200, 50)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_clone = {
|
||||
name: 'examples.point_clone',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.A = new Point(25, 25)
|
||||
.attr('data-text', 'Point A')
|
||||
.attr('data-text-class', 'text-xl')
|
||||
.attr('data-text-fill-opacity', '0.5')
|
||||
points.B = points.A.clone().attr('data-text', 'Point B')
|
||||
|
||||
snippets.x = new Snippet('notch', points.A)
|
||||
|
||||
return box(part)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_copy = {
|
||||
name: 'examples.point_copy',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.A = new Point(50, 25).attr('data-text', 'Point A').attr('data-text-class', 'text-xl')
|
||||
points.B = points.A.copy().attr('data-text', 'Point B')
|
||||
|
||||
snippets.x = new Snippet('notch', points.A)
|
||||
|
||||
return box(part)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_dist = {
|
||||
name: 'examples.point_dist',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(80, 70)
|
||||
|
||||
points.text = points.from
|
||||
.shiftFractionTowards(points.to, 0.6)
|
||||
.attr('data-text', points.from.dist(points.to) + 'mm')
|
||||
.attr('data-text-class', 'text-sm fill-note center')
|
||||
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_dx = {
|
||||
name: 'examples.point_dx',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(80, 70)
|
||||
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'dashed')
|
||||
|
||||
points.totop = points.from.shift(0, points.from.dx(points.to))
|
||||
|
||||
points.text_dx = points.from
|
||||
.shiftFractionTowards(points.totop, 0.6)
|
||||
.shiftFractionTowards(points.to, 0.1)
|
||||
.attr('data-text', points.from.dx(points.to) + 'mm')
|
||||
.attr('data-text-class', 'text-sm fill-note center')
|
||||
|
||||
paths.line_dx = new Path().move(points.from).line(points.totop).attr('class', 'dashed')
|
||||
|
||||
paths.line_dy = new Path().move(points.to).line(points.totop).attr('class', 'dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_dy = {
|
||||
name: 'examples.point_dy',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(80, 70)
|
||||
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'dashed')
|
||||
|
||||
points.totop = points.from.shift(0, points.from.dx(points.to))
|
||||
|
||||
paths.line_dx = new Path().move(points.from).line(points.totop).attr('class', 'dashed')
|
||||
|
||||
points.text_dy = points.totop
|
||||
.shiftFractionTowards(points.to, 0.4)
|
||||
.attr('data-text', points.from.dy(points.to) + 'mm')
|
||||
.attr('data-text-class', 'text-sm fill-note right')
|
||||
|
||||
paths.line_dy = new Path().move(points.to).line(points.totop).attr('class', 'dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_flipx = {
|
||||
name: 'examples.point_flipy',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.top = new Point(50, 10)
|
||||
points.out1 = new Point(70, 30)
|
||||
points.in1 = new Point(55, 35)
|
||||
points.out2 = new Point(75, 50)
|
||||
points.in2 = new Point(60, 55)
|
||||
points.out3 = new Point(80, 70)
|
||||
points.in3 = new Point(55, 70)
|
||||
points.trunkOut = new Point(55, 80)
|
||||
points.trunkIn = new Point(50, 80)
|
||||
|
||||
points._out1 = points.out1.flipX(points.top)
|
||||
points._in1 = points.in1.flipX(points.top)
|
||||
points._out2 = points.out2.flipX(points.top)
|
||||
points._in2 = points.in2.flipX(points.top)
|
||||
points._out3 = points.out3.flipX(points.top)
|
||||
points._in3 = points.in3.flipX(points.top)
|
||||
points._trunkOut = points.trunkOut.flipX(points.top)
|
||||
|
||||
points.bottom = new Point(50, 80)
|
||||
|
||||
paths.tree = new Path()
|
||||
.move(points.top)
|
||||
.line(points.out1)
|
||||
.line(points.in1)
|
||||
.line(points.out2)
|
||||
.line(points.in2)
|
||||
.line(points.out3)
|
||||
.line(points.in3)
|
||||
.line(points.trunkOut)
|
||||
.line(points._trunkOut)
|
||||
.line(points._in3)
|
||||
.line(points._out3)
|
||||
.line(points._in2)
|
||||
.line(points._out2)
|
||||
.line(points._in1)
|
||||
.line(points._out1)
|
||||
.close()
|
||||
|
||||
paths.mirror = new Path().move(points.top).line(points.bottom).attr('class', 'note dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_flipy = {
|
||||
name: 'examples.point_flipy',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.start = new Point(0, 50)
|
||||
points.churchTowerWallLeft = new Point(10, 50)
|
||||
points.churchTowerRoofLeft = new Point(10, 30)
|
||||
points.churchTowerTop = new Point(15, 10)
|
||||
points.churchTowerRoofRight = new Point(20, 30)
|
||||
points.churchRoofRight = new Point(50, 30)
|
||||
points.churchWallRight = new Point(50, 50)
|
||||
points.houseWallLeft = new Point(65, 50)
|
||||
points.houseRoofLeft = new Point(65, 35)
|
||||
points.houseRoofTop = new Point(75, 25)
|
||||
points.houseRoofRight = new Point(85, 35)
|
||||
points.houseWallRight = new Point(85, 50)
|
||||
points.end = new Point(95, 50)
|
||||
|
||||
points.mirror = new Point(0, 60)
|
||||
points.mirrorLineEnd = new Point(95, 60)
|
||||
|
||||
points._start = points.start.flipY(points.mirror)
|
||||
points._churchTowerWallLeft = points.churchTowerWallLeft.flipY(points.mirror)
|
||||
points._churchTowerRoofLeft = points.churchTowerRoofLeft.flipY(points.mirror)
|
||||
points._churchTowerTop = points.churchTowerTop.flipY(points.mirror)
|
||||
points._churchTowerRoofRight = points.churchTowerRoofRight.flipY(points.mirror)
|
||||
points._churchRoofRight = points.churchRoofRight.flipY(points.mirror)
|
||||
points._churchWallRight = points.churchWallRight.flipY(points.mirror)
|
||||
points._houseWallLeft = points.houseWallLeft.flipY(points.mirror)
|
||||
points._houseRoofLeft = points.houseRoofLeft.flipY(points.mirror)
|
||||
points._houseRoofTop = points.houseRoofTop.flipY(points.mirror)
|
||||
points._houseRoofRight = points.houseRoofRight.flipY(points.mirror)
|
||||
points._houseWallRight = points.houseWallRight.flipY(points.mirror)
|
||||
points._end = points.end.flipY(points.mirror)
|
||||
|
||||
paths.skylineTop = new Path()
|
||||
.move(points.start)
|
||||
.line(points.churchTowerWallLeft)
|
||||
.line(points.churchTowerRoofLeft)
|
||||
.line(points.churchTowerTop)
|
||||
.line(points.churchTowerRoofRight)
|
||||
.line(points.churchRoofRight)
|
||||
.line(points.churchWallRight)
|
||||
.line(points.houseWallLeft)
|
||||
.line(points.houseRoofLeft)
|
||||
.line(points.houseRoofTop)
|
||||
.line(points.houseRoofRight)
|
||||
.line(points.houseWallRight)
|
||||
.line(points.end)
|
||||
|
||||
paths.skylineBottom = new Path()
|
||||
.move(points._start)
|
||||
.line(points._churchTowerWallLeft)
|
||||
.line(points._churchTowerRoofLeft)
|
||||
.line(points._churchTowerTop)
|
||||
.line(points._churchTowerRoofRight)
|
||||
.line(points._churchRoofRight)
|
||||
.line(points._churchWallRight)
|
||||
.line(points._houseWallLeft)
|
||||
.line(points._houseRoofLeft)
|
||||
.line(points._houseRoofTop)
|
||||
.line(points._houseRoofRight)
|
||||
.line(points._houseWallRight)
|
||||
.line(points._end)
|
||||
|
||||
paths.mirrorLine = new Path()
|
||||
.move(points.mirror)
|
||||
.line(points.mirrorLineEnd)
|
||||
.attr('class', 'note dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_rotate = {
|
||||
name: 'examples.point_rotate',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.sun = new Point(40, 40)
|
||||
points.moon = new Point(70, 40)
|
||||
let step = 360 / 36
|
||||
for (let i = 1; i < 37; i++) {
|
||||
let angle = step * i
|
||||
points[`moon${i}`] = points.moon.rotate(angle, points.sun)
|
||||
paths[`moon${i}`] = new Path().move(points.sun).line(points[`moon${i}`])
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_setcircle = {
|
||||
name: 'examples.point_setcircle',
|
||||
draft: ({ Point, points, part }) => {
|
||||
points.a = new Point(30, 10).setCircle(3, 'lining dashed').setCircle(7, 'mark dashed')
|
||||
|
||||
points.b = new Point(50, 10)
|
||||
.setCircle(1, 'interfacing')
|
||||
.setCircle(3, 'fabric')
|
||||
.setCircle(5, 'lining')
|
||||
.setCircle(7, 'mark')
|
||||
.setCircle(9, 'note')
|
||||
|
||||
points.c = new Point(70, 10).setCircle(3, 'interfacing').setCircle(7, 'mark lashed')
|
||||
return box(part, 100, 20)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_settext = {
|
||||
name: 'examples.point_settext',
|
||||
draft: ({ Point, points, part }) => {
|
||||
points.anchor = new Point(100, 25)
|
||||
.setText('supportFreesewingBecomeAPatron', 'center')
|
||||
.setText('please?')
|
||||
|
||||
return box(part, 200, 50)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_shift = {
|
||||
name: 'examples.point_shift',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.A = new Point(90, 40).attr('data-text', 'Point A').attr('data-text-class', 'right')
|
||||
points.B = points.A.shift(155, 70)
|
||||
.attr('data-text', 'Point B is point A shifted 7cm\nat a 155 degree angle')
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
macro('ld', {
|
||||
from: points.B,
|
||||
to: points.A,
|
||||
d: -10,
|
||||
})
|
||||
|
||||
return box(part, 100, 45)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_shiftfractiontowards = {
|
||||
name: 'examples.point_shiftfractiontowards',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.A = new Point(90, 70).attr('data-text', 'Point A')
|
||||
points.B = new Point(10, 10).attr('data-text', 'Point B')
|
||||
points.C = points.A.shiftFractionTowards(points.B, 0.5)
|
||||
.attr('data-text', 'Point C is point A shifted 50%\nin the direction of point B')
|
||||
.attr('data-text-class', 'center')
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
paths.direction = new Path().move(points.A).line(points.B).attr('class', 'note dashed')
|
||||
|
||||
macro('ld', {
|
||||
from: points.C,
|
||||
to: points.A,
|
||||
d: -10,
|
||||
})
|
||||
|
||||
macro('ld', {
|
||||
from: points.B,
|
||||
to: points.A,
|
||||
d: 20,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_shiftoutwards = {
|
||||
name: 'examples.point_shiftoutwards',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.A = new Point(90, 70).attr('data-text', 'Point A')
|
||||
points.B = new Point(30, 30).attr('data-text', 'Point B')
|
||||
points.C = points.A.shiftOutwards(points.B, 30)
|
||||
.attr('data-text', 'Point C is point A shifted 3cm\nbeyond point B')
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
paths.direction = new Path().move(points.A).line(points.C).attr('class', 'note dashed')
|
||||
|
||||
macro('ld', {
|
||||
from: points.C,
|
||||
to: points.B,
|
||||
d: -10,
|
||||
})
|
||||
|
||||
return box(part, 110, 75)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_shifttowards = {
|
||||
name: 'examples.point_shifttowards',
|
||||
draft: ({ Point, points, Path, paths, macro, part }) => {
|
||||
points.A = new Point(90, 70).attr('data-text', 'Point A')
|
||||
points.B = new Point(10, 10).attr('data-text', 'Point B')
|
||||
points.C = points.A.shiftTowards(points.B, 35)
|
||||
.attr('data-text', 'Point C is point A shifted 3.5cm\nin the direction of point B')
|
||||
.attr('data-text-class', 'center')
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
paths.direction = new Path().move(points.A).line(points.B).attr('class', 'note dashed')
|
||||
|
||||
macro('ld', {
|
||||
from: points.C,
|
||||
to: points.A,
|
||||
d: -10,
|
||||
})
|
||||
|
||||
return box(part, 110, 80)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_sitson = {
|
||||
name: 'examples.point_sitson',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
let s
|
||||
for (let i = 0; i < 10; i++) {
|
||||
points[`a${i}`] = new Point(i * 10, 40)
|
||||
points[`b${i}`] = new Point(i * 10, i * 8)
|
||||
if (points[`a${i}`].sitsOn(points[`b${i}`])) s = 'notch'
|
||||
else s = 'bnotch'
|
||||
snippets[`b${i}`] = new Snippet(s, points[`b${i}`])
|
||||
snippets[`a${i}`] = new Snippet(s, points[`a${i}`])
|
||||
}
|
||||
|
||||
return box(part)
|
||||
},
|
||||
}
|
||||
|
||||
export const point_sitsroughlyon = {
|
||||
name: 'examples.point_sitsroughlyon',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
box(part)
|
||||
|
||||
let s
|
||||
for (let i = 0; i < 10; i++) {
|
||||
points[`a${i}`] = new Point(i * 10, 40)
|
||||
points[`b${i}`] = new Point(i * 10, i * 8)
|
||||
if (points[`a${i}`].sitsRoughlyOn(points[`b${i}`])) s = 'notch'
|
||||
else s = 'bnotch'
|
||||
snippets[`b${i}`] = new Snippet(s, points[`b${i}`])
|
||||
snippets[`a${i}`] = new Snippet(s, points[`a${i}`])
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const point_translate = {
|
||||
name: 'examples.point_translate',
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.A = new Point(20, 20).attr('data-text', 'Point A')
|
||||
points.B = points.A.translate(120, 60)
|
||||
.attr('data-text', 'Point B is point A with a\ntranslate(120, 60)\ntransform applied')
|
||||
.attr('data-text-class', 'right')
|
||||
.attr('data-text-dy', -6)
|
||||
.attr('data-text-lineheight', 6)
|
||||
|
||||
macro('ld', {
|
||||
from: points.A,
|
||||
to: points.B,
|
||||
text: 'translate(120,60)',
|
||||
noStartMarker: true,
|
||||
})
|
||||
|
||||
return box(part, 150, 85)
|
||||
},
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
export const settings_sa = {
|
||||
name: 'examples.settings_sa',
|
||||
draft: ({ Point, points, Path, paths, part }) => {
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.line(points.A)
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
paths.offset = paths.example.offset(-10).attr('class', 'fabric sa')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* This draws a (diagonal in a) box
|
||||
* with with w and height h with a non-visible line.
|
||||
* This is to force our examples parts to a certain size
|
||||
*/
|
||||
export function box(part, w = 100, h = 50) {
|
||||
part.paths.box = new part.Path()
|
||||
.move(new part.Point(0, 0))
|
||||
.line(new part.Point(w, h))
|
||||
.setClass('hidden noxray')
|
||||
|
||||
return part
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const snippet = {
|
||||
name: 'examples.snippet',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor1 = new Point(20, 15)
|
||||
points.anchor2 = new Point(50, 15)
|
||||
points.anchor3 = new Point(80, 15)
|
||||
snippets.demo1 = new Snippet('button', points.anchor1)
|
||||
snippets.demo2 = new Snippet('buttonhole', points.anchor2)
|
||||
snippets.demo3 = new Snippet('logo', points.anchor3).attr('data-scale', 0.5)
|
||||
|
||||
return box(part)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_attr = {
|
||||
name: 'examples.snippet_attr',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 15)
|
||||
snippets.demo = new Snippet('logo', points.anchor)
|
||||
.attr('data-scale', 0.8)
|
||||
.attr('data-rotate', 180)
|
||||
|
||||
return box(part)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_clone = {
|
||||
name: 'examples.snippet_clone',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(35, 35)
|
||||
snippets.demo = new Snippet('logo', points.anchor).attr('style', 'color: #f006')
|
||||
|
||||
snippets.clone = snippets.demo.clone().attr('data-scale', 0.5)
|
||||
|
||||
return box(part)
|
||||
},
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const snippet_bnotch = {
|
||||
name: 'examples.snippet_bnotch',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 5)
|
||||
snippets.demo = new Snippet('bnotch', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_button = {
|
||||
name: 'examples.snippet_button',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 5)
|
||||
snippets.demo = new Snippet('button', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_buttonholeend = {
|
||||
name: 'examples.snippet_buttonholeend',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 0)
|
||||
snippets.demo = new Snippet('buttonhole-end', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_buttonholestart = {
|
||||
name: 'examples.snippet_buttonholestart',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 10)
|
||||
snippets.demo = new Snippet('buttonhole-start', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_buttonhole = {
|
||||
name: 'examples.snippet_buttonhole',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 5)
|
||||
snippets.demo = new Snippet('buttonhole', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_logo = {
|
||||
name: 'examples.snippet_logo',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 35)
|
||||
snippets.demo = new Snippet('logo', points.anchor)
|
||||
|
||||
return box(part, 100, 50)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_notch = {
|
||||
name: 'examples.snippet_notch',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 5)
|
||||
snippets.demo = new Snippet('notch', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_snapsocket = {
|
||||
name: 'examples.snippet_snapsocket',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 5)
|
||||
snippets.demo = new Snippet('snap-socket', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
||||
|
||||
export const snippet_snapstud = {
|
||||
name: 'examples.snippet_snapstud',
|
||||
draft: ({ Point, points, Snippet, snippets, part }) => {
|
||||
points.anchor = new Point(50, 5)
|
||||
snippets.demo = new Snippet('snap-stud', points.anchor)
|
||||
|
||||
return box(part, 100, 10)
|
||||
},
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
const stack = (settings, partName) => {
|
||||
if (settings?.options?.stackIt === 'Do stack') return 'example'
|
||||
else return partName
|
||||
}
|
||||
|
||||
export const stacks_top = {
|
||||
name: 'examples.stacks_top',
|
||||
stack,
|
||||
measurements: ['head'],
|
||||
options: {
|
||||
size: { pct: 50, min: 5, max: 100, menu: 'stack' },
|
||||
x: { pct: 0, min: -100, max: 100, menu: 'stack' },
|
||||
y: { pct: 0, min: -100, max: 100, menu: 'stack' },
|
||||
stackIt: { dflt: 'Do stack', list: ['Do stack', 'Do not stack'], menu: 'stack' },
|
||||
},
|
||||
draft: ({ store, Point, points, Path, paths, options, measurements, part }) => {
|
||||
store.set('size', measurements.head * options.size)
|
||||
store.set('x', measurements.head * options.x)
|
||||
store.set('y', measurements.head * options.y)
|
||||
points.from = new Point(store.get('x'), store.get('y'))
|
||||
points.to = points.from.shift(0, store.get('size'))
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const stacks_right = {
|
||||
name: 'examples.stacks_right',
|
||||
stack,
|
||||
after: stacks_top,
|
||||
draft: ({ store, Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(store.get('x') + store.get('size'), store.get('y'))
|
||||
points.to = points.from.shift(-90, store.get('size'))
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const stacks_bottom = {
|
||||
name: 'examples.stacks_bottom',
|
||||
stack,
|
||||
after: stacks_top,
|
||||
draft: ({ store, Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(store.get('x') + store.get('size'), store.get('y') + store.get('size'))
|
||||
points.to = points.from.shift(180, store.get('size'))
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const stacks_left = {
|
||||
name: 'examples.stacks_left',
|
||||
stack,
|
||||
after: stacks_top,
|
||||
draft: ({ store, Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(store.get('x'), store.get('y') + store.get('size'))
|
||||
points.to = points.from.shift(90, store.get('size'))
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const stacks_leftEye = {
|
||||
name: 'examples.stacks_leftEye',
|
||||
stack,
|
||||
after: stacks_top,
|
||||
draft: ({ store, Point, points, part }) => {
|
||||
points.leftEye = new Point(
|
||||
store.get('x') + store.get('size') * 0.35,
|
||||
store.get('y') + store.get('size') * 0.4
|
||||
)
|
||||
.attr('data-circle', store.get('size') * 0.1)
|
||||
.attr('data-circle-class', 'stroke-6xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const stacks_rightEye = {
|
||||
name: 'examples.stacks_rightEye',
|
||||
stack,
|
||||
after: stacks_top,
|
||||
draft: ({ store, Point, points, part }) => {
|
||||
points.rightEye = new Point(
|
||||
store.get('x') + store.get('size') * 0.65,
|
||||
store.get('y') + store.get('size') * 0.4
|
||||
)
|
||||
.attr('data-circle', store.get('size') * 0.08)
|
||||
.attr('data-circle-class', 'stroke-7xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const stacks_mouth = {
|
||||
name: 'examples.stacks_mouth',
|
||||
stack,
|
||||
after: stacks_top,
|
||||
draft: ({ store, Point, points, paths, Path, part }) => {
|
||||
points.left = new Point(
|
||||
store.get('x') + store.get('size') * 0.15,
|
||||
store.get('y') + store.get('size') * 0.5
|
||||
)
|
||||
points.right = new Point(
|
||||
store.get('x') + store.get('size') * 0.85,
|
||||
store.get('y') + store.get('size') * 0.5
|
||||
)
|
||||
points.leftCp = new Point(
|
||||
store.get('x') + store.get('size') * 0.35,
|
||||
store.get('y') + store.get('size') * 0.8
|
||||
)
|
||||
points.rightCp = new Point(
|
||||
store.get('x') + store.get('size') * 0.65,
|
||||
store.get('y') + store.get('size') * 0.8
|
||||
)
|
||||
|
||||
paths.mouth = new Path()
|
||||
.move(points.left)
|
||||
.curve(points.leftCp, points.rightCp, points.right)
|
||||
.attr('class', 'fabric stroke-7xl')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
|
@ -1,445 +0,0 @@
|
|||
import { box } from './shared.mjs'
|
||||
|
||||
export const utils_beamintersectscircle = {
|
||||
name: 'examples.utils_beamintersectscircle',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
|
||||
points.A = new Point(95, 45).attr('data-circle', 35).attr('data-circle-class', '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)
|
||||
|
||||
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 box(part, 200, 80)
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_beamintersectsx = {
|
||||
name: 'examples.utils_beamintersectsx',
|
||||
draft: ({ 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))
|
||||
.attr('class', 'note dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_beamintersectsy = {
|
||||
name: 'examples.utils_beamintersectsy',
|
||||
draft: ({ 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
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_beamsintersect = {
|
||||
name: 'examples.utils_beamsintersect',
|
||||
draft: ({ 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
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_circlesintersect = {
|
||||
name: 'examples.utils_circlesintersect',
|
||||
draft: ({ Point, points, Snippet, snippets, utils, part }) => {
|
||||
points.A = new Point(10, 10).attr('data-circle', 15).attr('data-circle-class', 'fabric')
|
||||
points.B = new Point(30, 30).attr('data-circle', 35).attr('data-circle-class', 'fabric')
|
||||
points.C = new Point(90, 10).attr('data-circle', 15).attr('data-circle-class', 'various')
|
||||
points.D = new Point(110, 30).attr('data-circle', 35).attr('data-circle-class', 'various')
|
||||
|
||||
let intersections1 = utils.circlesIntersect(
|
||||
points.A,
|
||||
points.A.attributes.get('data-circle'),
|
||||
points.B,
|
||||
points.B.attributes.get('data-circle')
|
||||
)
|
||||
let 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
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_curveintersectsx = {
|
||||
name: 'examples.utils_curveintersectsx',
|
||||
draft: ({ Point, points, Path, paths, utils, snippets, Snippet, 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])
|
||||
.attr('class', '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
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_curveintersectsy = {
|
||||
name: 'examples.utils_curveintersectsy',
|
||||
draft: ({ Point, points, Path, paths, utils, snippets, Snippet, 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])
|
||||
.attr('class', '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
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_curvesintersect = {
|
||||
name: 'examples.utils_curvesintersect',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, 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.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)
|
||||
|
||||
for (let p of utils.curvesIntersect(
|
||||
points.A,
|
||||
points.Acp,
|
||||
points.Bcp,
|
||||
points.B,
|
||||
points.C,
|
||||
points.Ccp,
|
||||
points.Dcp,
|
||||
points.D
|
||||
)) {
|
||||
snippets[part.getId()] = new Snippet('notch', p)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_lineintersectscircle = {
|
||||
name: 'examples.utils_lineintersectscircle',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
|
||||
points.A = new Point(95, 45).attr('data-circle', 35).attr('data-circle-class', '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)
|
||||
|
||||
let intersections1 = utils.lineIntersectsCircle(
|
||||
points.A,
|
||||
points.A.attributes.get('data-circle'),
|
||||
points.B,
|
||||
points.C
|
||||
)
|
||||
let intersections2 = utils.lineIntersectsCircle(
|
||||
points.A,
|
||||
points.A.attributes.get('data-circle'),
|
||||
points.D,
|
||||
points.E,
|
||||
'y'
|
||||
)
|
||||
let 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 box(part, 200, 80)
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_lineintersectscurve = {
|
||||
name: 'examples.utils_lineintersectscurve',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, 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[part.getId()] = new Snippet('notch', p)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_linesintersect = {
|
||||
name: 'examples.utils_linesintersect',
|
||||
draft: ({ 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
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_pointonbeam = {
|
||||
name: 'examples.utils_pointonbeam',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, 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)
|
||||
|
||||
let 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[part.getId()] = new Snippet(snippet, point)
|
||||
if (utils.pointOnBeam(points.from2, points.to2, point, 0.01)) {
|
||||
snippet = 'notch'
|
||||
} else snippet = 'bnotch'
|
||||
snippets[part.getId()] = new Snippet(snippet, point)
|
||||
}
|
||||
paths.line1 = new Path().move(points.from1).line(points.to1).attr('class', 'fabric stroke-lg')
|
||||
paths.lne1 = new Path().move(points.to1).line(points.b1).attr('class', 'fabric dashed')
|
||||
paths.line2 = new Path().move(points.from2).line(points.to2).attr('class', 'fabric stroke-lg')
|
||||
paths.lne2 = new Path().move(points.to2).line(points.b2).attr('class', 'fabric dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_pointoncurve = {
|
||||
name: 'examples.utils_pointoncurve',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, 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)
|
||||
|
||||
let 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[part.getId()] = new Snippet(snippet, point)
|
||||
}
|
||||
paths.curve = new Path()
|
||||
.move(points.start)
|
||||
.curve(points.cp1, points.cp2, points.end)
|
||||
.attr('class', 'fabric stroke-lg')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_pointonline = {
|
||||
name: 'examples.utils_pointonline',
|
||||
draft: ({ Point, points, Path, paths, Snippet, snippets, 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)
|
||||
|
||||
let 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[part.getId()] = new Snippet(snippet, point)
|
||||
if (utils.pointOnLine(points.from2, points.to2, point, 0.01)) {
|
||||
snippet = 'notch'
|
||||
} else snippet = 'bnotch'
|
||||
snippets[part.getId()] = new Snippet(snippet, point)
|
||||
}
|
||||
paths.line1 = new Path().move(points.from1).line(points.to1).attr('class', 'fabric stroke-lg')
|
||||
paths.lne1 = new Path().move(points.to1).line(points.b1).attr('class', 'fabric dashed')
|
||||
paths.line2 = new Path().move(points.from2).line(points.to2).attr('class', 'fabric stroke-lg')
|
||||
paths.lne2 = new Path().move(points.to2).line(points.b2).attr('class', 'fabric dashed')
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
||||
|
||||
export const utils_splitcurve = {
|
||||
name: 'examples.utils_splitcurve',
|
||||
draft: ({ Point, points, Path, paths, utils, part }) => {
|
||||
points.from = new Point(40, 10)
|
||||
points.to = new Point(40, 80)
|
||||
paths.line = new Path().move(points.from).line(points.to).attr('class', 'lining dashed')
|
||||
|
||||
points.start = new Point(10, 15)
|
||||
points.cp1 = new Point(80, 10)
|
||||
points.cp2 = new Point(-50, 80)
|
||||
points.end = new Point(110, 70)
|
||||
|
||||
points.i40 = utils.curveIntersectsX(points.start, points.cp1, points.cp2, points.end, 40)
|
||||
|
||||
let parts = utils.splitCurve(points.start, points.cp1, points.cp2, points.end, points.i40)
|
||||
|
||||
let colors = ['lining', 'interfacing']
|
||||
for (let p of parts) {
|
||||
let color = colors.pop()
|
||||
paths[color] = new Path()
|
||||
.move(p.start)
|
||||
.curve(p.cp1, p.cp2, p.end)
|
||||
.attr('class', 'stroke-xl ' + color)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
|
@ -409,7 +409,6 @@ function draftHiBody({
|
|||
.curve(points.body02cp1, points.body03cp2, points.body03)
|
||||
.join(paths.allButDart)
|
||||
.close()
|
||||
.hide()
|
||||
|
||||
let gillPath = new Path()
|
||||
.move(points.body17)
|
||||
|
|
|
@ -89,9 +89,7 @@ function hugoFront({
|
|||
.line(points.raglanTipFront)
|
||||
.join(neckOpeningParts[0].reverse())
|
||||
paths.saBase.hide()
|
||||
paths.seam = paths.saBase.clone().close().attr('class', 'fabric')
|
||||
// FIXME: This pocket path is not getting set on the paths object
|
||||
// It's something to do with the paths proxy which -- I assume -- is proxying the wrong object?
|
||||
paths.seam = paths.saBase.clone().unhide().close().attr('class', 'fabric')
|
||||
paths.pocket = new Path()
|
||||
.move(points.pocketHem)
|
||||
.line(points.pocketTip)
|
||||
|
|
|
@ -101,6 +101,6 @@ function hugoPocket({
|
|||
export const pocket = {
|
||||
name: 'hugo.pocket',
|
||||
from: front,
|
||||
hideDependencies: true,
|
||||
// hideDependencies: true,
|
||||
draft: hugoPocket,
|
||||
}
|
||||
|
|
|
@ -47,6 +47,5 @@ function hugoPocketFacing({ sa, points, Path, paths, complete, paperless, macro,
|
|||
export const pocketFacing = {
|
||||
name: 'hugo.pocketFacing',
|
||||
from: pocket,
|
||||
hideDependencies: true,
|
||||
draft: hugoPocketFacing,
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ function lunetiusLacerna({
|
|||
.line(points.bottom)
|
||||
.hide()
|
||||
paths.saBase = new Path().move(points.top).line(points.topLeft).hide()
|
||||
paths.seam = paths.saBase.join(paths.hem).join(paths.fold).attr('class', 'fabric').hide()
|
||||
paths.seam = paths.saBase.join(paths.hem).join(paths.fold).attr('class', 'fabric')
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
|
|
|
@ -17,7 +17,7 @@ const pluginRound = ({ Point, points, Path, paths, macro, options, part }) => {
|
|||
.attr('class', 'note dashed')
|
||||
|
||||
const opts = {
|
||||
radius: options.roundRadius,
|
||||
radius: Number(options.roundRadius),
|
||||
hide: options.roundHide,
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ const pluginScalebox = ({ Point, points, macro, options, part }) => {
|
|||
|
||||
macro(options.scaleboxType, {
|
||||
at: points.a,
|
||||
rotate: options.scaleboxRotation,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -19,6 +20,7 @@ export const scalebox = {
|
|||
after: base,
|
||||
options: {
|
||||
scaleboxType: { dflt: 'scalebox', list: ['scalebox', 'miniscale'], menu: 'scalebox' },
|
||||
scaleboxRotation: { deg: 0, min: 0, max: 360, menu: 'scalebox' },
|
||||
},
|
||||
draft: pluginScalebox,
|
||||
}
|
||||
|
|
|
@ -39,8 +39,7 @@ function teaganBack({
|
|||
.join(paths.saBase)
|
||||
.line(points.cfHem)
|
||||
.close()
|
||||
.hide()
|
||||
.attr('class', 'fabric')
|
||||
.setClass('fabric')
|
||||
|
||||
// Set store values required to draft sleevecap
|
||||
store.set('sleevecapEase', 0)
|
||||
|
|
18
designs/unice/.eslintrc.yml
Normal file
18
designs/unice/.eslintrc.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
env:
|
||||
browser: true
|
||||
es2021: true
|
||||
extends: eslint:recommended
|
||||
overrides:
|
||||
- files: ["*.yaml", "*.yml"]
|
||||
plugins: ["yaml"]
|
||||
extends: ["plugin:yaml/recommended"]
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
rules: {}
|
||||
globals:
|
||||
it: readonly
|
||||
describe: readonly
|
||||
process: readonly
|
||||
__dirname: readonly
|
||||
|
15
designs/unice/CHANGELOG.md
Normal file
15
designs/unice/CHANGELOG.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Change log for: @freesewing/unice
|
||||
|
||||
|
||||
## 2.21.0 (2022-06-27)
|
||||
|
||||
### Added
|
||||
|
||||
- Unice is an underwear pattern
|
||||
|
||||
|
||||
This is the **initial release**, and the start of this change log.
|
||||
|
||||
> Prior to version 2, FreeSewing was not a JavaScript project.
|
||||
> As such, that history is out of scope for this change log.
|
||||
|
|
@ -1,13 +1,13 @@
|
|||

|
||||
<p align='center'><a
|
||||
href="https://www.npmjs.com/package/@freesewing/examples"
|
||||
title="@freesewing/examples on NPM"
|
||||
><img src="https://img.shields.io/npm/v/@freesewing/examples.svg"
|
||||
alt="@freesewing/examples on NPM"/>
|
||||
href="https://www.npmjs.com/package/@freesewing/unice"
|
||||
title="@freesewing/unice on NPM"
|
||||
><img src="https://img.shields.io/npm/v/@freesewing/unice.svg"
|
||||
alt="@freesewing/unice on NPM"/>
|
||||
</a><a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img src="https://img.shields.io/npm/l/@freesewing/examples.svg?label=License"
|
||||
><img src="https://img.shields.io/npm/l/@freesewing/unice.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a><a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
|
@ -15,10 +15,10 @@
|
|||
><img src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="Code quality on DeepScan"/>
|
||||
</a><a
|
||||
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Aexamples"
|
||||
title="Open issues tagged pkg:examples"
|
||||
><img src="https://img.shields.io/github/issues/freesewing/freesewing/pkg:examples.svg?label=Issues"
|
||||
alt="Open issues tagged pkg:examples"/>
|
||||
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Aunice"
|
||||
title="Open issues tagged pkg:unice"
|
||||
><img src="https://img.shields.io/github/issues/freesewing/freesewing/pkg:unice.svg?label=Issues"
|
||||
alt="Open issues tagged pkg:unice"/>
|
||||
</a><a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
|
@ -46,9 +46,9 @@
|
|||
alt="Follow @freesewing_org on Twitter"/>
|
||||
</a></p>
|
||||
|
||||
# @freesewing/examples
|
||||
# @freesewing/unice
|
||||
|
||||
A FreeSewing pattern holding examples for our documentation
|
||||
A FreeSewing pattern for a basic, highly-customizable underwear pattern
|
||||
|
||||
|
||||
|
||||
|
@ -63,7 +63,7 @@ A FreeSewing pattern holding examples for our documentation
|
|||
|
||||
This repository is our *monorepo* holding all our NPM designs, plugins, other NPM packages, and (web)sites.
|
||||
|
||||
This folder holds: @freesewing/examples
|
||||
This folder holds: @freesewing/unice
|
||||
|
||||
If you're not entirely sure what to do or how to start, type this command:
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// This file is auto-generated | All changes you make will be overwritten.
|
||||
export const name = "@freesewing/examples"
|
||||
export const name = "@freesewing/unice"
|
||||
export const version = "3.0.0-alpha.0"
|
||||
export const data = { name, version }
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "@freesewing/examples",
|
||||
"name": "@freesewing/unice",
|
||||
"version": "3.0.0-alpha.0",
|
||||
"description": "A FreeSewing pattern holding examples for our documentation",
|
||||
"author": "Joost De Cock <joost@joost.at> (https://github.com/joostdecock)",
|
||||
"description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
|
||||
"author": "Anna Puk (https://github.com/anna-puk)",
|
||||
"homepage": "https://freesewing.org/",
|
||||
"repository": "github:freesewing/freesewing",
|
||||
"license": "MIT",
|
||||
|
@ -15,9 +15,14 @@
|
|||
},
|
||||
"keywords": [
|
||||
"freesewing",
|
||||
"documentation",
|
||||
"example",
|
||||
"parametric design"
|
||||
"design",
|
||||
"diy",
|
||||
"fashion",
|
||||
"made to measure",
|
||||
"parametric design",
|
||||
"pattern",
|
||||
"sewing",
|
||||
"sewing pattern"
|
||||
],
|
||||
"type": "module",
|
||||
"module": "dist/index.mjs",
|
||||
|
@ -41,9 +46,7 @@
|
|||
"peerDependencies": {
|
||||
"@freesewing/core": "^3.0.0-alpha.0",
|
||||
"@freesewing/plugin-bundle": "^3.0.0-alpha.0",
|
||||
"@freesewing/config-helpers": "^3.0.0-alpha.0",
|
||||
"@freesewing/plugin-mirror": "^3.0.0-alpha.0",
|
||||
"@freesewing/plugin-gore": "^3.0.0-alpha.0"
|
||||
"@freesewing/config-helpers": "^3.0.0-alpha.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
308
designs/unice/src/back.mjs
Normal file
308
designs/unice/src/back.mjs
Normal file
|
@ -0,0 +1,308 @@
|
|||
import { front } from './front.mjs'
|
||||
|
||||
export const back = {
|
||||
name: 'unice.back',
|
||||
measurements: ['waist', 'seat', 'waistToSeat', 'waistToUpperLeg', 'hips', 'waistToHips'],
|
||||
optionalMeasurements: ['crossSeam', 'crossSeamFront'],
|
||||
options: {
|
||||
backToFrontLength: 1.15, // Maybe include this in advanced options?
|
||||
backToFrontWidth: 1.1, // Maybe include this in advanced options?
|
||||
gussetRatio: 0.7, // Relationship between front and back gusset widths
|
||||
backDip: { pct: 2.5, min: -5, max: 15, menu: 'style' },
|
||||
backExposure: { pct: 20, min: -30, max: 90, menu: 'style' },
|
||||
},
|
||||
after: front,
|
||||
draft: ({
|
||||
utils,
|
||||
store,
|
||||
sa,
|
||||
Point,
|
||||
points,
|
||||
Path,
|
||||
paths,
|
||||
options,
|
||||
measurements,
|
||||
complete,
|
||||
paperless,
|
||||
macro,
|
||||
part,
|
||||
}) => {
|
||||
// Design pattern here
|
||||
|
||||
// Create points
|
||||
points.backWaistMid = new Point(measurements.seat / 4, 0)
|
||||
points.backWaistBandLeft = new Point(
|
||||
store.get('sideSeamWaist').x / options.backToFrontWidth,
|
||||
store.get('sideSeamWaist').y
|
||||
)
|
||||
points.backLegOpeningLeft = new Point(
|
||||
store.get('sideSeamHip').x / options.backToFrontWidth,
|
||||
store.get('sideSeamHip').y
|
||||
)
|
||||
|
||||
// back height is given by (estimated) cross seam, minus front and gusset lengths
|
||||
// this does not account for vertical stretch yet
|
||||
const backHeight =
|
||||
store.get('crossSeam') - store.get('frontHeight') - options.gussetLength * measurements.seat
|
||||
|
||||
// calculate the actual back height, using yScale above and yScaleReduced below leg opening
|
||||
const backHeightAbove = store.get('frontHeightAbove') // part above has same height front and back
|
||||
|
||||
let backHeightBelow
|
||||
backHeightBelow =
|
||||
store.get('yScale') * (backHeight - backHeightAbove / store.get('yScaleReduced'))
|
||||
|
||||
const backHeightReduced = backHeightBelow + backHeightAbove
|
||||
|
||||
points.backGussetLeft = new Point(
|
||||
measurements.seat / 4 -
|
||||
((measurements.waist * options.gussetWidth * store.get('xScale')) / options.gussetRatio) *
|
||||
options.backToFrontWidth,
|
||||
backHeightReduced
|
||||
)
|
||||
points.backGussetMid = new Point(measurements.seat / 4, backHeightReduced)
|
||||
|
||||
points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid)
|
||||
points.backLegOpeningRight = points.backLegOpeningLeft.flipX(points.backWaistMid)
|
||||
points.backWaistBandRight = points.backWaistBandLeft.flipX(points.backWaistMid)
|
||||
|
||||
points.backWaistBandMid = points.backWaistBandLeft
|
||||
.shiftFractionTowards(points.backWaistBandRight, 0.5)
|
||||
.shift(270, measurements.waistToUpperLeg * options.backDip)
|
||||
|
||||
/* Middle point for label */
|
||||
points.backMidMid = points.backLegOpeningLeft.shiftFractionTowards(
|
||||
points.backLegOpeningRight,
|
||||
0.5
|
||||
)
|
||||
|
||||
// Create control points
|
||||
|
||||
/* Control point for waistband dip */
|
||||
points.backWaistBandLeftCp1 = points.backWaistBandMid.shift(
|
||||
0,
|
||||
points.backWaistBandMid.dx(points.backWaistBandLeft) / 3
|
||||
)
|
||||
|
||||
/* Flip points to right side */
|
||||
points.backWaistBandRightCp1 = points.backWaistBandLeftCp1.flipX(points.backWaistMid)
|
||||
|
||||
// Shape back coverage
|
||||
|
||||
/* Only have to do this on one side */
|
||||
points.backLegOpeningCorner = utils.beamsIntersect(
|
||||
points.backLegOpeningLeft,
|
||||
points.backLegOpeningLeft.shift(180, points.backGussetLeft.dy(points.backLegOpeningLeft)),
|
||||
points.backGussetLeft,
|
||||
points.backGussetLeft.shift(270, points.backGussetLeft.dy(points.backLegOpeningLeft))
|
||||
)
|
||||
|
||||
if (options.backExposure >= 0) {
|
||||
/* If back exposure is high, like a thong style */
|
||||
/* This controls the hip bit */
|
||||
points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shiftFractionTowards(
|
||||
points.backLegOpeningCorner,
|
||||
options.backExposure
|
||||
)
|
||||
/* This controls the center bit */
|
||||
points.backGussetLeftCp1 = points.backGussetLeft.shiftFractionTowards(
|
||||
points.backWaistBandMid,
|
||||
options.backExposure
|
||||
)
|
||||
points.backGussetLeft = points.backGussetLeft.shiftFractionTowards(
|
||||
points.backGussetMid,
|
||||
options.backExposure
|
||||
) // This narrows the back of the gusset
|
||||
points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid)
|
||||
} else {
|
||||
/* If back exposure is low and flares out to cover more */
|
||||
store.set('adjustedBackExposure', options.backExposure * store.get('adjustedLegOpening')) // flare depends on leg opening
|
||||
/* This controls the hip bit */
|
||||
points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shift(
|
||||
-45,
|
||||
store.get('adjustedBackExposure') * points.backWaistBandMid.dx(points.backWaistBandLeft)
|
||||
)
|
||||
/* This controls the taper to gusset */
|
||||
points.backGussetLeftCp1 = points.backGussetLeft.shift(
|
||||
115,
|
||||
store.get('adjustedBackExposure') * points.backWaistBandMid.dx(points.backWaistBandLeft)
|
||||
)
|
||||
|
||||
/* center of the flare and its control points are on a line parallel to the backGussetLeft to backLegOpeningLeft line
|
||||
* first, define the points on that line */
|
||||
points.backFlare = points.backGussetLeft.shiftFractionTowards(points.backLegOpeningLeft, 0.5)
|
||||
// points.backFlareCp1 = points.backGussetLeft.shiftFractionTowards(points.backLegOpeningLeft, 0.5 - store.get('adjustedBackExposure'))
|
||||
points.backFlareCp1 = points.backGussetLeft.shiftFractionTowards(
|
||||
points.backLegOpeningLeft,
|
||||
0.7
|
||||
)
|
||||
points.backFlareCp2 = points.backGussetLeft.shiftFractionTowards(
|
||||
points.backLegOpeningLeft,
|
||||
0.3
|
||||
)
|
||||
/* then shift all three points outward */
|
||||
points.backFlareLeft = points.backFlare.shift(
|
||||
215,
|
||||
points.backWaistBandMid.dx(points.backWaistBandLeft) * store.get('adjustedBackExposure') * 2
|
||||
)
|
||||
points.backFlareLeftCp1 = points.backFlareCp1.shift(
|
||||
215,
|
||||
points.backWaistBandMid.dx(points.backWaistBandLeft) * store.get('adjustedBackExposure') * 2
|
||||
)
|
||||
points.backFlareLeftCp2 = points.backFlareCp2.shift(
|
||||
215,
|
||||
points.backWaistBandMid.dx(points.backWaistBandLeft) * store.get('adjustedBackExposure') * 2
|
||||
)
|
||||
|
||||
/* Flip points to the right */
|
||||
|
||||
points.backFlareRight = points.backFlareLeft.flipX(points.backWaistBandMid)
|
||||
points.backFlareRightCp1 = points.backFlareLeftCp1.flipX(points.backWaistMid)
|
||||
points.backFlareRightCp2 = points.backFlareLeftCp2.flipX(points.backWaistMid)
|
||||
}
|
||||
|
||||
/* Flip points to the right */
|
||||
|
||||
points.backLegOpeningRightCp1 = points.backLegOpeningLeftCp1.flipX(points.backWaistMid)
|
||||
points.backGussetRightCp1 = points.backGussetLeftCp1.flipX(points.backWaistMid)
|
||||
|
||||
// Draw paths
|
||||
|
||||
if (options.backExposure >= 0) {
|
||||
paths.seam = new Path()
|
||||
.move(points.backWaistBandMid)
|
||||
.curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip
|
||||
.line(points.backLegOpeningLeft)
|
||||
.curve(points.backLegOpeningLeftCp1, points.backGussetLeftCp1, points.backGussetLeft)
|
||||
.line(points.backGussetMid)
|
||||
.line(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
|
||||
.line(points.backWaistBandRight)
|
||||
.curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
} else {
|
||||
paths.seam = new Path()
|
||||
.move(points.backWaistBandMid)
|
||||
.curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip
|
||||
.line(points.backLegOpeningLeft)
|
||||
.curve(points.backLegOpeningLeftCp1, points.backFlareLeftCp1, points.backFlareLeft)
|
||||
.curve(points.backFlareLeftCp2, points.backGussetLeftCp1, points.backGussetLeft)
|
||||
.line(points.backGussetMid)
|
||||
.line(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
|
||||
.curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
|
||||
.line(points.backWaistBandRight)
|
||||
.curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
}
|
||||
|
||||
// Store points for use in other parts
|
||||
|
||||
/* Store gusset points for use in gusset */
|
||||
|
||||
store.set('backGussetLeft', points.backGussetLeft)
|
||||
store.set('backGussetRight', points.backGussetRight)
|
||||
|
||||
/* Store lengths for use in elastic */
|
||||
|
||||
paths.backLegOpening =
|
||||
options.backExposure >= 0
|
||||
? new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(
|
||||
points.backGussetRightCp1,
|
||||
points.backLegOpeningRightCp1,
|
||||
points.backLegOpeningRight
|
||||
)
|
||||
.setHidden(true)
|
||||
: new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
|
||||
.curve(
|
||||
points.backFlareRightCp1,
|
||||
points.backLegOpeningRightCp1,
|
||||
points.backLegOpeningRight
|
||||
)
|
||||
.setHidden(true)
|
||||
store.set('backLegOpeningLength', paths.backLegOpening.length())
|
||||
|
||||
paths.backWaistBand = new Path()
|
||||
.move(points.backWaistBandRight)
|
||||
.curve(points.backWaistBandRightCp1, points.backWaistBandLeftCp1, points.backWaistBandLeft)
|
||||
.setHidden(true)
|
||||
store.set('backWaistBandLength', paths.backWaistBand.length())
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
if (sa) {
|
||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
}
|
||||
}
|
||||
|
||||
macro('title', {
|
||||
at: points.backMidMid,
|
||||
nr: 2,
|
||||
title: 'back',
|
||||
})
|
||||
|
||||
macro('grainline', {
|
||||
from: points.backGussetMid,
|
||||
to: points.backGussetMid.shiftFractionTowards(points.backWaistBandMid, 0.4),
|
||||
})
|
||||
|
||||
points.scaleboxAnchor = points.scalebox = points.backMidMid.shift(90, -50)
|
||||
macro('miniscale', { at: points.scalebox })
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.backWaistBandRight,
|
||||
to: points.backWaistBandLeft,
|
||||
y: points.backWaistBandRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.backLegOpeningRight,
|
||||
to: points.backLegOpeningLeft,
|
||||
y: points.backLegOpeningRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.backGussetLeft,
|
||||
to: points.backGussetRight,
|
||||
y: points.backGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.backWaistBandMid,
|
||||
to: points.backGussetMid,
|
||||
x: points.backWaistBandMid.x + sa + 15,
|
||||
})
|
||||
if (options.backExposure >= 0) {
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(
|
||||
points.backGussetRightCp1,
|
||||
points.backLegOpeningRightCp1,
|
||||
points.backLegOpeningRight
|
||||
),
|
||||
d: 15,
|
||||
})
|
||||
} else {
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
|
||||
.curve(
|
||||
points.backFlareRightCp1,
|
||||
points.backLegOpeningRightCp1,
|
||||
points.backLegOpeningRight
|
||||
),
|
||||
d: 15,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
39
designs/unice/src/elastic.mjs
Normal file
39
designs/unice/src/elastic.mjs
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { gusset } from './gusset.mjs'
|
||||
|
||||
export const elastic = {
|
||||
name: 'unice.elastic',
|
||||
options: {
|
||||
elasticStretch: { pct: 8, min: 5, max: 15, menu: 'fit' },
|
||||
},
|
||||
after: gusset,
|
||||
draft: ({ options, Point, points, Path, paths, store, utils, units, sa, part }) => {
|
||||
// Stretch utility method
|
||||
store.set('elasticScale', utils.stretchToScale(options.elasticStretch))
|
||||
|
||||
// Design pattern here
|
||||
const legOpeningLength =
|
||||
store.get('frontLegOpeningLength') +
|
||||
store.get('backLegOpeningLength') +
|
||||
store.get('gussetSideLength')
|
||||
const waistBandLength = store.get('frontWaistBandLength') + store.get('backWaistBandLength')
|
||||
|
||||
points.elasticInfo = new Point(0, 0)
|
||||
.attr('data-text', 'cutTwoPiecesOfElasticToFinishTheLegOpenings')
|
||||
.attr('data-text', ':')
|
||||
.attr('data-text', units(legOpeningLength * store.get('elasticScale') + 2 * sa))
|
||||
.attr('data-text', '\n')
|
||||
.attr('data-text', 'cutOnePieceOfElasticToFinishTheWaistBand')
|
||||
.attr('data-text', ':')
|
||||
.attr('data-text', units(waistBandLength * store.get('elasticScale') + 2 * sa))
|
||||
|
||||
// Draw a box around the text, so the part shows up correctly.
|
||||
paths.box = new Path()
|
||||
.move(new Point(-10, -10))
|
||||
.line(new Point(-10, 15))
|
||||
.line(new Point(200, 15))
|
||||
.line(new Point(200, -10))
|
||||
.close()
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
340
designs/unice/src/front.mjs
Normal file
340
designs/unice/src/front.mjs
Normal file
|
@ -0,0 +1,340 @@
|
|||
import { pluginBundle } from '@freesewing/plugin-bundle'
|
||||
|
||||
export const front = {
|
||||
name: 'unice.front',
|
||||
measurements: ['waist', 'seat', 'waistToSeat', 'waistToUpperLeg', 'hips', 'waistToHips'],
|
||||
optionalMeasurements: ['crossSeam', 'crossSeamFront'],
|
||||
options: {
|
||||
gussetShift: 0.015, // fraction of seat circumference - could be an advanced option?
|
||||
gussetWidth: { pct: 7.2, min: 2, max: 12, menu: 'fit' }, // Gusset width in relation to waist-to-upperleg
|
||||
gussetLength: { pct: 12.7, min: 10, max: 16, menu: 'fit' }, // Gusset length in relation to seat
|
||||
fabricStretchX: { pct: 15, min: 0, max: 100, menu: 'fit' }, // horizontal stretch (range set wide for beta testing)
|
||||
fabricStretchY: { pct: 0, min: 0, max: 100, menu: 'fit' }, // vertical stretch (range set wide for beta testing)
|
||||
rise: { pct: 60, min: 30, max: 100, menu: 'style' }, // extending rise beyond 100% would require adapting paths.sideLeft!
|
||||
legOpening: { pct: 45, min: 5, max: 85, menu: 'style' },
|
||||
frontDip: { pct: 5.0, min: -5, max: 15, menu: 'style' },
|
||||
taperToGusset: { pct: 70, min: 5, max: 100, menu: 'style' },
|
||||
// booleans
|
||||
useCrossSeam: { bool: true, menu: 'fit' },
|
||||
adjustStretch: { bool: true, menu: 'fit' }, // to not stretch fabric to the limits
|
||||
},
|
||||
plugins: [pluginBundle],
|
||||
draft: ({
|
||||
utils,
|
||||
store,
|
||||
sa,
|
||||
Point,
|
||||
points,
|
||||
Path,
|
||||
paths,
|
||||
options,
|
||||
measurements,
|
||||
complete,
|
||||
paperless,
|
||||
macro,
|
||||
part,
|
||||
}) => {
|
||||
// Stretch utility method
|
||||
|
||||
// Use stretch inputs to calculate four different scale factors: horizontal/vertical and 'regular'/'reduced', depending on direction of the tension
|
||||
// xScale: for parts that go across the body (= stretched horizontally)
|
||||
// xScaleReduced: parts that are not under (horizontal) tension, e.g. the gusset
|
||||
// yScale: for parts which are stretched vertically but not horizontally (anything below leg opening)
|
||||
// yScaleReduced: parts which are already under horizontal stretch, which limits vertical stretch
|
||||
|
||||
if (options.adjustStretch) {
|
||||
// roughly 15% of stretch is reserved for comfort
|
||||
// horizontal: first, 'regular' stretch (for parts that go across the body)
|
||||
if (options.fabricStretchX < 0.30) {
|
||||
// subtract 15, but never go below 0
|
||||
store.set('xScale', utils.stretchToScale(Math.max(0, options.fabricStretchX - 0.15)))
|
||||
} else {
|
||||
store.set('xScale', utils.stretchToScale(options.fabricStretchX / 2))
|
||||
// rough approximation of rule of thumb quoted in Sanne's July 29, 2021 showcase
|
||||
}
|
||||
// use half of whatever the regular stretch is (no util available, convert from stretch to fraction manually
|
||||
store.set('xScaleReduced', (1 + store.get('xScale')) / 2)
|
||||
|
||||
// vertical:
|
||||
if (options.fabricStretchY < 0.30) {
|
||||
// subtract 15, but never go below 0
|
||||
store.set('yScale', utils.stretchToScale(Math.max(0, options.fabricStretchY - 0.15)))
|
||||
} else {
|
||||
store.set('yScale', utils.stretchToScale(options.fabricStretchY / 2))
|
||||
// rough approximation of rule of thumb quoted in Sanne's July 29, 2021 showcase
|
||||
}
|
||||
// reduced vertical stretch calculated below, same as for non-adjusted case
|
||||
} else {
|
||||
// in order: regular, then reduced horizontal stretch, followed by regular vertical stretch
|
||||
store.set('xScale', utils.stretchToScale(options.fabricStretchX))
|
||||
store.set('xScaleReduced', utils.stretchToScale(options.fabricStretchX / 2))
|
||||
store.set('yScale', utils.stretchToScale(options.fabricStretchY))
|
||||
}
|
||||
if (options.fabricStretchY < 0.20) {
|
||||
store.set('yScaleReduced', 1)
|
||||
} else {
|
||||
// reduced yScale gradually increases from equivalent of stretch 0 to 5%, then cuts off (uses third-order polynomial)
|
||||
// function to approximate Sanne's guidelines given in Discord (roughly 2.5% for stretch 30-40%, 5% above that)
|
||||
store.set(
|
||||
'yScaleReduced',
|
||||
utils.stretchToScale(Math.min(0.05, 6.25 * Math.pow(options.fabricStretchY - 0.2, 3)))
|
||||
)
|
||||
}
|
||||
|
||||
// // temporarily overrule yScale and yScaleReduced
|
||||
// store.set('yScale',1)
|
||||
// store.set('yScaleReduced',1)
|
||||
|
||||
// // Part definition starts here
|
||||
|
||||
// determine height of front part: use cross seam (and cross seam front) if selected and available
|
||||
// NOTE: neither crossSeam not frontHeight are adjusted for (vertical) stretch
|
||||
if (options.useCrossSeam && measurements.crossSeam) {
|
||||
store.set('crossSeam', measurements.crossSeam)
|
||||
} else {
|
||||
// use original approximation: front and back are roughly waistToUpperLeg high, plus gusset length
|
||||
store.set(
|
||||
'crossSeam',
|
||||
measurements.waistToUpperLeg * (1 + options.backToFrontLength) +
|
||||
options.gussetLength * measurements.seat
|
||||
)
|
||||
}
|
||||
// optionally use crossSeamFront to determine relative length of front and back
|
||||
// this does not account for vertical stretch yet
|
||||
if (options.useCrossSeam && measurements.crossSeamFront) {
|
||||
// subtract half the gusset length from cross seam front, and an additional 3.5% of the seat circumference to move the gusset upward (to match commercial panties)
|
||||
store.set(
|
||||
'frontHeight',
|
||||
measurements.crossSeamFront -
|
||||
measurements.seat * (0.5 * options.gussetLength + options.gussetShift)
|
||||
)
|
||||
} else {
|
||||
// subtract gusset length, divide by roughly 2
|
||||
store.set(
|
||||
'frontHeight',
|
||||
(store.get('crossSeam') - options.gussetLength * measurements.seat) /
|
||||
(1 + options.backToFrontLength)
|
||||
)
|
||||
}
|
||||
|
||||
// Create points
|
||||
|
||||
// side seam is on a line from upper leg to seat to hips (optional?) to waist
|
||||
points.frontWaistMid = new Point(measurements.seat / 4, 0)
|
||||
points.frontWaistLeft = new Point(
|
||||
measurements.seat / 4 - (measurements.waist / 4) * store.get('xScale'),
|
||||
0
|
||||
)
|
||||
points.frontSeatLeft = new Point(
|
||||
measurements.seat / 4 - (measurements.seat / 4) * store.get('xScale'),
|
||||
measurements.waistToSeat * store.get('yScaleReduced')
|
||||
)
|
||||
points.frontUpperLegLeft = new Point(
|
||||
measurements.seat / 4 - (measurements.seat / 4) * store.get('xScale'), // assume same circ. as seat
|
||||
measurements.waistToUpperLeg * store.get('yScaleReduced')
|
||||
)
|
||||
points.frontHipLeft = new Point(
|
||||
measurements.seat / 4 - (measurements.hips / 4) * store.get('xScale'),
|
||||
measurements.waistToHips * store.get('yScaleReduced')
|
||||
)
|
||||
|
||||
// use these points to define an invisible path
|
||||
paths.sideLeft = new Path()
|
||||
.move(points.frontUpperLegLeft)
|
||||
.line(points.frontSeatLeft)
|
||||
.line(points.frontHipLeft)
|
||||
.line(points.frontWaistLeft)
|
||||
.setHidden(true) // only show when debugging
|
||||
|
||||
/* Waist band is somewhere on the sideLeft path */
|
||||
points.frontWaistBandLeft = paths.sideLeft.shiftFractionAlong(options.rise)
|
||||
points.frontWaistBandRight = points.frontWaistBandLeft.flipX(points.frontWaistMid)
|
||||
points.frontWaistBandMid = points.frontWaistBandLeft
|
||||
.shiftFractionTowards(points.frontWaistBandRight, 0.5)
|
||||
.shift(270, measurements.waistToUpperLeg * options.frontDip) /* Waist band dip */
|
||||
|
||||
/* Leg opening is also on the sideLeft path, and cannot be higher than rise */
|
||||
/* Minimum side seam length is defined as 3.5% of the sideLeft path (which is at least waistToUpperLeg long) */
|
||||
store.set('adjustedLegOpening', Math.min(options.legOpening, options.rise - 0.035)) // TODO: account for rise having a different domain
|
||||
|
||||
points.frontLegOpeningLeft = paths.sideLeft.shiftFractionAlong(store.get('adjustedLegOpening'))
|
||||
points.frontLegOpeningRight = points.frontLegOpeningLeft.flipX(points.frontWaistMid) // Waist band low point
|
||||
|
||||
// calculate the actual front height, using yScale above and yScaleReduced below leg opening
|
||||
store.set('frontHeightAbove', points.frontWaistLeft.dy(points.frontLegOpeningLeft))
|
||||
|
||||
var frontHeightBelow
|
||||
frontHeightBelow =
|
||||
store.get('yScale') *
|
||||
(store.get('frontHeight') - store.get('frontHeightAbove') / store.get('yScaleReduced'))
|
||||
|
||||
var frontHeightReduced
|
||||
frontHeightReduced = frontHeightBelow + store.get('frontHeightAbove')
|
||||
|
||||
// gusset width uses modified xScale (barely stretches) and depends on waistToUpperLeg - least sensitive to girth
|
||||
points.frontGussetLeft = new Point(
|
||||
measurements.seat / 4 -
|
||||
measurements.waistToSeat * options.gussetWidth * store.get('xScaleReduced') * 2.2,
|
||||
frontHeightReduced
|
||||
)
|
||||
points.frontGussetMid = new Point(measurements.seat / 4, frontHeightReduced)
|
||||
|
||||
/* Flip points to right side */
|
||||
points.frontGussetRight = points.frontGussetLeft.flipX(points.frontWaistMid)
|
||||
points.frontHipRight = points.frontSeatLeft.flipX(points.frontWaistMid)
|
||||
points.frontWaistRight = points.frontWaistLeft.flipX(points.frontWaistMid)
|
||||
|
||||
console.log('points', points)
|
||||
|
||||
/* Middle point for label */
|
||||
points.frontMidMid = points.frontLegOpeningLeft.shiftFractionTowards(
|
||||
points.frontLegOpeningRight,
|
||||
0.5
|
||||
)
|
||||
|
||||
// Create control points
|
||||
|
||||
/* Control points for leg opening curves */
|
||||
points.frontLegOpeningLeftCp1 = points.frontLegOpeningLeft.shift(
|
||||
180,
|
||||
points.frontGussetLeft.dy(points.frontLegOpeningLeft) / 3
|
||||
)
|
||||
|
||||
/* Control point above gusset moves higher as taperToGusset (= front exposure) increases, but is limited by both the leg opening (allow minimal arching only) and the rise (leg opening must not intersect the waist band) */
|
||||
points.frontGussetLeftCp1 = points.frontGussetLeft.shift(
|
||||
270,
|
||||
Math.max(
|
||||
Math.max(
|
||||
(points.frontGussetLeft.dy(points.frontWaistMid) * options.taperToGusset) / 2,
|
||||
points.frontGussetLeft.dy(points.frontLegOpeningLeft) * 2
|
||||
),
|
||||
points.frontGussetLeft.dy(points.frontWaistBandMid)
|
||||
)
|
||||
)
|
||||
|
||||
/* Control point for waistband dip */
|
||||
points.frontWaistBandLeftCp1 = points.frontWaistBandMid.shift(
|
||||
0,
|
||||
points.frontWaistBandMid.dx(points.frontWaistBandLeft) / 3
|
||||
)
|
||||
|
||||
/* Flip control points to right side */
|
||||
points.frontGussetRightCp1 = points.frontGussetLeftCp1.flipX(points.frontWaistMid)
|
||||
points.frontLegOpeningRightCp1 = points.frontLegOpeningLeftCp1.flipX(points.frontWaistMid)
|
||||
points.frontWaistBandRightCp1 = points.frontWaistBandLeftCp1.flipX(points.frontWaistMid)
|
||||
|
||||
// Draw paths
|
||||
|
||||
paths.seam = new Path()
|
||||
.move(points.frontWaistBandMid)
|
||||
.curve(points.frontWaistBandLeftCp1, points.frontWaistBandLeft, points.frontWaistBandLeft) // Waist band dip
|
||||
.line(points.frontLegOpeningLeft)
|
||||
.curve(points.frontLegOpeningLeftCp1, points.frontGussetLeftCp1, points.frontGussetLeft)
|
||||
.line(points.frontGussetMid)
|
||||
.line(points.frontGussetRight)
|
||||
.curve(
|
||||
points.frontGussetRightCp1,
|
||||
points.frontLegOpeningRightCp1,
|
||||
points.frontLegOpeningRight
|
||||
)
|
||||
.line(points.frontWaistBandRight)
|
||||
.curve(points.frontWaistBandRight, points.frontWaistBandRightCp1, points.frontWaistBandMid) // Waist band dip
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
// Store points for use in other parts
|
||||
|
||||
/* Store side seam points for use in back */
|
||||
|
||||
store.set('sideSeamWaist', points.frontWaistBandLeft)
|
||||
store.set('sideSeamHip', points.frontLegOpeningLeft)
|
||||
|
||||
/* Store gusset points for use in gusset */
|
||||
|
||||
store.set('frontGussetLeft', points.frontGussetLeft)
|
||||
store.set('frontGussetRight', points.frontGussetRight)
|
||||
store.set('frontGussetMid', points.frontGussetMid)
|
||||
|
||||
/* Store lengths for use in elastic */
|
||||
|
||||
paths.frontLegOpening = new Path()
|
||||
.move(points.frontGussetRight)
|
||||
.curve(
|
||||
points.frontGussetRightCp1,
|
||||
points.frontLegOpeningRightCp1,
|
||||
points.frontLegOpeningRight
|
||||
)
|
||||
.setHidden(true)
|
||||
store.set('frontLegOpeningLength', paths.frontLegOpening.length())
|
||||
|
||||
paths.frontWaistBand = new Path()
|
||||
.move(points.frontWaistBandRight)
|
||||
.curve(points.frontWaistBandRightCp1, points.frontWaistBandLeftCp1, points.frontWaistBandLeft)
|
||||
.setHidden(true)
|
||||
store.set('frontWaistBandLength', paths.frontWaistBand.length())
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
if (sa) {
|
||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
}
|
||||
}
|
||||
|
||||
macro('title', {
|
||||
at: points.frontMidMid,
|
||||
nr: 1,
|
||||
title: 'front',
|
||||
})
|
||||
|
||||
macro('grainline', {
|
||||
from: points.frontGussetMid,
|
||||
to: points.frontGussetMid.shiftFractionTowards(points.frontWaistBandMid, 0.5),
|
||||
})
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.frontWaistBandRight,
|
||||
to: points.frontWaistBandLeft,
|
||||
y: points.frontWaistBandRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.frontLegOpeningRight,
|
||||
to: points.frontLegOpeningLeft,
|
||||
y: points.frontLegOpeningRight.y + sa - 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.frontGussetLeft,
|
||||
to: points.frontGussetRight,
|
||||
y: points.frontGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.frontWaistBandMid,
|
||||
to: points.frontGussetMid,
|
||||
x: points.frontWaistBandMid.x + sa + 15,
|
||||
})
|
||||
macro('ld', {
|
||||
from: points.frontWaistBandLeft,
|
||||
to: points.frontLegOpeningLeft,
|
||||
d: points.frontWaistBandLeft.y + sa - 15,
|
||||
})
|
||||
macro('pd', {
|
||||
path: new Path()
|
||||
.move(points.frontGussetRight)
|
||||
.curve(
|
||||
points.frontGussetRightCp1,
|
||||
points.frontLegOpeningRightCp1,
|
||||
points.frontLegOpeningRight
|
||||
),
|
||||
d: 15,
|
||||
})
|
||||
/* macro('vd', {
|
||||
from: points.frontWaistBandLeft,
|
||||
to: points.frontWaistBandMid,
|
||||
x: points.frontWaistBandMid.x + sa + 15,
|
||||
}) */
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
113
designs/unice/src/gusset.mjs
Normal file
113
designs/unice/src/gusset.mjs
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { back } from './back.mjs'
|
||||
|
||||
export const gusset = {
|
||||
name: 'unice.gusset',
|
||||
measurements: ['waist', 'seat', 'waistToSeat', 'waistToUpperLeg', 'hips', 'waistToHips'],
|
||||
optionalMeasurements: ['crossSeam', 'crossSeamFront'],
|
||||
options: {
|
||||
gussetShift: 0.015, // fraction of seat circumference - could be an advanced option?
|
||||
gussetWidth: { pct: 7.2, min: 2, max: 12, menu: 'fit' }, // Gusset width in relation to waist-to-upperleg
|
||||
gussetLength: { pct: 12.7, min: 10, max: 16, menu: 'fit' }, // Gusset length in relation to seat
|
||||
fabricStretch: { pct: 15, min: 0, max: 100, menu: 'fit' }, // used in Ursula
|
||||
fabricStretchX: { pct: 15, min: 0, max: 100, menu: 'fit' }, // horizontal stretch (range set wide for beta testing)
|
||||
fabricStretchY: { pct: 0, min: 0, max: 100, menu: 'fit' }, // vertical stretch (range set wide for beta testing)
|
||||
rise: { pct: 60, min: 30, max: 100, menu: 'style' }, // extending rise beyond 100% would require adapting paths.sideLeft!
|
||||
legOpening: { pct: 45, min: 5, max: 85, menu: 'style' },
|
||||
frontDip: { pct: 5.0, min: -5, max: 15, menu: 'style' },
|
||||
taperToGusset: { pct: 70, min: 5, max: 100, menu: 'style' },
|
||||
// booleans
|
||||
useCrossSeam: { bool: true, menu: 'fit' },
|
||||
},
|
||||
after: back,
|
||||
draft: ({
|
||||
store,
|
||||
sa,
|
||||
Point,
|
||||
points,
|
||||
Path,
|
||||
paths,
|
||||
options,
|
||||
measurements,
|
||||
complete,
|
||||
paperless,
|
||||
macro,
|
||||
part,
|
||||
}) => {
|
||||
// Design pattern here
|
||||
var yScaleDoubleLayer
|
||||
yScaleDoubleLayer = (1 + store.get('yScale')) / 2 // double layer of fabric stretches half as much
|
||||
|
||||
// Create points
|
||||
points.frontGussetLeft = new Point(store.get('frontGussetLeft').x, 0)
|
||||
points.backGussetLeft = new Point(
|
||||
store.get('backGussetLeft').x,
|
||||
measurements.seat * options.gussetLength * yScaleDoubleLayer
|
||||
)
|
||||
points.frontGussetRight = new Point(store.get('frontGussetRight').x, 0)
|
||||
points.backGussetRight = new Point(
|
||||
store.get('backGussetRight').x,
|
||||
measurements.seat * options.gussetLength * yScaleDoubleLayer
|
||||
)
|
||||
|
||||
// Create control points
|
||||
points.gussetCp1 = points.frontGussetLeft
|
||||
.shiftFractionTowards(points.backGussetLeft, 0.5)
|
||||
.shift(180, points.frontGussetRight.x / -15)
|
||||
|
||||
// Flip points to right side
|
||||
points.gussetCp2 = points.gussetCp1.flipX(store.get('frontGussetMid'))
|
||||
|
||||
// Create point for title
|
||||
points.frontMidMid = points.gussetCp1.shiftFractionTowards(points.gussetCp2, 0.5)
|
||||
|
||||
/* Store lengths for use in elastic */
|
||||
paths.gussetLegOpening = new Path()
|
||||
.move(points.backGussetRight)
|
||||
.curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight)
|
||||
.setHidden(true)
|
||||
store.set('gussetSideLength', paths.gussetLegOpening.length())
|
||||
|
||||
// Draw paths
|
||||
paths.seam = new Path()
|
||||
.move(points.frontGussetLeft)
|
||||
.curve(points.gussetCp1, points.backGussetLeft, points.backGussetLeft)
|
||||
.line(points.backGussetRight)
|
||||
.curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight)
|
||||
.line(points.frontGussetLeft) // Without this, doesn't generate seam allowance
|
||||
.close()
|
||||
.attr('class', 'fabric')
|
||||
|
||||
// Complete?
|
||||
if (complete) {
|
||||
if (sa) {
|
||||
paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
|
||||
}
|
||||
macro('title', {
|
||||
at: points.frontMidMid,
|
||||
nr: 3,
|
||||
title: 'gusset',
|
||||
})
|
||||
}
|
||||
|
||||
// Paperless?
|
||||
if (paperless) {
|
||||
macro('hd', {
|
||||
from: points.frontGussetLeft,
|
||||
to: points.frontGussetRight,
|
||||
y: points.frontGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('hd', {
|
||||
from: points.backGussetLeft,
|
||||
to: points.backGussetRight,
|
||||
y: points.backGussetLeft.y + sa + 15,
|
||||
})
|
||||
macro('vd', {
|
||||
from: points.frontGussetRight,
|
||||
to: points.backGussetRight,
|
||||
x: points.frontGussetRight.x + sa + 15,
|
||||
})
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
}
|
15
designs/unice/src/index.mjs
Normal file
15
designs/unice/src/index.mjs
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Design } from '@freesewing/core'
|
||||
import { front } from './front.mjs'
|
||||
import { back } from './back.mjs'
|
||||
import { gusset } from './gusset.mjs'
|
||||
import { elastic } from './elastic.mjs'
|
||||
import { data } from '../data.mjs'
|
||||
|
||||
// Setup our new design
|
||||
const Unice = new Design({
|
||||
data,
|
||||
parts: [front, back, gusset, elastic],
|
||||
})
|
||||
|
||||
// Named exports
|
||||
export { front, back, gusset, elastic, Unice }
|
|
@ -1,5 +1,5 @@
|
|||
// This file is auto-generated | Any changes you make will be overwritten.
|
||||
import { Examples } from '../src/index.mjs'
|
||||
import { Unice } from '../src/index.mjs'
|
||||
|
||||
// Shared tests
|
||||
import { testPatternConfig } from '../../../tests/designs/config.mjs'
|
||||
|
@ -7,10 +7,10 @@ import { testPatternDrafting } from '../../../tests/designs/drafting.mjs'
|
|||
//import { testPatternSampling } from '../../../tests/designs/sampling.mjs'
|
||||
|
||||
// Test config
|
||||
testPatternConfig(Examples)
|
||||
testPatternConfig(Unice)
|
||||
|
||||
// Test drafting - Change the second parameter to `true` to log errors
|
||||
testPatternDrafting(Examples, false)
|
||||
testPatternDrafting(Unice, false)
|
||||
|
||||
// Test sampling - Change the second parameter to `true` to log errors
|
||||
//testPatternSampling(Examples, false)
|
||||
//testPatternSampling(Unice, false)
|
|
@ -3,14 +3,21 @@ title: Design
|
|||
order: 10
|
||||
---
|
||||
|
||||
The `Design` named export in FreeSewing's core library serves a single purpose:
|
||||
To create new pattern designs.
|
||||
The `Design` named export in FreeSewing's core library is a contructor that
|
||||
creates new pattern designs.
|
||||
|
||||
## Design constructor
|
||||
## Signature
|
||||
|
||||
```js
|
||||
import { Design } from "@freesewing/core"
|
||||
Pattern Design({
|
||||
array parts,
|
||||
object data
|
||||
})
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
const Sorcha = new Design({
|
||||
// design configuration here
|
||||
})
|
||||
|
@ -21,9 +28,8 @@ It takes a single argument, an object holding the design's configuration.
|
|||
|
||||
## Design configuration
|
||||
|
||||
|
||||
Since a design's configuration is managed at the part level,
|
||||
the Design constructor only expects a `parts` attribute that should
|
||||
the Design configuration object only requires a `parts` property that should
|
||||
hold an array of parts to include in the Design.
|
||||
|
||||
```js
|
||||
|
@ -44,14 +50,29 @@ to [the Store](/reference/api/store).
|
|||
const Sorcha = new Design({
|
||||
parts: [ front, back, sleeve ],
|
||||
data: {
|
||||
// Your custom data here
|
||||
version: 3,
|
||||
price: 12,
|
||||
currency: 'euro'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
<Tip>
|
||||
## Notes
|
||||
|
||||
This Design constructor is a _super-constructor_.
|
||||
|
||||
The Design constructor is a _super-constructor_.
|
||||
It will return a constructor method that will a pattern based on your design.
|
||||
|
||||
</Tip>
|
||||
## Properties
|
||||
|
||||
In addition to the returned constructor method, an instantiated Design object
|
||||
also provides the following properties:
|
||||
|
||||
### Design.designConfig
|
||||
|
||||
This holds the design configuration as passed to the Design constructor.
|
||||
|
||||
### Design.patternConfig
|
||||
|
||||
Holds the resolved pattern configuration based on the configuration passed to the Design constructor.
|
||||
|
||||
|
|
|
@ -17,24 +17,24 @@ Path path._curve(Point cp2, Point to)
|
|||
|
||||
## Example
|
||||
|
||||
<TabbedExample part="path__curve" caption="Example of the Path.\_curve() method">
|
||||
<Example caption="Example of the Path.\_curve() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.from = new Point(5, 20);
|
||||
points.cp2 = new Point(60, 30);
|
||||
points.cp2 = new Point(60, 50);
|
||||
points.to = new Point(90, 20);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
._curve(points.cp2, points.to)
|
||||
.attr("data-text", "Path._curve()")
|
||||
.attr("data-text-class", "text-sm center fill-note");
|
||||
.setText("Path._curve()", "text-sm center fill-note")
|
||||
.attr("data-text-dy", -1)
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</TabbedExample>
|
||||
</Example>
|
||||
|
||||
|
||||
## Notes
|
||||
|
|
|
@ -4,31 +4,17 @@ title: Path.addClass()
|
|||
|
||||
The `Path.addClass()` method adds a CSS class to the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.addClass(string className)
|
||||
```
|
||||
|
||||
<Tip | compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Tip>
|
||||
|
||||
###### This method exists to save you some typing
|
||||
|
||||
Note that the two following calls yield the same result:
|
||||
|
||||
```js
|
||||
path.attr('class', 'fabric')
|
||||
path.addClass('fabric')
|
||||
```
|
||||
|
||||
So the only purpose of this method is to save your some typing.
|
||||
|
||||
</Tip>
|
||||
|
||||
<Example part="path_addclass">
|
||||
Example of the Path.addClass() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.addClass() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
|
@ -43,3 +29,15 @@ Example of the Path.addClass() method
|
|||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
## Notes
|
||||
|
||||
The main purpose of this method is to save your some typing,
|
||||
as the two following calls yield the same result:
|
||||
|
||||
```js
|
||||
path.attr('class', 'fabric')
|
||||
path.addClass('fabric')
|
||||
```
|
||||
|
||||
|
|
47
markdown/dev/reference/api/path/addtext/en.md
Normal file
47
markdown/dev/reference/api/path/addtext/en.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: Path.addText()
|
||||
---
|
||||
|
||||
The `Path.addText()` method adds text to the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.addText(string text, string className)
|
||||
```
|
||||
|
||||
The second argument will optionally be used to set the CSS class for the text.
|
||||
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.addText() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(5, 10)
|
||||
points.to = new Point(95, 10)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.addText('FreeSewing rocks')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
## Notes
|
||||
|
||||
The main purpose of this method is to save your some typing,
|
||||
as the two following calls yield the same result:
|
||||
|
||||
```js
|
||||
path.attr('data-text', 'Hello')
|
||||
path.addText('Hello')
|
||||
```
|
||||
|
||||
The difference with [Path.setText()](/reference/api/path/addtext) is that this
|
||||
method will add to the existing text whereas `Path.setText()` will overwrite
|
||||
existing text on the path,
|
|
@ -5,13 +5,13 @@ title: Path.asPathString()
|
|||
This `Path.asPathString()` returs the path as a string that can be used
|
||||
as the `d` attribute for an SVG `path` element.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
string path.asPathString()
|
||||
```
|
||||
|
||||
<Note>
|
||||
## Notes
|
||||
|
||||
This method is mostly aimed at people looking to implement their own rendering
|
||||
methods, or integrate with SVG processing tools.
|
||||
|
||||
</Note>
|
||||
|
|
|
@ -8,6 +8,8 @@ It calls `this.attributes.add()` under the hood, and returns the Path object.
|
|||
If the third parameter is set to `true` it will call `this.attributes.set()`
|
||||
instead, thereby overwriting the value of the attribute.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
|
@ -18,31 +20,35 @@ Path path.attr(
|
|||
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption=" Example of the Path.attr() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.from = new Point(10, 50);
|
||||
points.cp1 = new Point(40, 10);
|
||||
points.cp2 = new Point(90, 30);
|
||||
points.to = new Point(50, 90);
|
||||
points.from = new Point(10, 20);
|
||||
points.cp1 = new Point(20, -10);
|
||||
points.cp2 = new Point(50, 50);
|
||||
points.to = new Point(70, 20);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.from)
|
||||
.curve(points.cp1, points.cp2, points.to)
|
||||
.addClass("canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
.setClass("canvas")
|
||||
.setText("FreeSewing rocks", "text-xs center")
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
<Note>
|
||||
|
||||
Methods like `addClass`, `setClass`, `addCircle`, `setCircle`, `adddText`, and `setText`
|
||||
## Notes
|
||||
|
||||
Methods like
|
||||
[`Path.addClass`](/reference/api/path/addclass),
|
||||
[`Path.setClass`](/reference/api/path/setclass),
|
||||
[`Path.adddText`](/reference/api/path/addtext), and
|
||||
[`Path.setText`](/reference/api/path/settext)
|
||||
all call this method under the hood.
|
||||
|
||||
</Note>
|
||||
|
|
|
@ -5,6 +5,8 @@ title: Path.bbox()
|
|||
The `Path.bbox()` method returns an object describing the bounding box of a path.
|
||||
In other words, it gives you a rectangle the Path fits in.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
object path.bbox()
|
||||
```
|
||||
|
@ -18,8 +20,6 @@ It returns an object with a signature like this:
|
|||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
## Notes
|
||||
|
||||
This method is mostly aimed at people looking to implement their own layout solution.
|
||||
|
||||
</Note>
|
||||
|
|
|
@ -4,30 +4,36 @@ title: Path.clone()
|
|||
|
||||
The `Path.clone()` method returns a new `Path` object that is a deep copy of this path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.clone()
|
||||
```
|
||||
|
||||
<Example part="path_clone">
|
||||
Example of the Path.clone() method
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.clone() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
paths.clone = paths.example
|
||||
.clone()
|
||||
.setClass("note lashed stroke-xl")
|
||||
.attr("style", "stroke-opacity: 0.5");
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
paths.clone = paths.example
|
||||
.clone()
|
||||
.attr("class", "note lashed stroke-l")
|
||||
.attr("style", "stroke-opacity: 0.5");
|
||||
```
|
||||
|
|
|
@ -1,29 +1,36 @@
|
|||
---
|
||||
title: close()
|
||||
title: Path.close()
|
||||
---
|
||||
|
||||
The `Path.close()` method closes a path by drawing a straight line from the current position to the path's start.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.close()
|
||||
```
|
||||
|
||||
Closes a path by drawing a straight line from the current position to the path's start.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Example part="path_close">
|
||||
Example of the Path.close() method
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.close() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.from = new Point(10, 20)
|
||||
points.cp2 = new Point(60, 30)
|
||||
points.to = new Point(90, 20)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
._curve(points.cp2, points.to)
|
||||
.close()
|
||||
.reverse() // To keep text from being upside-down
|
||||
.setText('Path._close()', 'text-sm right fill-note')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.from = new Point(10, 20);
|
||||
points.cp2 = new Point(60, 30);
|
||||
points.to = new Point(90, 20);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
._curve(points.cp2, points.to)
|
||||
.close()
|
||||
.reverse() // To keep text from being upside-down
|
||||
.attr("data-text", "Path._close()")
|
||||
.attr("data-text-class", "text-sm right fill-note");
|
||||
```
|
||||
|
|
|
@ -1,28 +1,36 @@
|
|||
---
|
||||
title: curve()
|
||||
title: Path.curve()
|
||||
---
|
||||
|
||||
The `Path.curve()` method draws a cubic Bezier curve from the current position
|
||||
via two control points to a given endpoint.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.curve(Point cp1, Point cp2, Point to)
|
||||
```
|
||||
|
||||
Draws a cubic Bezier curve from the current position via two control points to a given endpoint.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Example part="path_curve">
|
||||
Example of the Path.curve() method
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.curve() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.from = new Point(10, 20);
|
||||
points.cp1 = new Point(40, 0);
|
||||
points.cp2 = new Point(60, 40);
|
||||
points.to = new Point(90, 20);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve(points.cp1, points.cp2, points.to)
|
||||
.setText("Path.curve()", "text-sm center fill-note")
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.from = new Point(10, 20);
|
||||
points.cp1 = new Point(40, 0);
|
||||
points.cp2 = new Point(60, 30);
|
||||
points.to = new Point(90, 20);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve(points.cp1, points.cp2, points.to)
|
||||
.attr("data-text", "Path.curve()")
|
||||
.attr("data-text-class", "text-sm center fill-note");
|
||||
```
|
||||
|
|
|
@ -1,35 +1,26 @@
|
|||
---
|
||||
title: "curve_()"
|
||||
title: Path.curve_()
|
||||
---
|
||||
|
||||
The `Path.curve_()` method draws a cubic Bezier curve from the current position
|
||||
via two control points to a given endpoint. However, the end control point is
|
||||
identical to the end point.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.curve_(Point cp1, Point to)
|
||||
```
|
||||
|
||||
Draws a cubic Bezier curve from the current position via two control points to a given endpoint.
|
||||
However, the end control point is identical to the end point.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Tip>
|
||||
## Example
|
||||
|
||||
###### This method exists to save you some typing
|
||||
|
||||
Note that the two following calls yield the same result:
|
||||
<Example caption="Example of the Path.curve\_() method">
|
||||
|
||||
```js
|
||||
.curve(point1, point2, point2)
|
||||
.curve_(point1, point2)
|
||||
```
|
||||
|
||||
So the only purpose of this method is to save your some typing;
|
||||
|
||||
</Tip>
|
||||
|
||||
<Example part="path_curve_">
|
||||
Example of the Path.curve\_() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.from = new Point(10, 20);
|
||||
points.cp1 = new Point(40, 0);
|
||||
|
@ -38,6 +29,20 @@ Example of the Path.curve\_() method
|
|||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.curve_(points.cp1, points.to)
|
||||
.attr("data-text", "Path.curve_()")
|
||||
.attr("data-text-class", "text-sm center fill-note");
|
||||
.setText("Path.curve_()", "text-sm center fill-note")
|
||||
.attr("data-text-dy", -1)
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
## Notes
|
||||
|
||||
The main purpose of this method is to save your some typing,
|
||||
as the two following calls yield the same result:
|
||||
|
||||
```js
|
||||
.curve(point1, point2, point2)
|
||||
.curve_(point1, point2)
|
||||
```
|
||||
|
|
|
@ -1,42 +1,49 @@
|
|||
---
|
||||
title: divide()
|
||||
title: Path.divide()
|
||||
---
|
||||
|
||||
The `Path.divide()` method breaks a path apart in an array of atomic paths. An
|
||||
atomic path is a path that can't be divided further and is always made up of
|
||||
one move + one drawing operation.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
array path.divide()
|
||||
```
|
||||
|
||||
Breaks a path apart in an array of atomic paths. An atomic path is a path that can't be divided further and is
|
||||
always made up of one move + one drawing operation.
|
||||
|
||||
<Example part="path_divide">
|
||||
Example of the Path.divide() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.divide() method">
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.A = new Point(55, 40);
|
||||
points.B = new Point(10, 70);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 60);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 80);
|
||||
points.DCp1 = new Point(140, 50);
|
||||
points.A = new Point(55, 40);
|
||||
points.B = new Point(10, 70);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 60);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 80);
|
||||
points.DCp1 = new Point(140, 50);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D)
|
||||
.close();
|
||||
|
||||
let style = "stroke-width: 4; stroke-opacity: 0.5;";
|
||||
let i = 0;
|
||||
for (let p of paths.example.divide()) {
|
||||
i++;
|
||||
paths[i] = p
|
||||
.attr("style", style)
|
||||
.attr('style', `stroke: hsl(${i * 70}, 100%, 50%)`)
|
||||
}
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D)
|
||||
.close();
|
||||
|
||||
let style = "stroke-width: 4; stroke-opacity: 0.5;";
|
||||
let i = 0;
|
||||
for (let p of paths.example.divide()) {
|
||||
i++;
|
||||
paths[i] = p
|
||||
.attr("style", style)
|
||||
.attr("style", `stroke: hsl(${i * 70}, 100%, 50%)`);
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: edge()
|
||||
title: Path.edge()
|
||||
---
|
||||
|
||||
```js
|
||||
|
@ -17,36 +17,37 @@ Returns the Point object at the edge of the path you specify. Edge must be one o
|
|||
- `bottomLeft`
|
||||
- `bottomRight`
|
||||
|
||||
<Example part="path_edge">
|
||||
Example of the Path.edge() method
|
||||
</Example>
|
||||
|
||||
<Example caption="Example of the Path.edge() method">
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
({ Point, points, Path, paths,snippets, Snippet, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(-60, 90);
|
||||
points.E = new Point(90, 190);
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
points.D = new Point(-60, 90)
|
||||
points.E = new Point(90, 190)
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.E, points.D, points.A)
|
||||
.close()
|
||||
|
||||
for (let i of [
|
||||
"topLeft",
|
||||
"topRight",
|
||||
"bottomLeft",
|
||||
"bottomRight",
|
||||
"top",
|
||||
"left",
|
||||
"bottom",
|
||||
"right"
|
||||
]) snippets[i] = new Snippet("notch", paths.demo.edge(i))
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.E, points.D, points.A)
|
||||
.close();
|
||||
|
||||
for (let i of [
|
||||
"topLeft",
|
||||
"topRight",
|
||||
"bottomLeft",
|
||||
"bottomRight",
|
||||
"top",
|
||||
"left",
|
||||
"bottom",
|
||||
"right"
|
||||
]) snippets[i] = new Snippet("notch", paths.demo.edge(i));
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
|
|
@ -13,8 +13,13 @@ Path new Path();
|
|||
|
||||
A Path objects comes with the following properties:
|
||||
|
||||
- `render` : Set this to `false` to not render the path (exclude it from the output)
|
||||
- `attributes` : An [Attributes](/reference/api/attributes) instance holding the path's attributes
|
||||
- `attributes` : An [Attributes](/reference/api/attributes) instance holding
|
||||
the path's attributes
|
||||
- `hidden` : When this is `true` the path will be hidden (excluded it from the
|
||||
output). See [Path.hide()](/reference/api/path/hide),
|
||||
[Path.unhide()](/reference/api/path/unhide), and
|
||||
[Path.setHidden()](/reference/api/path/sethidden) for various methods that
|
||||
allow setting this in a chainable way.
|
||||
|
||||
In addition, a Path object exposes the following methods:
|
||||
|
||||
|
|
|
@ -1,30 +1,38 @@
|
|||
---
|
||||
title: end()
|
||||
title: Path.end()
|
||||
---
|
||||
|
||||
The `Path.end()` method returns the Point object at the end of the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point path.end()
|
||||
```
|
||||
|
||||
Returns the Point object at the end of the path.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Example part="path_end">
|
||||
Example of the Path.end() method
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.end() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, snippets, Snippet, part }) => {
|
||||
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
snippets.end = new Snippet("notch", paths.demo.end())
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
snippets.end = new Snippet("notch", paths.demo.end());
|
||||
```
|
||||
|
|
|
@ -1,37 +1,33 @@
|
|||
---
|
||||
title: hide()
|
||||
title: Path.hide()
|
||||
---
|
||||
|
||||
The `Path.hide()` hides the path so it does not appear in the output.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Path path.hide()
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
## Example
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
<Example caption="Example of the Path.hide() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
points.top = new Point(50, 0)
|
||||
points.left = new Point (20,50)
|
||||
points.right = new Point (80,50)
|
||||
|
||||
paths.a = new Path().move(points.top).line(points.right).setText('a')
|
||||
paths.b = new Path().move(points.right).line(points.left).setText('b').hide()
|
||||
paths.c = new Path().move(points.left).line(points.top).setText('c')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
```
|
||||
|
|
|
@ -1,38 +1,51 @@
|
|||
---
|
||||
title: insop()
|
||||
title: Path.insop()
|
||||
---
|
||||
|
||||
The `Path.insop()` method injects a Path into the [`noop`
|
||||
operation](/reference/api/path/noop) with id `id`.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.insop(string id, Path path)
|
||||
```
|
||||
|
||||
Injects a Path into the [`noop` operation](/reference/api/path/noop) with id `id`.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Tip compact>This is often used to insert darts into a path</Tip>
|
||||
|
||||
<Example part="path_noop">
|
||||
Example of the Path.noop() method
|
||||
<Example caption="Example of the Path.insop() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.left = new Point(10,10)
|
||||
points.dartLeft = new Point(40, 10)
|
||||
points.dartTip = new Point(50, 50)
|
||||
points.dartRight = new Point(60, 10)
|
||||
points.right = new Point(90, 10)
|
||||
|
||||
paths.withoutDart = new Path()
|
||||
.move(points.left)
|
||||
.line(points.dartLeft)
|
||||
.noop('dart')
|
||||
.line(points.right)
|
||||
|
||||
paths.withDart = paths.withoutDart
|
||||
.clone()
|
||||
.insop(
|
||||
'dart',
|
||||
new Path()
|
||||
.line(points.dartTip)
|
||||
.line(points.dartRight)
|
||||
)
|
||||
.attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
points.left = new Point(10,10)
|
||||
points.dartLeft = new Point(40, 10)
|
||||
points.dartTip = new Point(50, 50)
|
||||
points.dartRight = new Point(60, 10)
|
||||
points.right = new Point(90, 10)
|
||||
## Notes
|
||||
|
||||
paths.withoutDart = new Path()
|
||||
.move(points.left)
|
||||
.line(points.dartLeft)
|
||||
.noop('dart')
|
||||
.line(points.right)
|
||||
This is often used to insert darts into a path.
|
||||
|
||||
paths.withDart = paths.without
|
||||
.insop(
|
||||
'dart',
|
||||
new Path()
|
||||
.line(points.dartTip)
|
||||
.line(points.dartRight)
|
||||
)
|
||||
.attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
|
||||
```
|
||||
|
|
|
@ -1,59 +1,61 @@
|
|||
---
|
||||
title: intersects()
|
||||
title: Path.intersects()
|
||||
---
|
||||
|
||||
```
|
||||
array|false path.intersects(Path path)
|
||||
```
|
||||
The `Path.intersects()` method returns the Point object(s) where the path
|
||||
intersects with a path you pass it.
|
||||
|
||||
Returns the Point object(s) where the path intersects with a path you pass it.
|
||||
## Signature
|
||||
|
||||
<Tip>
|
||||
```
|
||||
array|false path.intersects(Path path)
|
||||
```
|
||||
|
||||
###### Use the intersection methods in Utils whenever possible
|
||||
|
||||
<Example caption="Example of the Path.intersects() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, snippets, Snippet, getId, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 130);
|
||||
points.DCp1 = new Point(150, 30);
|
||||
|
||||
points._A = new Point(55, 40);
|
||||
points._B = new Point(0, 55);
|
||||
points._BCp2 = new Point(40, -20);
|
||||
points._C = new Point(90, 40);
|
||||
points._CCp1 = new Point(50, -30);
|
||||
points._D = new Point(40, 120);
|
||||
points._DCp1 = new Point(180, 40);
|
||||
|
||||
paths.demo1 = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D);
|
||||
paths.demo2 = new Path()
|
||||
.move(points._A)
|
||||
.line(points._B)
|
||||
.curve(points._BCp2, points._CCp1, points._C)
|
||||
.curve(points._DCp1, points._DCp1, points._D);
|
||||
|
||||
for (let p of paths.demo1.intersects(paths.demo2)) {
|
||||
snippets[getId()] = new Snippet('notch', p)
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
This is an expensive (read: slow) method that you should only use when you don't know
|
||||
in advance in what segment of your path the intersection will occur.
|
||||
|
||||
If you do know, use one of the intersection methods in [Utils](/reference/api/utils).
|
||||
|
||||
</Tip>
|
||||
|
||||
<Example part="path_intersects">
|
||||
Example of the Path.intersects() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 130);
|
||||
points.DCp1 = new Point(150, 30);
|
||||
|
||||
points._A = new Point(55, 40);
|
||||
points._B = new Point(0, 55);
|
||||
points._BCp2 = new Point(40, -20);
|
||||
points._C = new Point(90, 40);
|
||||
points._CCp1 = new Point(50, -30);
|
||||
points._D = new Point(40, 120);
|
||||
points._DCp1 = new Point(180, 40);
|
||||
|
||||
paths.demo1 = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D);
|
||||
paths.demo2 = new Path()
|
||||
.move(points._A)
|
||||
.line(points._B)
|
||||
.curve(points._BCp2, points._CCp1, points._C)
|
||||
.curve(points._DCp1, points._DCp1, points._D);
|
||||
|
||||
for (let p of paths.demo1.intersects(paths.demo2)) {
|
||||
snippets[part.getId()] = new Snippet("notch", p);
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,43 +1,50 @@
|
|||
---
|
||||
title: intersectsX()
|
||||
title: Path.intersectsX()
|
||||
---
|
||||
|
||||
The `Path.intersectsX()` method returns the Point object(s) where the path
|
||||
intersects with a given X-value.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
array|false path.intersectsX(float x)
|
||||
```
|
||||
|
||||
Returns the Point object(s) where the path intersects with a given X-value.
|
||||
|
||||
<Example part="path_intersectsx">
|
||||
Example of the Path.intersectsX() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.intersectsX() method">
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
({ Point, points, Path, paths, snippets, Snippet, getId, part }) => {
|
||||
|
||||
points.A = new Point(95, 50);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 130);
|
||||
points.DCp1 = new Point(150, 30);
|
||||
points.A = new Point(95, 50);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 130);
|
||||
points.DCp1 = new Point(150, 30);
|
||||
|
||||
points.top = new Point(60, -10);
|
||||
points.bot = new Point(60, 140);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.top)
|
||||
.line(points.bot)
|
||||
.attr("class", "lining dashed");
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D);
|
||||
|
||||
for (let p of paths.demo.intersectsX(60)) {
|
||||
snippets[getId()] = new Snippet("notch", p);
|
||||
}
|
||||
|
||||
points.top = new Point(60, -10);
|
||||
points.bot = new Point(60, 140);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.top)
|
||||
.line(points.bot)
|
||||
.attr("class", "lining dashed");
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D);
|
||||
|
||||
for (let p of paths.demo.intersectsX(60)) {
|
||||
snippets[part.getId()] = new Snippet("notch", p);
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
|
|
@ -1,43 +1,50 @@
|
|||
---
|
||||
title: intersectsY()
|
||||
title: Path.intersectsY()
|
||||
---
|
||||
|
||||
The `Path.intersectsY()` method returns the Point object(s) where the path
|
||||
intersects with a given Y-value.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
array|false path.intersectsY(float y)
|
||||
```
|
||||
|
||||
Returns the Point object(s) where the path intersects with a given Y-value.
|
||||
|
||||
<Example part="path_intersectsy">
|
||||
Example of the Path.intersectsY() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.intersectsY() method">
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
({ Point, points, Path, paths, snippets, Snippet, getId, part }) => {
|
||||
|
||||
points.A = new Point(55, 40);
|
||||
points.B = new Point(10, 70);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 60);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 80);
|
||||
points.DCp1 = new Point(140, 50);
|
||||
points.A = new Point(55, 40);
|
||||
points.B = new Point(10, 70);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 60);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 80);
|
||||
points.DCp1 = new Point(140, 50);
|
||||
|
||||
points.top = new Point(10, 58);
|
||||
points.bot = new Point(130, 58);
|
||||
points.top = new Point(10, 58);
|
||||
points.bot = new Point(130, 58);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.top)
|
||||
.line(points.bot)
|
||||
.attr("class", "lining dashed");
|
||||
paths.line = new Path()
|
||||
.move(points.top)
|
||||
.line(points.bot)
|
||||
.attr("class", "lining dashed");
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D);
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.curve(points.DCp1, points.DCp1, points.D);
|
||||
|
||||
for (let p of paths.demo.intersectsY(58)) {
|
||||
snippets[part.getId()] = new Snippet("notch", p);
|
||||
for (let p of paths.demo.intersectsY(58)) {
|
||||
snippets[getId()] = new Snippet("notch", p);
|
||||
}
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
|
|
@ -1,44 +1,49 @@
|
|||
---
|
||||
title: join()
|
||||
title: Path.join()
|
||||
---
|
||||
|
||||
The `Path.join()` method joins this path with another path.
|
||||
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.join(path other)
|
||||
```
|
||||
|
||||
Joins this path with another path.
|
||||
## Examples
|
||||
|
||||
<Warning>
|
||||
<Example caption="Example of the Path.join() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.path1 = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.setClass("various")
|
||||
|
||||
paths.path2 = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.setClass("note")
|
||||
|
||||
paths.joint = paths.path1
|
||||
.join(paths.path2)
|
||||
.setClass("lining dotted")
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
You cannot join a closed path to another path
|
||||
|
||||
</Warning>
|
||||
|
||||
<Example part="path_join">
|
||||
Example of the Path.join() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.path1 = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.attr("class", "various");
|
||||
|
||||
paths.path2 = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas");
|
||||
|
||||
paths.joint = paths.path1
|
||||
.join(paths.path2)
|
||||
.attr("class", "note lashed stroke-l")
|
||||
.attr("style", "stoke-opacity: 0.5");
|
||||
```
|
||||
|
|
|
@ -1,43 +1,49 @@
|
|||
---
|
||||
title: length()
|
||||
title: Path.length()
|
||||
---
|
||||
|
||||
The `Path.length()` method returns the length of the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
float path.length()
|
||||
```
|
||||
|
||||
Returns the length of the path.
|
||||
## Example
|
||||
|
||||
<Example part="path_length">
|
||||
Example of the Path.length() method
|
||||
<Example caption="Example of the Path.length() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, macro, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
macro("pd", {
|
||||
path: paths.example,
|
||||
d: -20
|
||||
});
|
||||
|
||||
macro("pd", {
|
||||
path: new Path().move(points.B).line(points.A),
|
||||
d: 10
|
||||
});
|
||||
|
||||
macro("pd", {
|
||||
path: new Path().move(points.B).curve(points.BCp2, points.CCp1, points.C),
|
||||
d: -10
|
||||
});
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, macro } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
macro("pd", {
|
||||
path: paths.example,
|
||||
d: -20
|
||||
});
|
||||
|
||||
macro("pd", {
|
||||
path: new Path().move(points.B).line(points.A),
|
||||
d: 10
|
||||
});
|
||||
|
||||
macro("pd", {
|
||||
path: new Path().move(points.B).curve(points.BCp2, points.CCp1, points.C),
|
||||
d: -10
|
||||
});
|
||||
```
|
||||
|
|
|
@ -1,26 +1,34 @@
|
|||
---
|
||||
title: line()
|
||||
title: Path.line()
|
||||
---
|
||||
|
||||
The `Path.line()` method draws a straight line from the current position to a
|
||||
given point.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.line(Point to)
|
||||
```
|
||||
|
||||
Draws a straight line from the current position to a given point.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Example part="path_line">
|
||||
Example of the Path.line() method
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.line() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(90, 10)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.setText("Path.line()", "text-sm center fill-note")
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.from = new Point(10, 10);
|
||||
points.to = new Point(90, 10);
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.attr("data-text", "Path.line()")
|
||||
.attr("data-text-class", "text-sm center fill-note");
|
||||
```
|
||||
|
|
|
@ -1,18 +1,36 @@
|
|||
---
|
||||
title: move()
|
||||
title: Path.move()
|
||||
---
|
||||
|
||||
The `Path.move()` method moves to a given point without drawing a line.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.move(Point to)
|
||||
```
|
||||
|
||||
Moves to a given point without drawing a line.
|
||||
## Example
|
||||
|
||||
<Tip>
|
||||
|
||||
###### Always start your path with a move
|
||||
<Example caption="Example of the Path.move() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
When drawing a path, you must always start with a `move()` call,
|
||||
points.to = new Point(50, 20)
|
||||
.setText("Path.move()", "text-xs fill-note center")
|
||||
|
||||
paths.noline = new Path().move(points.to)
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
When drawing a path, **you must always start with a `move()` call**,
|
||||
followed by your `line()` and/or `curve()` calls
|
||||
and an optional `close()` call.
|
||||
|
||||
|
@ -23,21 +41,5 @@ paths.example = new Path()
|
|||
.move(points.a)
|
||||
.curve(points.b, points.c, points.d)
|
||||
.line(points.e)
|
||||
.close();
|
||||
```
|
||||
|
||||
</Tip>
|
||||
|
||||
<Example part="path_move">
|
||||
Example of the Path.move() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.to = new Point(50, 20)
|
||||
.attr("data-text", "Path.move()")
|
||||
.attr("data-text-class", "text-xs fill-note");
|
||||
|
||||
paths.noline = new Path().move(points.to);
|
||||
.close()
|
||||
```
|
||||
|
|
|
@ -1,41 +1,49 @@
|
|||
---
|
||||
title: noop()
|
||||
title: Path.noop()
|
||||
---
|
||||
|
||||
The `Path.noop()` method adds a placeholder path operation.
|
||||
A `noop` operation does nothing, but is intended to be replaced later
|
||||
with [`Path.insop()`](/reference/api/path/insop).
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.noop(string id)
|
||||
```
|
||||
|
||||
Adds a placeholder path operation.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
A `noop` operation does nothing, but is intended to be replaced later
|
||||
with [`Path.insop()`](/reference/api/path/insop).
|
||||
## Example
|
||||
|
||||
<Tip compact>This is often used to insert darts into a path</Tip>
|
||||
<Example caption="Example of the Path.noop() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_noop">
|
||||
Example of the Path.noop() method
|
||||
points.left = new Point(10,10)
|
||||
points.dartLeft = new Point(40, 10)
|
||||
points.dartTip = new Point(50, 50)
|
||||
points.dartRight = new Point(60, 10)
|
||||
points.right = new Point(90, 10)
|
||||
|
||||
paths.withoutDart = new Path()
|
||||
.move(points.left)
|
||||
.line(points.dartLeft)
|
||||
.noop('dart')
|
||||
.line(points.right)
|
||||
|
||||
paths.withDart = paths.withoutDart
|
||||
.clone()
|
||||
.insop(
|
||||
'dart',
|
||||
new Path()
|
||||
.line(points.dartTip)
|
||||
.line(points.dartRight)
|
||||
)
|
||||
.attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
points.left = new Point(10,10)
|
||||
points.dartLeft = new Point(40, 10)
|
||||
points.dartTip = new Point(50, 50)
|
||||
points.dartRight = new Point(60, 10)
|
||||
points.right = new Point(90, 10)
|
||||
|
||||
paths.withoutDart = new Path()
|
||||
.move(points.left)
|
||||
.line(points.dartLeft)
|
||||
.noop('dart')
|
||||
.line(points.right)
|
||||
|
||||
paths.withDart = paths.without
|
||||
.insop(
|
||||
'dart',
|
||||
new Path()
|
||||
.line(points.dartTip)
|
||||
.line(points.dartRight)
|
||||
)
|
||||
.attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
|
||||
```
|
||||
|
|
|
@ -1,46 +1,53 @@
|
|||
---
|
||||
title: offset()
|
||||
title: Path.offset()
|
||||
---
|
||||
|
||||
The `Path.offset()` method returns a new Path that is offset by distance from
|
||||
the original path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.offset(float distance)
|
||||
```
|
||||
|
||||
Returns a new Path that is offset by distance from the original path.
|
||||
## Example
|
||||
|
||||
<Example part="path_offset">
|
||||
Example of the Path.offset() method
|
||||
<Example caption="Example of the Path.offset() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.line(points.A)
|
||||
.close();
|
||||
|
||||
paths.offset = paths.example
|
||||
.offset(-10)
|
||||
.attr("class", "interfacing");
|
||||
|
||||
paths.lineOffset = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.offset(-5)
|
||||
.attr("class", "various");
|
||||
|
||||
paths.curveOffset = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.offset(-5)
|
||||
.attr("class", "canvas");
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.line(points.A)
|
||||
.close();
|
||||
|
||||
paths.offset = paths.example
|
||||
.offset(-10)
|
||||
.attr("class", "interfacing");
|
||||
|
||||
paths.lineOffset = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.offset(-5)
|
||||
.attr("class", "various");
|
||||
|
||||
paths.curveOffset = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.offset(-5)
|
||||
.attr("class", "canvas");
|
||||
```
|
||||
|
|
|
@ -1,42 +1,49 @@
|
|||
---
|
||||
title: reverse()
|
||||
title: Path.reverse()
|
||||
---
|
||||
|
||||
The `Path.reverse()` returns a path that is the reversed version of this path.
|
||||
As in, start becomes end, and end becomes start.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.reverse()
|
||||
Path path.reverse(bool cloneAttributes=false)
|
||||
```
|
||||
|
||||
Returns a path that is the reversed version of this path. As in, start becomes end, and end becomes start.
|
||||
If you pass a truthy value to this method, it will return a deep clone of the
|
||||
path, including its attributes. By default, it will return a shallow
|
||||
copy, whithout the attributes.
|
||||
|
||||
<Note>
|
||||
## Example
|
||||
|
||||
|
||||
<Example caption="Example of the Path.reverse() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.setText("FreeSewing rocks", "text-xs fill-note center")
|
||||
|
||||
paths.reverse = paths.example.reverse(true)
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
## Notes
|
||||
|
||||
The reversed path is a shallow copy.
|
||||
It will in other words not inherit the attributes of the original path.
|
||||
|
||||
If you want a deep copy, including the attributes, use `Path.clone().reverse()`.
|
||||
If you want a deep copy, including the attributes, use `Path.reverse(true)`.
|
||||
|
||||
</Note>
|
||||
|
||||
<Example part="path_reverse">
|
||||
Example of the Path.reverse() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs fill-note");
|
||||
|
||||
paths.reverse = paths.example
|
||||
.reverse()
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs fill-lining");
|
||||
```
|
||||
|
|
|
@ -1,37 +1,50 @@
|
|||
---
|
||||
title: roughLength()
|
||||
title: Path.roughLength()
|
||||
---
|
||||
|
||||
The `Path.roughLength()` method returns a (very) rough estimate of the path's length.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Number path.roughLength()
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
## Example
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
<Example caption="Example of the Path.attr() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, macro, units, part }) => {
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(120, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
macro("pd", {
|
||||
path: paths.example,
|
||||
d: -10,
|
||||
text: `Path.roughLength() = ${units(paths.example.roughLength())}`
|
||||
})
|
||||
macro("pd", {
|
||||
path: paths.example,
|
||||
d: 10,
|
||||
text: `Path.length() = ${units(paths.example.length())}`
|
||||
});
|
||||
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
## Notes
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
The `Path.roughLength()` is not intended to give an estimate that is accurate, but rather differentiatate between paths that are a few millimeter long, or meters long.
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
```
|
||||
It calculates the length without *walking the (cubic) Bezier curve* making it very fast and very inaccurate (for curves).
|
||||
It is typically used to determine how much precision to apply when walking a curve.
|
||||
|
|
|
@ -1,37 +1,43 @@
|
|||
---
|
||||
title: setClass()
|
||||
title: Path.setClass()
|
||||
---
|
||||
|
||||
The `Path.setClass()` method sets the CSS class(es) of the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Path path.setClass(string className)
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
## Example
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
<Example caption="Example of the Path.setClass() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
points.from = new Point(5, 10)
|
||||
points.to = new Point(95, 10)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.setClass('note dashed')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
## Notes
|
||||
|
||||
The main purpose of this method is to save your some typing,
|
||||
as the two following calls yield the same result:
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
path.attr('class', 'fabric', true)
|
||||
path.addClass('fabric')
|
||||
```
|
||||
|
||||
|
|
|
@ -1,37 +1,34 @@
|
|||
---
|
||||
title: setHidden()
|
||||
title: Path.setHidden()
|
||||
---
|
||||
|
||||
The `Path.setHidden()` method either hides or unhides the path depending on the
|
||||
value you pass it.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Path path.setHidden(bool hidden = false)
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
## Example
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
<Example caption="Example of the Path.setHidden() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
points.top = new Point(50, 0)
|
||||
points.left = new Point (20,50)
|
||||
points.right = new Point (80,50)
|
||||
|
||||
paths.a = new Path().move(points.top).line(points.right).setText('a')
|
||||
paths.b = new Path().move(points.right).line(points.left).setText('b').setHidden(true)
|
||||
paths.c = new Path().move(points.left).line(points.top).setText('c')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
```
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
title: setRender()
|
||||
---
|
||||
|
||||
```js
|
||||
Path path.setRender(bool render)
|
||||
```
|
||||
|
||||
This is a chainable method to sets the `path.render` property.
|
||||
If you set it to `false` your path will not be rendered.
|
||||
|
||||
<Fixme>Add example</Fixme>
|
48
markdown/dev/reference/api/path/settext/en.md
Normal file
48
markdown/dev/reference/api/path/settext/en.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: Path.setText()
|
||||
---
|
||||
|
||||
The `Path.addText()` method set text on the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.setText(string text, string className)
|
||||
```
|
||||
|
||||
The second argument will optionally be used to set the CSS class for the text.
|
||||
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.setText() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
points.from = new Point(5, 10)
|
||||
points.to = new Point(95, 10)
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.addText('FreeSewing rocks')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
## Notes
|
||||
|
||||
The main purpose of this method is to save your some typing,
|
||||
as the two following calls yield the same result:
|
||||
|
||||
```js
|
||||
path.attr('data-text', 'Hello')
|
||||
path.setText('Hello')
|
||||
```
|
||||
|
||||
The difference with [Path.addText()](/reference/api/path/addtext) is that this
|
||||
method will overwrite existing text on the path, whereas `Path.addText()` will
|
||||
add to the existing text.
|
||||
|
|
@ -1,54 +1,55 @@
|
|||
---
|
||||
title: shiftAlong()
|
||||
title: Path.shiftAlong()
|
||||
---
|
||||
|
||||
```js
|
||||
Point path.shiftAlong(float distance[, int stepsPerMm=25])
|
||||
```
|
||||
The `Path.shiftAlong()` method returns a point that lies at distance travelled
|
||||
along the path.
|
||||
|
||||
Returns a point that lies at distance travelled along the path.
|
||||
|
||||
<Example part="path_shiftalong">
|
||||
Example of the Path.shiftAlong() method
|
||||
</Example>
|
||||
## Signature
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
points.x1 = paths.example
|
||||
.shiftAlong(20)
|
||||
.attr("data-text", "2cm")
|
||||
.attr("data-text-class", "center fill-note")
|
||||
.attr("data-text-lineheight", 6);
|
||||
points.x2 = paths.example
|
||||
.shiftAlong(90)
|
||||
.attr("data-text", "9cm")
|
||||
.attr("data-text-class", "center fill-note")
|
||||
.attr("data-text-lineheight", 6);
|
||||
|
||||
snippets.x1 = new Snippet("notch", points.x1);
|
||||
snippets.x2 = new Snippet("notch", points.x2);
|
||||
Point path.shiftAlong(float distance[, int stepsPerMm=10])
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
##### The second parameter is optional
|
||||
|
||||
The second parameter controls the precision by which the path will be _walked_.
|
||||
By default, we'll divide it into 25 steps per mm.
|
||||
By default, we'll divide it into 10 steps per mm.
|
||||
|
||||
If you don't need that precision, you can pass a lower number.
|
||||
But for most cases, you can just ignore it.
|
||||
If you need more precision, you can pass a higher number.
|
||||
For most cases, the default will be fine.
|
||||
|
||||
</Note>
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.shiftAlong() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
points.x1 = paths.example
|
||||
.shiftAlong(20)
|
||||
.attr("data-text", "2cm")
|
||||
.attr("data-text-class", "center fill-note")
|
||||
.attr("data-text-lineheight", 6);
|
||||
points.x2 = paths.example
|
||||
.shiftAlong(90)
|
||||
.attr("data-text", "9cm")
|
||||
.attr("data-text-class", "center fill-note")
|
||||
.attr("data-text-lineheight", 6);
|
||||
|
||||
snippets.x1 = new Snippet("notch", points.x1);
|
||||
snippets.x2 = new Snippet("notch", points.x2);
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
|
|
@ -1,54 +1,52 @@
|
|||
---
|
||||
title: shiftFractionAlong()
|
||||
title: Path.shiftFractionAlong()
|
||||
---
|
||||
|
||||
The `Path.shiftFractionAlong()` returns a point that lies at fraction of the
|
||||
length of the path travelled along the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point path.shiftFractionAlong(float fraction[, int stepsPerMm=25])
|
||||
```
|
||||
|
||||
Returns a point that lies at fraction of the length of the path travelled along the path.
|
||||
|
||||
<Example part="path_shiftfractionalong">
|
||||
Example of the Path.shiftFractionAlong() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
points.x1 = paths.example
|
||||
.shiftFractionAlong(0.2)
|
||||
.attr("data-text", "msg_20")
|
||||
.attr("data-text-class", "center")
|
||||
.attr("data-text-lineheight", 6);
|
||||
points.x2 = paths.example
|
||||
.shiftFractionAlong(0.9)
|
||||
.attr("data-text", "msg_90")
|
||||
.attr("data-text-class", "center")
|
||||
.attr("data-text-lineheight", 6);
|
||||
|
||||
snippets.xl = new Snippet("notch", points.x1);
|
||||
snippets.x2 = new Snippet("notch", points.x2);
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
##### The second parameter is optional
|
||||
|
||||
The second parameter controls the precision by which the path will be _walked_.
|
||||
By default, we'll divide it into 25 steps per mm.
|
||||
By default, we'll divide it into 10 steps per mm.
|
||||
|
||||
If you don't need that precision, you can pass a lower number.
|
||||
But for most cases, you can just ignore it.
|
||||
If you need more precision, you can pass a higher number.
|
||||
For most cases, the default will be fine.
|
||||
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.shiftFractionAlong() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
points.x1 = paths.example
|
||||
.shiftFractionAlong(0.2)
|
||||
.setText("0.2", "center")
|
||||
points.x2 = paths.example
|
||||
.shiftFractionAlong(0.9)
|
||||
.setText("0.9", "center")
|
||||
|
||||
snippets.xl = new Snippet("notch", points.x1);
|
||||
snippets.x2 = new Snippet("notch", points.x2);
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
</Note>
|
||||
|
|
|
@ -1,37 +1,41 @@
|
|||
---
|
||||
title: smurve()
|
||||
title: Path.smurve()
|
||||
---
|
||||
|
||||
The `Path.smurve()` method draws a smooth curve from the current point via a control point to an endpoint.
|
||||
A smooth curve means it will use the reflection of the end control point of the previous curve.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Path path.smurve(Point cp2, Point end)
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
## Example
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
<Example caption="Example of the Path.smurve() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
points.aFrom = new Point(10, 10);
|
||||
points.aCp1 = new Point(40, 40);
|
||||
points.aCp2 = new Point(70, -20);
|
||||
points.aTo = new Point(100, 10);
|
||||
|
||||
points.bCp2 = new Point(50,50)
|
||||
points.bTo = new Point(10,50)
|
||||
|
||||
paths.smurve = new Path()
|
||||
.move(points.aFrom)
|
||||
.curve(points.aCp1, points.aCp2,points.aTo)
|
||||
.smurve(points.bCp2, points.bTo)
|
||||
.reverse() // Puts text at the end
|
||||
.setText('Path.smurve()')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
```
|
||||
|
|
|
@ -1,37 +1,42 @@
|
|||
---
|
||||
title: smurve_()
|
||||
title: Path.smurve_()
|
||||
---
|
||||
|
||||
The `Path.smurve_()` method draws a smooth curve from the current point an endpoint.
|
||||
In addition, the end point's control point lies on top of the end point.
|
||||
|
||||
A smooth curve means it will use the reflection of the end control point of the previous curve.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Path path.smurve_(Point cp2, Point end)
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
## Example
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
<Example caption="Example of the Path.smurve_() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
points.aFrom = new Point(10, 10);
|
||||
points.aCp1 = new Point(40, 40);
|
||||
points.aCp2 = new Point(70, -20);
|
||||
points.aTo = new Point(100, 10);
|
||||
|
||||
points.bTo = new Point(10,50)
|
||||
|
||||
paths.smurve = new Path()
|
||||
.move(points.aFrom)
|
||||
.curve(points.aCp1, points.aCp2,points.aTo)
|
||||
.smurve_(points.bTo)
|
||||
.reverse() // Puts text at the end
|
||||
.setText('Path.smurve()')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
```
|
||||
|
|
|
@ -1,42 +1,49 @@
|
|||
---
|
||||
title: split
|
||||
title: Path.split()
|
||||
---
|
||||
|
||||
The `Path.split()` method splits a path in two halves, on a point along that
|
||||
path that you pass it.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
array path.split(Point splitPoint)
|
||||
```
|
||||
|
||||
Splits a path in two halves, on a point along that path that you pass it.
|
||||
|
||||
<Example part="path_split">
|
||||
Example of the Path.split() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.split() method">
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
({ Point, points, Path, paths, snippets, Snippet, part }) => {
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 130);
|
||||
points.DCp1 = new Point(150, 30);
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
points.D = new Point(50, 130);
|
||||
points.DCp1 = new Point(150, 30);
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.D)
|
||||
.curve(points.DCp1, points.DCp1, points.C)
|
||||
.curve(points.CCp1, points.BCp2, points.B)
|
||||
.line(points.A);
|
||||
|
||||
points.split = paths.demo.shiftFractionAlong(0.75);
|
||||
snippets.split = new Snippet("notch", points.split);
|
||||
|
||||
let style = "stroke-width: 3; stroke-opacity: 0.5;";
|
||||
let halves = paths.demo.split(points.split);
|
||||
for (let i in halves) {
|
||||
paths[i] = halves[i]
|
||||
.attr("style", style)
|
||||
.attr("style", `stroke: hsl(${i * 70}, 100%, 50%)`);
|
||||
}
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.D)
|
||||
.curve(points.DCp1, points.DCp1, points.C)
|
||||
.curve(points.CCp1, points.BCp2, points.B)
|
||||
.line(points.A);
|
||||
|
||||
points.split = paths.demo.shiftFractionAlong(0.75);
|
||||
snippets.split = new Snippet("notch", points.split);
|
||||
|
||||
let style = "stroke-width: 3; stroke-opacity: 0.5;";
|
||||
let halves = paths.demo.split(points.split);
|
||||
for (let i in halves) {
|
||||
paths[i] = halves[i]
|
||||
.attr("style", style)
|
||||
.attr("style", `stroke: hsl(${i * 70}, 100%, 50%)`);
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
|
|
@ -1,30 +1,38 @@
|
|||
---
|
||||
title: start()
|
||||
title: Path.start()
|
||||
---
|
||||
|
||||
The `Path.start()` method returns the Point object at the start of the path.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point path.start()
|
||||
```
|
||||
|
||||
Returns the Point object at the start of the path.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
<Example part="path_start">
|
||||
Example of the Path.start() method
|
||||
## Example
|
||||
|
||||
<Example caption="Example of the Path.start() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, snippets, Snippet, part }) => {
|
||||
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.demo = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
snippets.end = new Snippet("notch", paths.demo.start())
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
snippets.start = new Snippet("notch", paths.example.start());
|
||||
```
|
||||
|
|
|
@ -1,45 +1,51 @@
|
|||
---
|
||||
title: translate()
|
||||
title: Path.translate()
|
||||
---
|
||||
|
||||
The `Path.translate()` method returns a path with
|
||||
[a translate transform](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#Translate)
|
||||
applied.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
Path path.translate(float deltaX, float deltaY)
|
||||
```
|
||||
|
||||
Returns a path with
|
||||
[a translate transform](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#Translate)
|
||||
applied.
|
||||
## Example
|
||||
|
||||
<Example part="path_translate">
|
||||
Example of the Path.translate() method
|
||||
<Example caption="Example of the Path.translate() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part, macro }) => {
|
||||
|
||||
points.A = new Point(45, 60)
|
||||
points.B = new Point(10, 30)
|
||||
points.BCp2 = new Point(40, 20)
|
||||
points.C = new Point(90, 30)
|
||||
points.CCp1 = new Point(50, -30)
|
||||
|
||||
paths.A = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
|
||||
paths.B = paths.A.translate(60, 30)
|
||||
|
||||
points.step1 = points.B.shift(0, 60)
|
||||
points.step2 = points.step1.shift(-90, 30)
|
||||
macro("ld", {
|
||||
from: points.B,
|
||||
to: points.step1,
|
||||
noStartMarker: true
|
||||
})
|
||||
macro("ld", {
|
||||
from: points.step1,
|
||||
to: points.step2,
|
||||
noStartMarker: true
|
||||
})
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths, macro } = part.shorthand();
|
||||
|
||||
points.A = new Point(45, 60);
|
||||
points.B = new Point(10, 30);
|
||||
points.BCp2 = new Point(40, 20);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, -30);
|
||||
|
||||
paths.A = new Path()
|
||||
.move(points.A)
|
||||
.line(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C);
|
||||
|
||||
paths.B = paths.A.translate(60, 30);
|
||||
|
||||
points.step1 = points.B.shift(0, 60);
|
||||
points.step2 = points.step1.shift(-90, 30);
|
||||
macro("ld", {
|
||||
from: points.B,
|
||||
to: points.step1,
|
||||
noStartMarker: true
|
||||
});
|
||||
macro("ld", {
|
||||
from: points.step1,
|
||||
to: points.step2,
|
||||
noStartMarker: true
|
||||
});
|
||||
```
|
||||
|
|
|
@ -1,18 +1,68 @@
|
|||
---
|
||||
title: trim()
|
||||
title: Path.trim()
|
||||
---
|
||||
|
||||
The `Path.trim()` method Returns a new Path that is this path with overlapping
|
||||
parts removed.
|
||||
|
||||
```js
|
||||
Path path.trim()
|
||||
```
|
||||
|
||||
Returns a new Path that is this path with overlapping parts removed.
|
||||
|
||||
|
||||
<Example caption="Example of the Path.trim() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.center = new Point(0, 0)
|
||||
points.base = new Point(0, 10)
|
||||
points.tip = new Point(0, 50)
|
||||
points.tipCpRight = new Point(30, 50)
|
||||
points.tipCpLeft = new Point(-30, 50)
|
||||
paths.example = new Path().move(points.base)
|
||||
for (let i = 0; i < 4; i++) {
|
||||
points["base" + i] = points.base.rotate(60 * i, points.center)
|
||||
points["tip" + i] = points.tip.rotate(60 * i, points.center)
|
||||
points["tipCpRight" + i] = points.tipCpRight.rotate(60 * i, points.center)
|
||||
points["tipCpLeft" + i] = points.tipCpLeft.rotate(60 * i, points.center)
|
||||
if (i < 2) {
|
||||
paths.example
|
||||
.line(points["base" + i])
|
||||
.curve(points["base" + i], points["tipCpLeft" + i], points["tip" + i])
|
||||
.curve(
|
||||
points["tipCpRight" + i],
|
||||
points["base" + i],
|
||||
points["base" + i]
|
||||
);
|
||||
} else {
|
||||
paths.example
|
||||
.line(points["base" + i])
|
||||
.line(points["tip" + i])
|
||||
.line(points["tipCpRight" + i])
|
||||
.line(points["base" + i])
|
||||
}
|
||||
}
|
||||
|
||||
paths.offset = paths.example
|
||||
.offset(10)
|
||||
.setClass("lining dotted stroke-sm")
|
||||
|
||||
paths.trimmed = paths.offset
|
||||
.trim()
|
||||
.setClass("various stroke-xl")
|
||||
.attr("style", "stroke-opacity: 0.5;")
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
This method is typically used when [Path.offset()](/reference/api/path/offset) caused some overlap.
|
||||
|
||||
<Warning>
|
||||
|
||||
###### Use sparsely or performance will suffer
|
||||
However, use this sparsely or performance will suffer.
|
||||
|
||||
This method is recursive and complex, and the performance penalty for using
|
||||
it on a long/complex path will be significant.
|
||||
|
@ -22,54 +72,3 @@ To limit the impact of path.trim(), follow this approach:
|
|||
- construct a minimal path that contains the overlap
|
||||
- trim it
|
||||
- now join it to the rest of your path
|
||||
|
||||
You can see an example of this
|
||||
[in the front part of the Bruce pattern](https://github.com/freesewing/freesewing/blob/3ca5d0edfe54c7ac20aaf3af2f3544aee72f9b99/designs/bruce/src/front.js#L158).
|
||||
|
||||
</Warning>
|
||||
|
||||
<Example part="path_trim">
|
||||
Example of the Path.trim() method
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.center = new Point(0, 0);
|
||||
points.base = new Point(0, 10);
|
||||
points.tip = new Point(0, 50);
|
||||
points.tipCpRight = new Point(30, 50);
|
||||
points.tipCpLeft = new Point(-30, 50);
|
||||
paths.example = new Path().move(points.base);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
points["base" + i] = points.base.rotate(60 * i, points.center);
|
||||
points["tip" + i] = points.tip.rotate(60 * i, points.center);
|
||||
points["tipCpRight" + i] = points.tipCpRight.rotate(60 * i, points.center);
|
||||
points["tipCpLeft" + i] = points.tipCpLeft.rotate(60 * i, points.center);
|
||||
if (i < 2) {
|
||||
paths.example
|
||||
.line(points["base" + i])
|
||||
.curve(points["base" + i], points["tipCpLeft" + i], points["tip" + i])
|
||||
.curve(
|
||||
points["tipCpRight" + i],
|
||||
points["base" + i],
|
||||
points["base" + i]
|
||||
);
|
||||
} else {
|
||||
paths.example
|
||||
.line(points["base" + i])
|
||||
.line(points["tip" + i])
|
||||
.line(points["tipCpRight" + i])
|
||||
.line(points["base" + i]);
|
||||
}
|
||||
}
|
||||
|
||||
paths.offset = paths.example
|
||||
.offset(10)
|
||||
.attr("class", "lining dotted stroke-sm");
|
||||
|
||||
paths.trimmed = paths.offset
|
||||
.trim()
|
||||
.attr("class", "various stroke-xl")
|
||||
.attr("style", "stroke-opacity: 0.5;");
|
||||
```
|
||||
|
|
|
@ -1,37 +1,35 @@
|
|||
---
|
||||
title: unhide()
|
||||
title: Path.unhide()
|
||||
---
|
||||
|
||||
The `Path.unhide()` method unhides the path so it does appears in the output.
|
||||
|
||||
By default, paths are not hidden. So you should only call this on path previously hidden via `Path.hide()`.
|
||||
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Path path.attr(
|
||||
string name,
|
||||
mixed value,
|
||||
bool overwrite = false
|
||||
)
|
||||
Path path.unhide()
|
||||
```
|
||||
|
||||
This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
This allows you to chain different calls together as in the example below.
|
||||
## Example
|
||||
|
||||
If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
|
||||
<Example caption="Example of the Path.unhide() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
<Example part="path_attr">
|
||||
Example of the Path.attr() method
|
||||
points.top = new Point(50, 0)
|
||||
points.left = new Point (20,50)
|
||||
points.right = new Point (80,50)
|
||||
|
||||
paths.a = new Path().move(points.top).line(points.right).setText('a')
|
||||
paths.b = new Path().move(points.right).line(points.left).setText('b').hide().unhide()
|
||||
paths.c = new Path().move(points.left).line(points.top).setText('c')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.B = new Point(10, 50);
|
||||
points.BCp2 = new Point(40, 10);
|
||||
points.C = new Point(90, 30);
|
||||
points.CCp1 = new Point(50, 90);
|
||||
|
||||
paths.example = new Path()
|
||||
.move(points.B)
|
||||
.curve(points.BCp2, points.CCp1, points.C)
|
||||
.attr("class", "canvas")
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "text-xs center");
|
||||
```
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
title: Point.addCircle()
|
||||
---
|
||||
|
||||
Adds a circle to a Point. Under the hood, this will call `Point.attr()` as circles
|
||||
are added by setting attributes. Refer to [Drawing circles](/howtos/code/drawing-circles) for
|
||||
more details.
|
||||
The `Point.addCircle()` method adds a circle to a Point. Under the hood, this
|
||||
will call `Point.attr()` as circles are added by setting attributes. Refer to
|
||||
[Drawing circles](/howtos/code/drawing-circles) for more details.
|
||||
|
||||
## Point.addCircle() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point point.addCircle(
|
||||
|
@ -15,12 +15,9 @@ Point point.addCircle(
|
|||
)
|
||||
```
|
||||
|
||||
## Point.addCircle() example
|
||||
|
||||
<Example part="point_addcircle">
|
||||
Examples of Point.addCircle(), compare this to [Point.setCircle](/reference/api/point/setcircle)
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Examples of Point.addCircle(), compare this to [Point.setCircle](/reference/api/point/setcircle)">
|
||||
```js
|
||||
({ Point, points, part }) => {
|
||||
points.a = new Point(30, 10)
|
||||
|
@ -41,4 +38,6 @@ Examples of Point.addCircle(), compare this to [Point.setCircle](/reference/api/
|
|||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
title: Point.addText()
|
||||
---
|
||||
|
||||
Adds text on a Point. Under the hood, this will call `Point.attr()` as text
|
||||
is added by setting attributes. Refer to [Adding text](/howtos/code/adding-text) for
|
||||
more details.
|
||||
The `Point.addText()` method adds text on a Point. Under the hood, this will
|
||||
call `Point.attr()` as text is added by setting attributes. Refer to [Adding
|
||||
text](/howtos/code/adding-text) for more details.
|
||||
|
||||
## Point.addText() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point point.addText(
|
||||
|
@ -15,21 +15,28 @@ Point point.addText(
|
|||
)
|
||||
```
|
||||
|
||||
## Point.addText() example
|
||||
|
||||
<Example part="point_addtext">
|
||||
Examples of Point.addText(), compare this to [Point.setText](/reference/api/point/settext)
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="Examples of Point.addText(), compare this to [Point.setText](/reference/api/point/settext)">
|
||||
```js
|
||||
({ Point, points, part }) => {
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
points.anchor = new Point(100, 25)
|
||||
.addText('supportFreesewingBecomeAPatron', 'center')
|
||||
.addText('please?')
|
||||
.addText('FreeSewing')
|
||||
.addText('rocks')
|
||||
|
||||
// Avoid the text getting cropped
|
||||
paths.hidden = new Path()
|
||||
.move(points.anchor)
|
||||
.line(points.anchor.shift(0, 80))
|
||||
.addClass('hidden')
|
||||
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
<Tip compact>Remember to [use translation keys, not text](/guides/best-practices/use-translation-keys)</Tip>
|
||||
## Notes
|
||||
|
||||
Remember to [use translation keys, not text](/guides/best-practices/use-translation-keys)
|
||||
|
||||
|
|
|
@ -2,33 +2,36 @@
|
|||
title: Point.angle()
|
||||
---
|
||||
|
||||
A point's `angle()` method returns the angle (in degrees) between this point and
|
||||
the point passed into the method. An angle of 0° points to the right, and the angle increases counterclockwise.
|
||||
The `Point.angle()` method returns the angle (in degrees) between this point
|
||||
and the point passed into the method. An angle of 0° points to the right, and
|
||||
the angle increases counterclockwise.
|
||||
|
||||
## Point.angle() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
float point.angle(Point pointB)
|
||||
```
|
||||
|
||||
## Point.angle() Example
|
||||
## Example
|
||||
|
||||
<Example part="point_angle">
|
||||
An example of the Point.angle() method
|
||||
<Example caption="An example of the Point.angle() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.sun = new Point(10, 5);
|
||||
points.moon = points.sun.shift(-15, 70);
|
||||
points.text = points.sun
|
||||
.shiftFractionTowards(points.moon, 0.8)
|
||||
.attr("data-text", points.sun.angle(points.moon)+"°")
|
||||
.attr("data-text-class", "text-sm fill-note center");
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.sun)
|
||||
.line(points.moon)
|
||||
.attr("class", "dashed");
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand();
|
||||
|
||||
points.sun = new Point(10, 5);
|
||||
points.moon = points.sun.shift(-15, 70);
|
||||
points.text = points.sun
|
||||
.shiftFractionTowards(points.moon, 0.8)
|
||||
.attr("data-text", points.sun.angle(points.moon)+"°")
|
||||
.attr("data-text-class", "text-sm fill-note center");
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.sun)
|
||||
.line(points.moon)
|
||||
.attr("class", "dashed");
|
||||
```
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
title: Point.attr()
|
||||
---
|
||||
|
||||
Adds an attribute to the point, and returns the original point. Setting the third parameter
|
||||
to `true` will replace the value of the attribute instead of adding it.
|
||||
The `Point.attr()` method adds an attribute to the point, and returns the
|
||||
original point. Setting the third parameter to `true` will replace the value of
|
||||
the attribute instead of adding it.
|
||||
|
||||
## Point.attr() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point point.attr(
|
||||
|
@ -15,21 +16,29 @@ Point point.attr(
|
|||
)
|
||||
```
|
||||
|
||||
The `Point.attr()` method calls [`this.attributes.add()`](/reference/api/attributes/add/) under the hood, but returns the `Point` object.
|
||||
This allows you to chain different calls together as in the example below.
|
||||
|
||||
If the third parameter is set to `true` it will call [`this.attributes.set()`](/reference/api/attributes/set/) instead, thereby overwriting the value of the attribute.
|
||||
|
||||
## Point.attr() example
|
||||
|
||||
<Example part="point_attr">
|
||||
An example of the Point.attr() method
|
||||
<Tip compact>This method is chainable as it returns the `Path` object</Tip>
|
||||
|
||||
## Example
|
||||
|
||||
<Example caption="An example of the Point.attr() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, part }) => {
|
||||
|
||||
points.anchor = new Point(100, 25)
|
||||
.attr('data-text', 'FreeSewing')
|
||||
.attr('data-text', 'rocks')
|
||||
|
||||
// Avoid the text getting cropped
|
||||
paths.hidden = new Path()
|
||||
.move(points.anchor)
|
||||
.line(points.anchor.shift(0, 80))
|
||||
.addClass('hidden')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points } = part.shorthand();
|
||||
|
||||
points.anchor = new Point(100, 25)
|
||||
.attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
|
||||
.attr("data-text-class", "center");
|
||||
```
|
||||
|
|
|
@ -2,37 +2,45 @@
|
|||
title: Point.clone()
|
||||
---
|
||||
|
||||
Returns a new `Point` with the same coordinates and attributes as the original point.
|
||||
The `Point.clone()` method returns a new `Point` with the same coordinates and
|
||||
attributes as the original point.
|
||||
|
||||
## Point.clone() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point point.clone()
|
||||
```
|
||||
|
||||
<Note>
|
||||
<Tip compact>This method is chainable as it returns the `Point` object</Tip>
|
||||
|
||||
###### Copy vs clone
|
||||
|
||||
The [`Point.copy()`](/reference/api/point/copy/) method will only copy the point's coordinates, whereas this
|
||||
`Point.clone()` method will also copy its attributes.
|
||||
|
||||
</Note>
|
||||
|
||||
## Point.clone() example
|
||||
|
||||
<Example part="point_clone">
|
||||
An example of the Point.clone() method
|
||||
</Example>
|
||||
## Example
|
||||
|
||||
<Example caption="An example of the Point.clone() method">
|
||||
```js
|
||||
let { Point, points, Snippet, snippets } = part.shorthand();
|
||||
({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
|
||||
points.A = new Point(25, 25)
|
||||
.attr("data-text", "Point A")
|
||||
.attr("data-text-class", "text-xl")
|
||||
.attr("data-text-fill-opacity", "0.5");
|
||||
points.B = points.A.clone().attr("data-text", "Point B");
|
||||
.setText("Point A", "text-xl")
|
||||
.attr("data-text-fill-opacity", "0.5")
|
||||
points.B = points.A.clone().setText("Point B")
|
||||
|
||||
snippets.x = new Snippet("notch", points.A);
|
||||
snippets.x = new Snippet("notch", points.A)
|
||||
|
||||
// Avoid the text getting cropped
|
||||
paths.hidden = new Path()
|
||||
.move(new Point(20,10))
|
||||
.move(new Point(75,30))
|
||||
.addClass('hidden')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
The [`Point.copy()`](/reference/api/point/copy/) method will only copy the
|
||||
point's coordinates, whereas this `Point.clone()` method will also copy its
|
||||
attributes.
|
||||
|
||||
|
|
|
@ -2,37 +2,43 @@
|
|||
title: Point.copy()
|
||||
---
|
||||
|
||||
A point's `copy()` method returns a new point with the same coordinates as the original point.
|
||||
This method does _not_ copy any attributes the original point may have.
|
||||
The `Point.copy()` method returns a new point with the same coordinates as the
|
||||
original point. This method does _not_ copy any attributes the original point
|
||||
may have.
|
||||
|
||||
## Point.copy() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
Point point.copy()
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
###### Copy vs clone
|
||||
|
||||
this `Point.copy()` method will only copy the point's coordinates.
|
||||
To also copy the attributes, use [`Point.clone()`](/reference/api/point/clone/) instead.
|
||||
|
||||
</Note>
|
||||
|
||||
## Point.copy() example
|
||||
|
||||
<Example part="point_copy">
|
||||
An example of the Point.copy() method
|
||||
<Example caption="An example of the Point.copy() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, Snippet, snippets, part }) => {
|
||||
|
||||
points.A = new Point(25, 25)
|
||||
.setText("Point A", "text-xl")
|
||||
.attr("data-text-fill-opacity", "0.5")
|
||||
points.B = points.A.clone().setText("Point B")
|
||||
|
||||
snippets.x = new Snippet("notch", points.A)
|
||||
|
||||
// Avoid the text getting cropped
|
||||
paths.hidden = new Path()
|
||||
.move(new Point(20,10))
|
||||
.move(new Point(75,30))
|
||||
.addClass('hidden')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Snippet, snippets } = part.shorthand();
|
||||
|
||||
points.A = new Point(50, 25)
|
||||
.attr("data-text", "Point A")
|
||||
.attr("data-text-class", "text-xl");
|
||||
points.B = points.A.copy().attr("data-text", "Point B");
|
||||
## Notes
|
||||
|
||||
snippets.x = new Snippet("notch", points.A);
|
||||
```
|
||||
The `Point.copy()` method will only copy the point's coordinates.
|
||||
To also copy the attributes, use [`Point.clone()`](/reference/api/point/clone/) instead.
|
||||
|
|
46
markdown/dev/reference/api/point/dist/en.md
vendored
46
markdown/dev/reference/api/point/dist/en.md
vendored
|
@ -2,35 +2,35 @@
|
|||
title: Point.dist()
|
||||
---
|
||||
|
||||
A point's `dist()` method returns the distance (in mm) between this point and the point you pass it.
|
||||
The `Point.dist()` method returns the distance (in mm) between this point and
|
||||
the point you pass it.
|
||||
|
||||
## Point.dist() signature
|
||||
## Signature
|
||||
|
||||
```js
|
||||
float point.dist(Point point)
|
||||
```
|
||||
|
||||
## Point.dist() example
|
||||
## Example
|
||||
|
||||
<Example part="point_dist">
|
||||
An example of the Point.dist() method
|
||||
<Example caption="An example of the Point.dist() method">
|
||||
```js
|
||||
({ Point, points, Path, paths, units, part }) => {
|
||||
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(80, 70)
|
||||
|
||||
points.text = points.from
|
||||
.shiftFractionTowards(points.to, 0.6)
|
||||
.setText(units(points.from.dist(points.to)), 'text-sm fill-note center')
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.attr('class', 'dashed')
|
||||
|
||||
return part
|
||||
}
|
||||
```
|
||||
</Example>
|
||||
|
||||
```js
|
||||
let { Point, points, Path, paths } = part.shorthand()
|
||||
|
||||
points.from = new Point(10, 10)
|
||||
points.to = new Point(80, 70)
|
||||
|
||||
points.text = points.from
|
||||
.shiftFractionTowards(points.to, 0.6)
|
||||
.attr('data-text', points.from.dist(points.to) + 'mm')
|
||||
.attr('data-text-class', 'text-sm fill-note center')
|
||||
|
||||
paths.line = new Path()
|
||||
.move(points.from)
|
||||
.line(points.to)
|
||||
.attr('class', 'dashed')
|
||||
|
||||
return part
|
||||
```
|
||||
|
|
|
@ -67,6 +67,20 @@ Path.prototype.addClass = function (className = false) {
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* A chainable way to add text to a Path
|
||||
*
|
||||
* @param {string} text - The text to add to the Path
|
||||
* @param {string} className - The CSS classes to apply to the text
|
||||
* @return {Path} this - The Path instance
|
||||
*/
|
||||
Path.prototype.addText = function (text = '', className = false) {
|
||||
this.attributes.add('data-text', text)
|
||||
if (className) this.attributes.add('data-text-class', className)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SVG pathstring for this path
|
||||
*
|
||||
|
@ -536,7 +550,7 @@ Path.prototype.offset = function (distance) {
|
|||
*
|
||||
* @return {object} reverse - A Path instance that is the reversed version of this Path
|
||||
*/
|
||||
Path.prototype.reverse = function () {
|
||||
Path.prototype.reverse = function (cloneAttributes = false) {
|
||||
let sections = []
|
||||
let current
|
||||
let closed = false
|
||||
|
@ -555,6 +569,7 @@ Path.prototype.reverse = function () {
|
|||
let rev = new Path().__withLog(this.log).move(current)
|
||||
for (let section of sections.reverse()) rev.ops.push(section.ops[1])
|
||||
if (closed) rev.close()
|
||||
if (cloneAttributes) rev.attributes = this.attributes.clone()
|
||||
|
||||
return rev
|
||||
}
|
||||
|
@ -613,6 +628,19 @@ Path.prototype.setHidden = function (hidden = false) {
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* A chainable way to set text on a Path
|
||||
*
|
||||
* @param {string} text - The text to add to the Path
|
||||
* @param {string} className - The CSS classes to apply to the text
|
||||
* @return {Path} this - The Path instance
|
||||
*/
|
||||
Path.prototype.setText = function (text = '', className = false) {
|
||||
this.attributes.set('data-text', text)
|
||||
if (className) this.attributes.set('data-text-class', className)
|
||||
|
||||
return this
|
||||
}
|
||||
/**
|
||||
* Returns a point that lies at distance along this Path
|
||||
*
|
||||
|
|
|
@ -149,8 +149,9 @@ Pattern.prototype.draft = function () {
|
|||
this.setStores[set].log.error(
|
||||
`Unable to draft pattern part __${partName}__. Part.draft() is not callable`
|
||||
)
|
||||
this.parts[set][partName].hidden =
|
||||
this.parts[set][partName].hidden === true ? true : !this.__wants(partName, set)
|
||||
// FIXME: THis won't work not that this is immutable
|
||||
// But is it still needed?
|
||||
// this.parts[set][partName].hidden === true ? true : !this.__wants(partName, set)
|
||||
} else {
|
||||
this.setStores[set].log.debug(
|
||||
`Part \`${partName}\` is not needed. Skipping draft and setting hidden to \`true\``
|
||||
|
@ -180,6 +181,7 @@ Pattern.prototype.getConfig = function () {
|
|||
* @return {object} this - The Pattern instance
|
||||
*/
|
||||
Pattern.prototype.getRenderProps = function () {
|
||||
this.store.log.info('Gathering render props')
|
||||
// Run pre-render hook
|
||||
let svg = new Svg(this)
|
||||
svg.hooks = this.hooks
|
||||
|
@ -193,15 +195,6 @@ Pattern.prototype.getRenderProps = function () {
|
|||
props.height = this.height
|
||||
props.autoLayout = this.autoLayout
|
||||
props.settings = this.settings
|
||||
props.logs = {
|
||||
pattern: this.store.logs,
|
||||
sets: this.setStores.map((store) => ({
|
||||
debug: store.logs.debug,
|
||||
info: store.logs.info,
|
||||
error: store.logs.error,
|
||||
warning: store.logs.warning,
|
||||
})),
|
||||
}
|
||||
props.parts = []
|
||||
for (const set of this.parts) {
|
||||
const setParts = {}
|
||||
|
@ -211,6 +204,10 @@ Pattern.prototype.getRenderProps = function () {
|
|||
...set[p].asProps(),
|
||||
store: this.setStores[set[p].set],
|
||||
}
|
||||
} else if (this.setStores[set?.set]) {
|
||||
this.setStores[set.set].log.info(
|
||||
`Part${p} is hidden in set ${set.set}. Not adding to render props`
|
||||
)
|
||||
}
|
||||
}
|
||||
props.parts.push(setParts)
|
||||
|
@ -219,7 +216,16 @@ Pattern.prototype.getRenderProps = function () {
|
|||
for (let s in this.stacks) {
|
||||
if (!this.__isStackHidden(s)) {
|
||||
props.stacks[s] = this.stacks[s].asProps()
|
||||
}
|
||||
} else this.store.log.info(`Stack ${s} is hidden. Skipping in render props.`)
|
||||
}
|
||||
props.logs = {
|
||||
pattern: this.store.logs,
|
||||
sets: this.setStores.map((store) => ({
|
||||
debug: store.logs.debug,
|
||||
info: store.logs.info,
|
||||
error: store.logs.error,
|
||||
warning: store.logs.warning,
|
||||
})),
|
||||
}
|
||||
|
||||
return props
|
||||
|
@ -500,40 +506,48 @@ function getPluginName(plugin) {
|
|||
* @return {Pattern} this - The Pattern instance
|
||||
*/
|
||||
Pattern.prototype.__addPartPlugins = function (part) {
|
||||
if (!part.plugins) return this
|
||||
if (!this.config.plugins) this.config.plugins = {}
|
||||
const plugins = { ...this.config.plugins }
|
||||
if (!part.plugins) return this
|
||||
// Side-step immutability of the part object to ensure plugins is an array
|
||||
let partPlugins = part.plugins
|
||||
if (!Array.isArray(partPlugins)) partPlugins = [partPlugins]
|
||||
for (const plugin of partPlugins) plugins[getPluginName(plugin)] = plugin
|
||||
// Go through list of part plugins
|
||||
for (let plugin of partPlugins) {
|
||||
const name = getPluginName(plugin)
|
||||
this.store.log.debug(
|
||||
plugin.plugin
|
||||
? `🔌 Resolved __${name}__ conditional plugin in \`${part.name}\``
|
||||
: `🔌 Resolved __${name}__ plugin in \`${part.name}\``
|
||||
)
|
||||
// Handle [plugin, data] scenario
|
||||
if (Array.isArray(plugin)) {
|
||||
const pluginObj = { ...plugin[0], data: plugin[1] }
|
||||
plugin = pluginObj
|
||||
}
|
||||
if (plugin.plugin)
|
||||
this.store.log.debug(`🔌 Resolved __${name}__ conditional plugin in \`${part.name}\``)
|
||||
else this.store.log.debug(`🔌 Resolved __${name}__ plugin in \`${part.name}\``)
|
||||
// Do not overwrite an existing plugin with a conditional plugin unless it is also conditional
|
||||
if (plugin.plugin && plugin.condition) {
|
||||
if (!plugins[name]) {
|
||||
plugins[name] = plugin
|
||||
this.store.log.info(`Plugin \`${name}\` was conditionally added.`)
|
||||
} else if (plugins[name]?.condition) {
|
||||
plugins[name + '_'] = plugin
|
||||
this.store.log.info(
|
||||
`Plugin \`${name}\` was conditionally added again. Renaming to ${name}_.`
|
||||
)
|
||||
} else
|
||||
this.store.log.info(
|
||||
`Plugin \`${name}\` was requested conditionally, but is already added explicitly. Not loading.`
|
||||
)
|
||||
} else {
|
||||
if (!plugins[name]) {
|
||||
// New plugin, so we load it
|
||||
plugins[name] = plugin
|
||||
this.store.log.info(`Plugin \`${name}\` was added.`)
|
||||
this.store.log.info(
|
||||
plugin.condition
|
||||
? `New plugin conditionally added: \`${name}\``
|
||||
: `New plugin added: \`${name}\``
|
||||
)
|
||||
} else {
|
||||
// Existing plugin, takes some more work
|
||||
if (plugin.plugin && plugin.condition) {
|
||||
// Multiple instances of the same plugin with different conditions
|
||||
// will all be added, so we need to change the name.
|
||||
if (plugins[name]?.condition) {
|
||||
plugins[name + '_'] = plugin
|
||||
this.store.log.info(
|
||||
`Plugin \`${name}\` was conditionally added again. Renaming to ${name}_.`
|
||||
)
|
||||
} else
|
||||
this.store.log.info(
|
||||
`Plugin \`${name}\` was requested conditionally, but is already added explicitly. Not loading.`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,6 +711,7 @@ Pattern.prototype.__isPartHidden = function (partName) {
|
|||
if (this.__designParts?.[partName]?.hideAll) return true
|
||||
if (this.__mutated.partHide?.[partName]) return true
|
||||
if (this.__mutated.partHideAll?.[partName]) return true
|
||||
if (this.parts?.[this.activeSet]?.[partName]?.hidden) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -722,6 +737,7 @@ Pattern.prototype.__isStackHidden = function (stackName) {
|
|||
if (this.__designParts?.[partName]?.hideAll) return true
|
||||
if (this.__mutated.partHide?.[partName]) return true
|
||||
if (this.__mutated.partHideAll?.[partName]) return true
|
||||
if (this.parts?.[this.activeSet]?.[partName]?.hidden) return true
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -1230,7 +1246,7 @@ Pattern.prototype.__resolveParts = function (count = 0, distance = 0) {
|
|||
if (part.hideAll) this.__mutated.partHide[part.name] = true
|
||||
// Inject (from)
|
||||
if (part.from) {
|
||||
if (part.hideDependencies || part.hideAll) {
|
||||
if (part.hideDependencies || this.__mutated.partHideAll[name]) {
|
||||
// Don't mutate the part, keep this info in the pattern object
|
||||
this.__mutated.partHide[part.from.name] = true
|
||||
this.__mutated.partHideAll[part.from.name] = true
|
||||
|
@ -1249,9 +1265,6 @@ Pattern.prototype.__resolveParts = function (count = 0, distance = 0) {
|
|||
this.__addDependency(name, part, dep)
|
||||
}
|
||||
} else {
|
||||
if (part.hideDependencies) {
|
||||
this.__mutated.partHide[part.after.name] = true
|
||||
}
|
||||
this.__mutated.partDistance[part.after.name] = distance
|
||||
this.__designParts[part.after.name] = part.after
|
||||
this.__addDependency(name, part, part.after)
|
||||
|
|
|
@ -50,6 +50,7 @@ Point.prototype.addText = function (text = '', className = false) {
|
|||
|
||||
return this.__check()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the angle between this Point and that Point
|
||||
*
|
||||
|
@ -202,7 +203,7 @@ Point.prototype.setCircle = function (radius = false, className = false) {
|
|||
}
|
||||
|
||||
/**
|
||||
* A chainable way to add text to a Point
|
||||
* A chainable way to set text on a Point
|
||||
*
|
||||
* @param {string} text - The text to add to the Point
|
||||
* @param {string} className - The CSS classes to apply to the text
|
||||
|
|
|
@ -702,6 +702,9 @@ describe('Pattern', () => {
|
|||
|
||||
it('Should check whether created parts get the pattern context', () => {
|
||||
let partContext
|
||||
const plugin = {
|
||||
name: 'example',
|
||||
}
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, paths, Path, part, context }) => {
|
||||
|
@ -710,6 +713,7 @@ describe('Pattern', () => {
|
|||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Pattern = new Design({ parts: [part], data: { name: 'test', version: '1' } })
|
||||
const pattern = new Pattern()
|
||||
|
|
|
@ -4,12 +4,12 @@ export const plugin = {
|
|||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preDraft: ({ settings }) => {
|
||||
for (const set of settings) {
|
||||
if (set.measurements) {
|
||||
if (typeof set.measurements.bust === 'undefined') {
|
||||
set.measurements.bust = set.measurements.chest
|
||||
set.measurements.chest = set.measurements.highBust
|
||||
preDraft: function ({ settings }) {
|
||||
for (const i in settings) {
|
||||
if (settings[i].measurements) {
|
||||
if (typeof settings[i].measurements.bust === 'undefined') {
|
||||
settings[i].measurements.bust = settings[i].measurements.chest
|
||||
settings[i].measurements.chest = settings[i].measurements.highBust
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,55 +4,48 @@ export const plugin = {
|
|||
name,
|
||||
version,
|
||||
macros: {
|
||||
gore: function (so) {
|
||||
gore: function (so, { points, paths, Path }) {
|
||||
const from = so.from
|
||||
const gores = so.gores
|
||||
const radius = so.radius //radius of the sphere
|
||||
const prefix = so.prefix
|
||||
const extraLength = so.extraLength //the length of the straight section after a complete semisphere
|
||||
|
||||
this.points[prefix + 'p1'] = from.shift(0, (radius * Math.PI) / 2 + extraLength)
|
||||
this.points[prefix + 'Cp1'] = this.points[prefix + 'p1'].shift(
|
||||
points[prefix + 'p1'] = from.shift(0, (radius * Math.PI) / 2 + extraLength)
|
||||
points[prefix + 'Cp1'] = points[prefix + 'p1'].shift(
|
||||
180 - 180 / gores,
|
||||
radius / 2 / Math.cos(Math.PI / gores)
|
||||
)
|
||||
this.points[prefix + 'p3'] = from.shift(90, (radius * Math.PI) / gores)
|
||||
this.points[prefix + 'p2'] = this.points[prefix + 'p3'].shift(0, extraLength)
|
||||
this.points[prefix + 'Cp2'] = this.points[prefix + 'p2'].shift(
|
||||
0,
|
||||
(radius * (Math.PI - 2)) / 2
|
||||
)
|
||||
points[prefix + 'p3'] = from.shift(90, (radius * Math.PI) / gores)
|
||||
points[prefix + 'p2'] = points[prefix + 'p3'].shift(0, extraLength)
|
||||
points[prefix + 'Cp2'] = points[prefix + 'p2'].shift(0, (radius * (Math.PI - 2)) / 2)
|
||||
|
||||
if (extraLength < 0) {
|
||||
//top curve used to calculate the new points if extraLength < 0
|
||||
this.paths.auxiliaryPath = new this.Path()
|
||||
.move(this.points[prefix + 'p1'])
|
||||
.curve(
|
||||
this.points[prefix + 'Cp1'],
|
||||
this.points[prefix + 'Cp2'],
|
||||
this.points[prefix + 'p2']
|
||||
)
|
||||
paths.auxiliaryPath = new Path()
|
||||
.move(points[prefix + 'p1'])
|
||||
.curve(points[prefix + 'Cp1'], points[prefix + 'Cp2'], points[prefix + 'p2'])
|
||||
.hide()
|
||||
|
||||
this.points[prefix + 'p2'] = this.paths.auxiliaryPath.intersectsX(0)[0] //the new point p2 is the one in which the auxiliary curve intersects x=0
|
||||
this.paths.auxiliaryPath = this.paths.auxiliaryPath.split(this.points[prefix + 'p2'])[0] //the auxiliary curve is split
|
||||
this.points[prefix + 'Cp1'] = this.paths.auxiliaryPath.ops[1].cp1 //the new control points are those of the new curve
|
||||
this.points[prefix + 'Cp2'] = this.paths.auxiliaryPath.ops[1].cp2
|
||||
this.points[prefix + 'p3'] = this.points[prefix + 'p2'].clone()
|
||||
points[prefix + 'p2'] = paths.auxiliaryPath.intersectsX(0)[0] //the new point p2 is the one in which the auxiliary curve intersects x=0
|
||||
paths.auxiliaryPath = paths.auxiliaryPath.split(points[prefix + 'p2'])[0] //the auxiliary curve is split
|
||||
points[prefix + 'Cp1'] = paths.auxiliaryPath.ops[1].cp1 //the new control points are those of the new curve
|
||||
points[prefix + 'Cp2'] = paths.auxiliaryPath.ops[1].cp2
|
||||
points[prefix + 'p3'] = points[prefix + 'p2'].clone()
|
||||
}
|
||||
|
||||
//the seam path is generated
|
||||
this.paths[prefix + 'seam'] = new this.Path()
|
||||
paths[prefix + 'seam'] = new Path()
|
||||
.move(from)
|
||||
.line(this.points[prefix + 'p1'])
|
||||
.curve(this.points[prefix + 'Cp1'], this.points[prefix + 'Cp2'], this.points[prefix + 'p2'])
|
||||
.line(this.points[prefix + 'p3'])
|
||||
.line(points[prefix + 'p1'])
|
||||
.curve(points[prefix + 'Cp1'], points[prefix + 'Cp2'], points[prefix + 'p2'])
|
||||
.line(points[prefix + 'p3'])
|
||||
.line(from)
|
||||
.close()
|
||||
.attr('class', so.class ? so.class : '')
|
||||
|
||||
if (so?.hidden) this.paths[prefix + 'seam'].hide()
|
||||
else this.paths[prefix + 'seam'].unhide()
|
||||
if (so?.hidden) paths[prefix + 'seam'].hide()
|
||||
else paths[prefix + 'seam'].unhide()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ describe('Gore Plugin Tests', () => {
|
|||
it('Should create a default gore', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, points, macro }) => {
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchorPoint = new Point(50, 50)
|
||||
macro('gore', {
|
||||
from: points.anchorPoint,
|
||||
|
@ -17,12 +17,15 @@ describe('Gore Plugin Tests', () => {
|
|||
extraLength: 0,
|
||||
prefix: 'gore',
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Test = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
let c = pattern.parts.test.points
|
||||
let c = pattern.parts[0].test.points
|
||||
expect(round(c.gorep1.y)).to.equal(50)
|
||||
expect(round(c.gorep2.x)).to.equal(50)
|
||||
expect(round(c.gorep2.y)).to.equal(30.37)
|
||||
|
@ -33,7 +36,7 @@ describe('Gore Plugin Tests', () => {
|
|||
it('Should use a configurable number of gores', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, points, macro }) => {
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchorPoint = new Point(50, 50)
|
||||
macro('gore', {
|
||||
from: points.anchorPoint,
|
||||
|
@ -42,12 +45,15 @@ describe('Gore Plugin Tests', () => {
|
|||
extraLength: 0,
|
||||
prefix: 'gore',
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Test = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
let c = pattern.parts.test.points
|
||||
let c = pattern.parts[0].test.points
|
||||
expect(round(c.gorep1.x)).to.equal(89.27)
|
||||
expect(round(c.gorep1.y)).to.equal(50)
|
||||
expect(round(c.gorep2.x)).to.equal(50)
|
||||
|
@ -59,7 +65,7 @@ describe('Gore Plugin Tests', () => {
|
|||
it('Should use a configurable extra length', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, points, macro }) => {
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchorPoint = new Point(50, 50)
|
||||
macro('gore', {
|
||||
from: points.anchorPoint,
|
||||
|
@ -68,12 +74,15 @@ describe('Gore Plugin Tests', () => {
|
|||
extraLength: 20,
|
||||
prefix: 'gore',
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Test = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
let c = pattern.parts.test.points
|
||||
let c = pattern.parts[0].test.points
|
||||
expect(round(c.gorep1.x)).to.equal(109.27)
|
||||
expect(round(c.gorep1.y)).to.equal(50)
|
||||
expect(round(c.gorep2.x)).to.equal(70)
|
||||
|
@ -85,7 +94,7 @@ describe('Gore Plugin Tests', () => {
|
|||
it('Should use a configurable radius', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, points, macro }) => {
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchorPoint = new Point(50, 50)
|
||||
macro('gore', {
|
||||
from: points.anchorPoint,
|
||||
|
@ -94,12 +103,15 @@ describe('Gore Plugin Tests', () => {
|
|||
extraLength: 0,
|
||||
prefix: 'gore',
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Test = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
let c = pattern.parts.test.points
|
||||
let c = pattern.parts[0].test.points
|
||||
expect(round(c.gorep1.x)).to.equal(97.12)
|
||||
expect(round(c.gorep1.y)).to.equal(50)
|
||||
expect(round(c.gorep2.x)).to.equal(50)
|
||||
|
@ -111,7 +123,7 @@ describe('Gore Plugin Tests', () => {
|
|||
it('Should generate a seam path', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, points, macro }) => {
|
||||
draft: ({ Point, points, macro, part }) => {
|
||||
points.anchorPoint = new Point(50, 50)
|
||||
macro('gore', {
|
||||
from: points.anchorPoint,
|
||||
|
@ -120,12 +132,15 @@ describe('Gore Plugin Tests', () => {
|
|||
extraLength: 0,
|
||||
prefix: 'gore',
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Test = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
let c = pattern.parts.test.paths.goreseam.ops
|
||||
let c = pattern.parts[0].test.paths.goreseam.ops
|
||||
expect(round(c[1].to.x)).to.equal(89.27)
|
||||
expect(round(c[1].to.y)).to.equal(50)
|
||||
expect(round(c[2].to.x)).to.equal(50)
|
||||
|
|
|
@ -19,19 +19,18 @@ export const plugin = {
|
|||
},
|
||||
},
|
||||
macros: {
|
||||
grainline: function (so = {}) {
|
||||
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
|
||||
if (so === false) {
|
||||
delete this.points.grainlineFrom
|
||||
delete this.points.grainlineTo
|
||||
delete this.paths.grainline
|
||||
this.setGrain(90) // Restoring default
|
||||
delete points.grainlineFrom
|
||||
delete points.grainlineTo
|
||||
delete paths.grainline
|
||||
setGrain(90) // Restoring default
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
...dflts,
|
||||
...so,
|
||||
}
|
||||
const { points, complete, setGrain } = this.shorthand()
|
||||
// setGrain relies on plugin-cutlist
|
||||
if (typeof setGrain === 'function') {
|
||||
setGrain(so.from.angle(so.to))
|
||||
|
@ -39,7 +38,7 @@ export const plugin = {
|
|||
if (complete) {
|
||||
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
|
||||
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
|
||||
this.paths.grainline = new this.Path()
|
||||
paths.grainline = new Path()
|
||||
.move(points.grainlineFrom)
|
||||
.line(points.grainlineTo)
|
||||
.attr('class', 'note')
|
||||
|
|
|
@ -8,19 +8,22 @@ describe('Grainline Plugin Tests', () => {
|
|||
it('Should run the default grainline macro', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ points, Point, macro }) => {
|
||||
draft: ({ points, Point, macro, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.to = new Point(10, 230)
|
||||
macro('grainline', {
|
||||
from: points.from,
|
||||
to: points.to,
|
||||
})
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Pattern = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Pattern = new Design({ parts: [part] })
|
||||
const pattern = new Pattern()
|
||||
pattern.draft()
|
||||
const c = pattern.parts.test.paths.grainline
|
||||
const c = pattern.parts[0].test.paths.grainline
|
||||
expect(c.attributes.get('class')).to.equal('note')
|
||||
expect(c.attributes.get('marker-start')).to.equal('url(#grainlineFrom)')
|
||||
expect(c.attributes.get('marker-end')).to.equal('url(#grainlineTo)')
|
||||
|
|
|
@ -5,31 +5,31 @@ export const plugin = {
|
|||
version,
|
||||
hooks: {
|
||||
preDraft: function ({ settings }) {
|
||||
if (settings.measurements) {
|
||||
if (
|
||||
typeof settings.measurements.seatBack !== 'undefined' &&
|
||||
typeof settings.measurements.seat !== 'undefined'
|
||||
) {
|
||||
settings.measurements.seatFront =
|
||||
settings.measurements.seat - settings.measurements.seatBack
|
||||
settings.measurements.seatBackArc = settings.measurements.seatBack / 2
|
||||
settings.measurements.seatFrontArc = settings.measurements.seatFront / 2
|
||||
}
|
||||
if (
|
||||
typeof settings.measurements.waist !== 'undefined' &&
|
||||
typeof settings.measurements.waistBack !== 'undefined'
|
||||
) {
|
||||
settings.measurements.waistFront =
|
||||
settings.measurements.waist - settings.measurements.waistBack
|
||||
settings.measurements.waistBackArc = settings.measurements.waistBack / 2
|
||||
settings.measurements.waistFrontArc = settings.measurements.waistFront / 2
|
||||
}
|
||||
if (
|
||||
typeof settings.measurements.crossSeam !== 'undefined' &&
|
||||
typeof settings.measurements.crossSeamFront !== 'undefined'
|
||||
) {
|
||||
settings.measurements.crossSeamBack =
|
||||
settings.measurements.crossSeam - settings.measurements.crossSeamFront
|
||||
for (const set of settings) {
|
||||
if (set.measurements) {
|
||||
if (
|
||||
typeof set.measurements.seatBack !== 'undefined' &&
|
||||
typeof set.measurements.seat !== 'undefined'
|
||||
) {
|
||||
set.measurements.seatFront = set.measurements.seat - set.measurements.seatBack
|
||||
set.measurements.seatBackArc = set.measurements.seatBack / 2
|
||||
set.measurements.seatFrontArc = set.measurements.seatFront / 2
|
||||
}
|
||||
if (
|
||||
typeof set.measurements.waist !== 'undefined' &&
|
||||
typeof set.measurements.waistBack !== 'undefined'
|
||||
) {
|
||||
set.measurements.waistFront = set.measurements.waist - set.measurements.waistBack
|
||||
set.measurements.waistBackArc = set.measurements.waistBack / 2
|
||||
set.measurements.waistFrontArc = set.measurements.waistFront / 2
|
||||
}
|
||||
if (
|
||||
typeof set.measurements.crossSeam !== 'undefined' &&
|
||||
typeof set.measurements.crossSeamFront !== 'undefined'
|
||||
) {
|
||||
set.measurements.crossSeamBack =
|
||||
set.measurements.crossSeam - set.measurements.crossSeamFront
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,62 +12,47 @@ const measurements = {
|
|||
crossSeam: 100,
|
||||
crossSeamFront: 42,
|
||||
}
|
||||
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ points, Point }) => {
|
||||
draft: ({ points, Point, part }) => {
|
||||
points.from = new Point(10, 20)
|
||||
points.to = new Point(10, 230)
|
||||
|
||||
return part
|
||||
},
|
||||
measurements: Object.keys(measurements),
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Pattern = new Design({ plugins: [plugin], parts: [part] })
|
||||
const pattern = new Pattern({ measurements })
|
||||
pattern.draft()
|
||||
const Pattern = new Design({ parts: [part] })
|
||||
|
||||
describe('Measurements Plugin Tests', () => {
|
||||
it('Should set the extra measurements', () => {
|
||||
expect(pattern.settings.measurements.seatFront).to.equal(40)
|
||||
expect(pattern.settings.measurements.seatFrontArc).to.equal(20)
|
||||
expect(pattern.settings.measurements.seatBackArc).to.equal(30)
|
||||
expect(pattern.settings.measurements.waistFront).to.equal(55)
|
||||
expect(pattern.settings.measurements.waistFrontArc).to.equal(27.5)
|
||||
expect(pattern.settings.measurements.crossSeamBack).to.equal(58)
|
||||
const pattern = new Pattern({ measurements })
|
||||
pattern.draft()
|
||||
expect(pattern.settings[0].measurements.seatFront).to.equal(40)
|
||||
expect(pattern.settings[0].measurements.seatFrontArc).to.equal(20)
|
||||
expect(pattern.settings[0].measurements.seatBackArc).to.equal(30)
|
||||
expect(pattern.settings[0].measurements.waistFront).to.equal(55)
|
||||
expect(pattern.settings[0].measurements.waistFrontArc).to.equal(27.5)
|
||||
expect(pattern.settings[0].measurements.crossSeamBack).to.equal(58)
|
||||
})
|
||||
|
||||
it('Should calculate seatFront from seat and seatBack', function () {
|
||||
const testPattern = new Design({
|
||||
measurements: {},
|
||||
plugins: [plugin],
|
||||
})
|
||||
const pattern = new testPattern()
|
||||
const userMeasurements = { seat: 50, seatBack: 20 }
|
||||
pattern.settings.measurements = userMeasurements
|
||||
const pattern = new Pattern({ measurements: { seat: 50, seatBack: 20 } })
|
||||
pattern.draft()
|
||||
expect(pattern.settings.measurements.seatFront).to.equal(30)
|
||||
expect(pattern.settings[0].measurements.seatFront).to.equal(30)
|
||||
})
|
||||
|
||||
it('Should calculate waistFrontArc and waistBackArc from waist and waistBack', function () {
|
||||
const testPattern = new Design({
|
||||
measurements: {},
|
||||
plugins: [plugin],
|
||||
})
|
||||
const pattern = new testPattern()
|
||||
const userMeasurements = { waist: 50, waistBack: 20 }
|
||||
pattern.settings.measurements = userMeasurements
|
||||
const pattern = new Pattern({ measurements: { waist: 50, waistBack: 20 } })
|
||||
pattern.draft()
|
||||
expect(pattern.settings.measurements.waistFrontArc).to.equal(15)
|
||||
expect(pattern.settings.measurements.waistBackArc).to.equal(10)
|
||||
expect(pattern.settings[0].measurements.waistFrontArc).to.equal(15)
|
||||
expect(pattern.settings[0].measurements.waistBackArc).to.equal(10)
|
||||
})
|
||||
|
||||
it('Should calculate crossSeamBack from crossSeam and crossSeamFront', function () {
|
||||
const testPattern = new Design({
|
||||
measurements: {},
|
||||
plugins: [plugin],
|
||||
})
|
||||
const pattern = new testPattern()
|
||||
const userMeasurements = { crossSeam: 50, crossSeamFront: 20 }
|
||||
pattern.settings.measurements = userMeasurements
|
||||
const pattern = new Pattern({ measurements: { crossSeam: 50, crossSeamFront: 20 } })
|
||||
pattern.draft()
|
||||
expect(pattern.settings.measurements.crossSeamBack).to.equal(30)
|
||||
expect(pattern.settings[0].measurements.crossSeamBack).to.equal(30)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -7,7 +7,7 @@ const expect = chai.expect
|
|||
describe('Mirror Plugin Tests', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ points, Point, macro, paths, Path }) => {
|
||||
draft: ({ points, Point, macro, paths, Path, part }) => {
|
||||
points.mirrorA = new Point(-100, -100)
|
||||
points.mirrorB = new Point(100, 100)
|
||||
points.a = new Point(10, 20)
|
||||
|
@ -23,58 +23,61 @@ describe('Mirror Plugin Tests', () => {
|
|||
macro('mirror', settings)
|
||||
macro('mirror', { ...settings, prefix: 'test' })
|
||||
macro('mirror', { ...settings, clone: false })
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Pattern = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Pattern = new Design({ parts: [part] })
|
||||
const pattern = new Pattern()
|
||||
pattern.draft()
|
||||
|
||||
it('Should mirror points', () => {
|
||||
expect(pattern.parts.test.points.mirroredA.x).to.equal(20)
|
||||
expect(pattern.parts.test.points.mirroredA.y).to.equal(10)
|
||||
expect(pattern.parts.test.points.mirroredB.x).to.equal(40)
|
||||
expect(pattern.parts.test.points.mirroredB.y).to.equal(30)
|
||||
expect(pattern.parts[0].test.points.mirroredA.x).to.equal(20)
|
||||
expect(pattern.parts[0].test.points.mirroredA.y).to.equal(10)
|
||||
expect(pattern.parts[0].test.points.mirroredB.x).to.equal(40)
|
||||
expect(pattern.parts[0].test.points.mirroredB.y).to.equal(30)
|
||||
})
|
||||
it('Should mirror points with custom prefix', () => {
|
||||
expect(pattern.parts.test.points.testA.x).to.equal(20)
|
||||
expect(pattern.parts.test.points.testA.y).to.equal(10)
|
||||
expect(pattern.parts.test.points.testB.x).to.equal(40)
|
||||
expect(pattern.parts.test.points.testB.y).to.equal(30)
|
||||
expect(pattern.parts[0].test.points.testA.x).to.equal(20)
|
||||
expect(pattern.parts[0].test.points.testA.y).to.equal(10)
|
||||
expect(pattern.parts[0].test.points.testB.x).to.equal(40)
|
||||
expect(pattern.parts[0].test.points.testB.y).to.equal(30)
|
||||
})
|
||||
it('Should mirror points without cloning them', () => {
|
||||
expect(pattern.parts.test.points.a.x).to.equal(20)
|
||||
expect(pattern.parts.test.points.a.y).to.equal(10)
|
||||
expect(pattern.parts.test.points.b.x).to.equal(40)
|
||||
expect(pattern.parts.test.points.b.y).to.equal(30)
|
||||
expect(pattern.parts[0].test.points.a.x).to.equal(20)
|
||||
expect(pattern.parts[0].test.points.a.y).to.equal(10)
|
||||
expect(pattern.parts[0].test.points.b.x).to.equal(40)
|
||||
expect(pattern.parts[0].test.points.b.y).to.equal(30)
|
||||
})
|
||||
it('Should mirror paths', () => {
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[0].to.x).to.equal(2)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[0].to.y).to.equal(1)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[1].cp1.x).to.equal(20)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[1].cp1.y).to.equal(10)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[1].cp2.x).to.equal(40)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[1].cp2.y).to.equal(30)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[1].to.x).to.equal(60)
|
||||
expect(pattern.parts.test.paths.mirroredTest.ops[1].to.y).to.equal(50)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[0].to.x).to.equal(2)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[0].to.y).to.equal(1)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp1.x).to.equal(20)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp1.y).to.equal(10)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp2.x).to.equal(40)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp2.y).to.equal(30)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[1].to.x).to.equal(60)
|
||||
expect(pattern.parts[0].test.paths.mirroredTest.ops[1].to.y).to.equal(50)
|
||||
})
|
||||
it('Should mirror paths with custom prefix', () => {
|
||||
expect(pattern.parts.test.paths.testTest.ops[0].to.x).to.equal(2)
|
||||
expect(pattern.parts.test.paths.testTest.ops[0].to.y).to.equal(1)
|
||||
expect(pattern.parts.test.paths.testTest.ops[1].cp1.x).to.equal(20)
|
||||
expect(pattern.parts.test.paths.testTest.ops[1].cp1.y).to.equal(10)
|
||||
expect(pattern.parts.test.paths.testTest.ops[1].cp2.x).to.equal(40)
|
||||
expect(pattern.parts.test.paths.testTest.ops[1].cp2.y).to.equal(30)
|
||||
expect(pattern.parts.test.paths.testTest.ops[1].to.x).to.equal(60)
|
||||
expect(pattern.parts.test.paths.testTest.ops[1].to.y).to.equal(50)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[0].to.x).to.equal(2)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[0].to.y).to.equal(1)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[1].cp1.x).to.equal(20)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[1].cp1.y).to.equal(10)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[1].cp2.x).to.equal(40)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[1].cp2.y).to.equal(30)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[1].to.x).to.equal(60)
|
||||
expect(pattern.parts[0].test.paths.testTest.ops[1].to.y).to.equal(50)
|
||||
})
|
||||
it('Should mirror paths without cloning them', () => {
|
||||
expect(pattern.parts.test.paths.test.ops[0].to.x).to.equal(2)
|
||||
expect(pattern.parts.test.paths.test.ops[0].to.y).to.equal(1)
|
||||
expect(pattern.parts.test.paths.test.ops[1].cp1.x).to.equal(20)
|
||||
expect(pattern.parts.test.paths.test.ops[1].cp1.y).to.equal(10)
|
||||
expect(pattern.parts.test.paths.test.ops[1].cp2.x).to.equal(40)
|
||||
expect(pattern.parts.test.paths.test.ops[1].cp2.y).to.equal(30)
|
||||
expect(pattern.parts.test.paths.test.ops[1].to.x).to.equal(60)
|
||||
expect(pattern.parts.test.paths.test.ops[1].to.y).to.equal(50)
|
||||
expect(pattern.parts[0].test.paths.test.ops[0].to.x).to.equal(2)
|
||||
expect(pattern.parts[0].test.paths.test.ops[0].to.y).to.equal(1)
|
||||
expect(pattern.parts[0].test.paths.test.ops[1].cp1.x).to.equal(20)
|
||||
expect(pattern.parts[0].test.paths.test.ops[1].cp1.y).to.equal(10)
|
||||
expect(pattern.parts[0].test.paths.test.ops[1].cp2.x).to.equal(40)
|
||||
expect(pattern.parts[0].test.paths.test.ops[1].cp2.y).to.equal(30)
|
||||
expect(pattern.parts[0].test.paths.test.ops[1].to.x).to.equal(60)
|
||||
expect(pattern.parts[0].test.paths.test.ops[1].to.y).to.equal(50)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -9,8 +9,9 @@ const part = {
|
|||
draft: ({ Point, snippets, Snippet }) => {
|
||||
snippets.button = new Snippet('notch', new Point(10, 20))
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Pattern = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Pattern = new Design({ parts: [part] })
|
||||
const pattern = new Pattern()
|
||||
pattern.draft().render()
|
||||
|
||||
|
@ -26,11 +27,14 @@ describe('Notches Plugin Test', () => {
|
|||
it('Draws a notch on an anchor point', () => {
|
||||
const part = {
|
||||
name: 'test',
|
||||
draft: ({ Point, snippets, Snippet }) => {
|
||||
draft: ({ Point, snippets, Snippet, part }) => {
|
||||
snippets.button = new Snippet('notch', new Point(10, 20))
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [plugin],
|
||||
}
|
||||
const Pattern = new Design({ plugins: [plugin], parts: [part] })
|
||||
const Pattern = new Design({ parts: [part] })
|
||||
const pattern = new Pattern()
|
||||
pattern.draft().render()
|
||||
const c = pattern.svg
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue