chore(plugin-annotations): Refactor plugin structure
This commit is contained in:
parent
607bc010da
commit
94d8ae4cab
11 changed files with 611 additions and 706 deletions
|
@ -1,5 +1,3 @@
|
||||||
import { version, name } from '../data.mjs'
|
|
||||||
|
|
||||||
// Method that draws the actual bartack
|
// Method that draws the actual bartack
|
||||||
const drawBartack = (pointList, { Path }) => {
|
const drawBartack = (pointList, { Path }) => {
|
||||||
let path = new Path().move(pointList.path1[0])
|
let path = new Path().move(pointList.path1[0])
|
||||||
|
@ -102,33 +100,25 @@ function createBartack(so, props) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actual plugin
|
// Export macros
|
||||||
export const bartack = {
|
export const bartackMacros = {
|
||||||
name,
|
bartack: function (so, props) {
|
||||||
version,
|
return createBartack(so, props)
|
||||||
macros: {
|
},
|
||||||
bartack: function (so, props) {
|
bartackAlong: function (so, props) {
|
||||||
return createBartack(so, props)
|
so.bartackFractionAlong = false
|
||||||
},
|
so.bartackAlong = true
|
||||||
bartackAlong: function (so, props) {
|
so.anchor = false
|
||||||
so.bartackFractionAlong = false
|
so.from = false
|
||||||
so.bartackAlong = true
|
so.to = false
|
||||||
so.anchor = false
|
return createBartack(so, props)
|
||||||
so.from = false
|
},
|
||||||
so.to = false
|
bartackFractionAlong: function (so, props) {
|
||||||
return createBartack(so, props)
|
so.bartackFractionAlong = true
|
||||||
},
|
so.bartackAlong = false
|
||||||
bartackFractionAlong: function (so, props) {
|
so.anchor = false
|
||||||
so.bartackFractionAlong = true
|
so.from = false
|
||||||
so.bartackAlong = false
|
so.to = false
|
||||||
so.anchor = false
|
return createBartack(so, props)
|
||||||
so.from = false
|
|
||||||
so.to = false
|
|
||||||
return createBartack(so, props)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const bartackPlugin = bartack
|
|
||||||
export const pluginBartack = bartack
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { name, version } from '../data.mjs'
|
|
||||||
|
|
||||||
const defs = [
|
const defs = [
|
||||||
// button
|
// button
|
||||||
`
|
`
|
||||||
|
@ -65,18 +63,13 @@ const defs = [
|
||||||
</g>`,
|
</g>`,
|
||||||
]
|
]
|
||||||
|
|
||||||
export const buttons = {
|
// Export hooks
|
||||||
name,
|
export const buttonsHooks = {
|
||||||
version,
|
preRender: [
|
||||||
hooks: {
|
function (svg) {
|
||||||
preRender: function (svg) {
|
|
||||||
for (const def of defs) {
|
for (const def of defs) {
|
||||||
if (svg.defs.indexOf(def) === -1) svg.defs += def
|
if (svg.defs.indexOf(def) === -1) svg.defs += def
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const buttonsPlugin = buttons
|
|
||||||
export const pluginButtons = buttons
|
|
||||||
|
|
|
@ -1,62 +1,53 @@
|
||||||
import { name, version } from '../data.mjs'
|
// Export macros
|
||||||
|
export const crossboxMacros = {
|
||||||
|
crossbox: function (so, { points, Point, paths, Path, getId }) {
|
||||||
|
let id = getId()
|
||||||
|
let shiftFraction = 0.1
|
||||||
|
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)
|
||||||
|
|
||||||
export const crossbox = {
|
points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards(
|
||||||
name: 'crossbox',
|
points[id + '_boxBottomRight'],
|
||||||
version,
|
shiftFraction
|
||||||
macros: {
|
)
|
||||||
crossbox: function (so, { points, Point, paths, Path, getId }) {
|
points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards(
|
||||||
let id = getId()
|
points[id + '_boxBottomLeft'],
|
||||||
let shiftFraction = 0.1
|
shiftFraction
|
||||||
points[id + '_boxTopLeft'] = so.from.copy()
|
)
|
||||||
points[id + '_boxBottomRight'] = so.to.copy()
|
points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards(
|
||||||
points[id + '_boxTopRight'] = new Point(so.to.x, so.from.y)
|
points[id + '_boxTopRight'],
|
||||||
points[id + '_boxBottomLeft'] = new Point(so.from.x, so.to.y)
|
shiftFraction
|
||||||
|
)
|
||||||
|
points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards(
|
||||||
|
points[id + '_boxTopLeft'],
|
||||||
|
shiftFraction
|
||||||
|
)
|
||||||
|
|
||||||
points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards(
|
paths[id + 'crossBox'] = new Path()
|
||||||
points[id + '_boxBottomRight'],
|
.move(points[id + '_boxTopLeft'])
|
||||||
shiftFraction
|
.line(points[id + '_boxTopRight'])
|
||||||
)
|
.line(points[id + '_boxBottomRight'])
|
||||||
points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards(
|
.line(points[id + '_boxBottomLeft'])
|
||||||
points[id + '_boxBottomLeft'],
|
.line(points[id + '_boxTopLeft'])
|
||||||
shiftFraction
|
.close()
|
||||||
)
|
.attr('class', 'lining dotted stroke-sm')
|
||||||
points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards(
|
paths[id + '_topCross'] = new Path()
|
||||||
points[id + '_boxTopRight'],
|
.move(points[id + '_topCrossTL'])
|
||||||
shiftFraction
|
.line(points[id + '_topCrossBR'])
|
||||||
)
|
.line(points[id + '_topCrossTR'])
|
||||||
points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards(
|
.line(points[id + '_topCrossBL'])
|
||||||
points[id + '_boxTopLeft'],
|
.line(points[id + '_topCrossTL'])
|
||||||
shiftFraction
|
.line(points[id + '_topCrossTR'])
|
||||||
)
|
.move(points[id + '_topCrossBR'])
|
||||||
|
.line(points[id + '_topCrossBL'])
|
||||||
paths[id + 'crossBox'] = new Path()
|
.attr('class', 'lining dotted stroke-sm')
|
||||||
.move(points[id + '_boxTopLeft'])
|
if (typeof so.text === 'string') {
|
||||||
.line(points[id + '_boxTopRight'])
|
points.textAnchor = points[id + '_boxTopLeft']
|
||||||
.line(points[id + '_boxBottomRight'])
|
.shiftFractionTowards(points[id + '_boxBottomRight'], 0.5)
|
||||||
.line(points[id + '_boxBottomLeft'])
|
.attr('data-text', so.text)
|
||||||
.line(points[id + '_boxTopLeft'])
|
.attr('data-text-class', 'center')
|
||||||
.close()
|
}
|
||||||
.attr('class', 'lining dotted stroke-sm')
|
|
||||||
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') {
|
|
||||||
points.textAnchor = points[id + '_boxTopLeft']
|
|
||||||
.shiftFractionTowards(points[id + '_boxBottomRight'], 0.5)
|
|
||||||
.attr('data-text', so.text)
|
|
||||||
.attr('data-text-class', 'center')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const crossboxPlugin = crossbox
|
|
||||||
export const pluginCrossbox = crossbox
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { name, version } from '../data.mjs'
|
|
||||||
|
|
||||||
const markers = `
|
const markers = `
|
||||||
<marker orient="auto" refY="4.0" refX="0.0" id="cutonfoldFrom" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
<marker orient="auto" refY="4.0" refX="0.0" id="cutonfoldFrom" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
||||||
<path class="note fill-note" d="M 0,4 L 12,0 C 10,2 10,6 12,8 z" />
|
<path class="note fill-note" d="M 0,4 L 12,0 C 10,2 10,6 12,8 z" />
|
||||||
|
@ -9,63 +7,59 @@ const markers = `
|
||||||
</marker>
|
</marker>
|
||||||
`
|
`
|
||||||
|
|
||||||
export const cutonfold = {
|
// Export hooks
|
||||||
name,
|
export const cutonfoldHooks = {
|
||||||
version,
|
preRender: [
|
||||||
hooks: {
|
function (svg) {
|
||||||
preRender: (svg) => {
|
|
||||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
macros: {
|
}
|
||||||
cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, scale }) {
|
// Export macros
|
||||||
if (so === false) {
|
export const cutonfoldMacros = {
|
||||||
delete points.cutonfoldFrom
|
cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, scale }) {
|
||||||
delete points.cutonfoldTo
|
if (so === false) {
|
||||||
delete points.cutonfoldVia1
|
delete points.cutonfoldFrom
|
||||||
delete points.cutonfoldVia2
|
delete points.cutonfoldTo
|
||||||
delete paths.cutonfold
|
delete points.cutonfoldVia1
|
||||||
// setCutOnFold relies on plugin-cutlist
|
delete points.cutonfoldVia2
|
||||||
if (typeof setCutOnFold === 'function') {
|
delete paths.cutonfold
|
||||||
setCutOnFold(false) // Restore default
|
// setCutOnFold relies on plugin-cutlist
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
so = {
|
|
||||||
offset: 15,
|
|
||||||
margin: 5,
|
|
||||||
prefix: 'cutonfold',
|
|
||||||
...so,
|
|
||||||
}
|
|
||||||
if (typeof setCutOnFold === 'function') {
|
if (typeof setCutOnFold === 'function') {
|
||||||
setCutOnFold(so.from, so.to)
|
setCutOnFold(false) // Restore default
|
||||||
if (so.grainline) setGrain(so.from.angle(so.to))
|
|
||||||
}
|
}
|
||||||
if (complete) {
|
return true
|
||||||
points[so.prefix + 'From'] = so.from.shiftFractionTowards(so.to, so.margin / 100)
|
}
|
||||||
points[so.prefix + 'To'] = so.to.shiftFractionTowards(so.from, so.margin / 100)
|
so = {
|
||||||
points[so.prefix + 'Via1'] = points[so.prefix + 'From']
|
offset: 15,
|
||||||
.shiftTowards(so.from, so.offset * scale)
|
margin: 5,
|
||||||
.rotate(-90, points[so.prefix + 'From'])
|
prefix: 'cutonfold',
|
||||||
points[so.prefix + 'Via2'] = points[so.prefix + 'To']
|
...so,
|
||||||
.shiftTowards(so.to, so.offset * scale)
|
}
|
||||||
.rotate(90, points[so.prefix + 'To'])
|
if (typeof setCutOnFold === 'function') {
|
||||||
const text = so.grainline ? 'cutOnFoldAndGrainline' : 'cutOnFold'
|
setCutOnFold(so.from, so.to)
|
||||||
paths[so.prefix + 'Cutonfold'] = new Path()
|
if (so.grainline) setGrain(so.from.angle(so.to))
|
||||||
.move(points[so.prefix + 'From'])
|
}
|
||||||
.line(points[so.prefix + 'Via1'])
|
if (complete) {
|
||||||
.line(points[so.prefix + 'Via2'])
|
points[so.prefix + 'From'] = so.from.shiftFractionTowards(so.to, so.margin / 100)
|
||||||
.line(points[so.prefix + 'To'])
|
points[so.prefix + 'To'] = so.to.shiftFractionTowards(so.from, so.margin / 100)
|
||||||
.attr('class', 'note')
|
points[so.prefix + 'Via1'] = points[so.prefix + 'From']
|
||||||
.attr('marker-start', 'url(#cutonfoldFrom)')
|
.shiftTowards(so.from, so.offset * scale)
|
||||||
.attr('marker-end', 'url(#cutonfoldTo)')
|
.rotate(-90, points[so.prefix + 'From'])
|
||||||
.attr('data-text', text)
|
points[so.prefix + 'Via2'] = points[so.prefix + 'To']
|
||||||
.attr('data-text-class', 'center fill-note')
|
.shiftTowards(so.to, so.offset * scale)
|
||||||
}
|
.rotate(90, points[so.prefix + 'To'])
|
||||||
},
|
const text = so.grainline ? 'cutOnFoldAndGrainline' : 'cutOnFold'
|
||||||
|
paths[so.prefix + 'Cutonfold'] = new Path()
|
||||||
|
.move(points[so.prefix + 'From'])
|
||||||
|
.line(points[so.prefix + 'Via1'])
|
||||||
|
.line(points[so.prefix + 'Via2'])
|
||||||
|
.line(points[so.prefix + 'To'])
|
||||||
|
.attr('class', 'note')
|
||||||
|
.attr('marker-start', 'url(#cutonfoldFrom)')
|
||||||
|
.attr('marker-end', 'url(#cutonfoldTo)')
|
||||||
|
.attr('data-text', text)
|
||||||
|
.attr('data-text-class', 'center fill-note')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const cutonfoldPlugin = cutonfold
|
|
||||||
export const pluginCutonfold = cutonfold
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { name, version } from '../data.mjs'
|
|
||||||
|
|
||||||
const markers = `
|
const markers = `
|
||||||
<marker orient="auto" refY="4.0" refX="10.0" id="grainlineFrom" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
<marker orient="auto" refY="4.0" refX="10.0" id="grainlineFrom" style="overflow:visible;" markerWidth="12" markerHeight="8">
|
||||||
<path class="note fill-note" d="M 0,4 L 12,0 C 10,2 10,6 12,8 z" />
|
<path class="note fill-note" d="M 0,4 L 12,0 C 10,2 10,6 12,8 z" />
|
||||||
|
@ -10,47 +8,42 @@ const markers = `
|
||||||
|
|
||||||
const dflts = { text: 'grainline' }
|
const dflts = { text: 'grainline' }
|
||||||
|
|
||||||
export const grainline = {
|
// Export hooks and macros
|
||||||
name,
|
export const grainlineHooks = {
|
||||||
version,
|
preRender: [
|
||||||
hooks: {
|
function (svg) {
|
||||||
preRender: (svg) => {
|
|
||||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
macros: {
|
}
|
||||||
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
|
export const grainlineMacros = {
|
||||||
if (so === false) {
|
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
|
||||||
delete points.grainlineFrom
|
if (so === false) {
|
||||||
delete points.grainlineTo
|
delete points.grainlineFrom
|
||||||
delete paths.grainline
|
delete points.grainlineTo
|
||||||
setGrain(90) // Restoring default
|
delete paths.grainline
|
||||||
return true
|
setGrain(90) // Restoring default
|
||||||
}
|
return true
|
||||||
so = {
|
}
|
||||||
...dflts,
|
so = {
|
||||||
...so,
|
...dflts,
|
||||||
}
|
...so,
|
||||||
// setGrain relies on plugin-cutlist
|
}
|
||||||
if (typeof setGrain === 'function') {
|
// setGrain relies on plugin-cutlist
|
||||||
setGrain(so.from.angle(so.to))
|
if (typeof setGrain === 'function') {
|
||||||
}
|
setGrain(so.from.angle(so.to))
|
||||||
if (complete) {
|
}
|
||||||
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
|
if (complete) {
|
||||||
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
|
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
|
||||||
paths.grainline = new Path()
|
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
|
||||||
.move(points.grainlineFrom)
|
paths.grainline = new Path()
|
||||||
.line(points.grainlineTo)
|
.move(points.grainlineFrom)
|
||||||
.attr('class', 'note')
|
.line(points.grainlineTo)
|
||||||
.attr('marker-start', 'url(#grainlineFrom)')
|
.attr('class', 'note')
|
||||||
.attr('marker-end', 'url(#grainlineTo)')
|
.attr('marker-start', 'url(#grainlineFrom)')
|
||||||
.attr('data-text', so.text)
|
.attr('marker-end', 'url(#grainlineTo)')
|
||||||
.attr('data-text-class', 'center fill-note')
|
.attr('data-text', so.text)
|
||||||
}
|
.attr('data-text-class', 'center fill-note')
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const grainlinePlugin = grainline
|
|
||||||
export const pluginGrainline = grainline
|
|
||||||
|
|
|
@ -1,59 +1,41 @@
|
||||||
import { name, version } from '../data.mjs'
|
import { name, version } from '../data.mjs'
|
||||||
|
// Hooks only
|
||||||
import { bartackPlugin } from './bartack.mjs'
|
import { buttonsHooks } from './buttons.mjs'
|
||||||
import { buttonsPlugin } from './buttons.mjs'
|
import { logoHooks } from './logo.mjs'
|
||||||
import { crossboxPlugin } from './crossbox.mjs'
|
import { notchesHooks } from './notches.mjs'
|
||||||
import { cutonfoldPlugin } from './cutonfold.mjs'
|
// Macros only
|
||||||
import { grainlinePlugin } from './grainline.mjs'
|
import { bartackMacros } from './bartack.mjs'
|
||||||
import { logoPlugin } from './logo.mjs'
|
import { crossboxMacros } from './crossbox.mjs'
|
||||||
import { notchesPlugin } from './notches.mjs'
|
import { scaleboxMacros } from './scalebox.mjs'
|
||||||
import { pleatPlugin } from './pleat.mjs'
|
// Hooks and Macros
|
||||||
import { scaleboxPlugin } from './scalebox.mjs'
|
import { cutonfoldMacros, cutonfoldHooks } from './cutonfold.mjs'
|
||||||
import { sewtogetherPlugin } from './sewtogether.mjs'
|
import { grainlineMacros, grainlineHooks } from './grainline.mjs'
|
||||||
|
import { pleatMacros, pleatHooks } from './pleat.mjs'
|
||||||
const annotationPlugins = [
|
import { sewtogetherMacros, sewtogetherHooks } from './sewtogether.mjs'
|
||||||
bartackPlugin,
|
|
||||||
buttonsPlugin,
|
|
||||||
crossboxPlugin,
|
|
||||||
cutonfoldPlugin,
|
|
||||||
grainlinePlugin,
|
|
||||||
logoPlugin,
|
|
||||||
notchesPlugin,
|
|
||||||
pleatPlugin,
|
|
||||||
scaleboxPlugin,
|
|
||||||
sewtogetherPlugin,
|
|
||||||
]
|
|
||||||
|
|
||||||
function annotationHooks() {
|
|
||||||
const hooks = {}
|
|
||||||
for (const plugin of annotationPlugins) {
|
|
||||||
for (const i in plugin.hooks) {
|
|
||||||
if (typeof hooks[i] === 'undefined') hooks[i] = []
|
|
||||||
const hook = plugin.hooks[i]
|
|
||||||
if (typeof hook === 'function') hooks[i].push(hook)
|
|
||||||
else if (typeof hook === 'object') {
|
|
||||||
for (let method of hook) hooks[i].push(method)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hooks
|
|
||||||
}
|
|
||||||
|
|
||||||
function annotationMacros() {
|
|
||||||
const macros = {}
|
|
||||||
for (const plugin of annotationPlugins) {
|
|
||||||
for (const i in plugin.macros) macros[i] = plugin.macros[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
return macros
|
|
||||||
}
|
|
||||||
|
|
||||||
export const plugin = {
|
export const plugin = {
|
||||||
name,
|
name,
|
||||||
version,
|
version,
|
||||||
hooks: annotationHooks(),
|
hooks: {
|
||||||
macros: annotationMacros(),
|
preRender: [
|
||||||
|
...buttonsHooks.preRender,
|
||||||
|
...logoHooks.preRender,
|
||||||
|
...notchesHooks.preRender,
|
||||||
|
...cutonfoldHooks.preRender,
|
||||||
|
...grainlineHooks.preRender,
|
||||||
|
...pleatHooks.preRender,
|
||||||
|
...sewtogetherHooks.preRender,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
macros: {
|
||||||
|
...bartackMacros,
|
||||||
|
...crossboxMacros,
|
||||||
|
...scaleboxMacros,
|
||||||
|
...cutonfoldMacros,
|
||||||
|
...grainlineMacros,
|
||||||
|
...pleatMacros,
|
||||||
|
...sewtogetherMacros,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const annotationPlugin = plugin
|
export const annotationPlugin = plugin
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,3 @@
|
||||||
import { name, version } from '../data.mjs'
|
|
||||||
|
|
||||||
const markers = `
|
const markers = `
|
||||||
<g id="notch">
|
<g id="notch">
|
||||||
<circle cy="0" cx="0" r="1.4" class="fill-note" />
|
<circle cy="0" cx="0" r="1.4" class="fill-note" />
|
||||||
|
@ -10,16 +8,11 @@ const markers = `
|
||||||
<circle cy="0" cx="0" r="2.8" class="note" />
|
<circle cy="0" cx="0" r="2.8" class="note" />
|
||||||
</g>`
|
</g>`
|
||||||
|
|
||||||
export const notches = {
|
// Export hooks
|
||||||
name,
|
export const notchesHooks = {
|
||||||
version,
|
preRender: [
|
||||||
hooks: {
|
function (svg) {
|
||||||
preRender: function (svg) {
|
|
||||||
if (svg.defs.indexOf(`id="notch"`) === -1) svg.defs += markers
|
if (svg.defs.indexOf(`id="notch"`) === -1) svg.defs += markers
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const notchesPlugin = notches
|
|
||||||
export const pluginNotches = notches
|
|
||||||
|
|
|
@ -1,76 +1,71 @@
|
||||||
import { name, version } from '../data.mjs'
|
|
||||||
|
|
||||||
const markers = `
|
const markers = `
|
||||||
<marker id="pleatTo" markerWidth="12" markerHeight="8" orient="auto" refY="4" refX="12">
|
<marker id="pleatTo" markerWidth="12" markerHeight="8" orient="auto" refY="4" refX="12">
|
||||||
<path class="note fill-note" d="M 12,4 L 0,0 C 2,2 2,6 0,8 z" />
|
<path class="note fill-note" d="M 12,4 L 0,0 C 2,2 2,6 0,8 z" />
|
||||||
</marker>
|
</marker>
|
||||||
`
|
`
|
||||||
|
|
||||||
export const pleat = {
|
// Export hooks
|
||||||
name,
|
export const pleatHooks = {
|
||||||
version,
|
preRender: [
|
||||||
hooks: {
|
function (svg) {
|
||||||
preRender: (svg) => {
|
|
||||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
macros: {
|
|
||||||
pleat: function (so, { points, paths, Path, complete, scale }) {
|
|
||||||
if (so === false) {
|
|
||||||
delete points.pleatFrom
|
|
||||||
delete points.pleatFromIn
|
|
||||||
delete points.pleatTo
|
|
||||||
delete points.pleatToIn
|
|
||||||
delete paths.pleatTo
|
|
||||||
delete paths.pleatFrom
|
|
||||||
delete paths.pleatArrow
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
so = {
|
|
||||||
margin: 35,
|
|
||||||
prefix: 'pleat',
|
|
||||||
reverse: false,
|
|
||||||
...so,
|
|
||||||
}
|
|
||||||
if (complete) {
|
|
||||||
points[so.prefix + 'From'] = so.from
|
|
||||||
points[so.prefix + 'To'] = so.to
|
|
||||||
points[so.prefix + 'FromIn'] = points[so.prefix + 'From'].shift(
|
|
||||||
so.from.shiftTowards(so.to, 0.1).angle(so.from) + 270,
|
|
||||||
so.margin * scale
|
|
||||||
)
|
|
||||||
points[so.prefix + 'ToIn'] = points[so.prefix + 'To'].shift(
|
|
||||||
so.from.shiftTowards(so.to, 0.1).angle(so.to) + 90,
|
|
||||||
so.margin * scale
|
|
||||||
)
|
|
||||||
paths[so.prefix + 'PleatFrom'] = new Path()
|
|
||||||
.move(points[so.prefix + 'From'])
|
|
||||||
.line(points[so.prefix + 'FromIn'])
|
|
||||||
.attr('class', 'note' + (so.reverse ? ' dashed' : ''))
|
|
||||||
paths[so.prefix + 'PleatTo'] = new Path()
|
|
||||||
.move(points[so.prefix + 'To'])
|
|
||||||
.line(points[so.prefix + 'ToIn'])
|
|
||||||
.attr('class', 'note' + (so.reverse ? '' : ' dashed'))
|
|
||||||
paths[so.prefix + 'PleatArrow'] = new Path()
|
|
||||||
.move(
|
|
||||||
points[so.prefix + (so.reverse ? 'To' : 'From')].shiftFractionTowards(
|
|
||||||
points[so.prefix + (so.reverse ? 'ToIn' : 'FromIn')],
|
|
||||||
0.25
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.line(
|
|
||||||
points[so.prefix + (so.reverse ? 'From' : 'To')].shiftFractionTowards(
|
|
||||||
points[so.prefix + (so.reverse ? 'FromIn' : 'ToIn')],
|
|
||||||
0.25
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.attr('class', 'note')
|
|
||||||
.attr('marker-end', 'url(#pleatTo)')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
// Export macros
|
||||||
export const pleatPlugin = pleat
|
export const pleatMacros = {
|
||||||
export const pluginPleat = pleat
|
pleat: function (so, { points, paths, Path, complete, scale }) {
|
||||||
|
if (so === false) {
|
||||||
|
delete points.pleatFrom
|
||||||
|
delete points.pleatFromIn
|
||||||
|
delete points.pleatTo
|
||||||
|
delete points.pleatToIn
|
||||||
|
delete paths.pleatTo
|
||||||
|
delete paths.pleatFrom
|
||||||
|
delete paths.pleatArrow
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
so = {
|
||||||
|
margin: 35,
|
||||||
|
prefix: 'pleat',
|
||||||
|
reverse: false,
|
||||||
|
...so,
|
||||||
|
}
|
||||||
|
if (complete) {
|
||||||
|
points[so.prefix + 'From'] = so.from
|
||||||
|
points[so.prefix + 'To'] = so.to
|
||||||
|
points[so.prefix + 'FromIn'] = points[so.prefix + 'From'].shift(
|
||||||
|
so.from.shiftTowards(so.to, 0.1).angle(so.from) + 270,
|
||||||
|
so.margin * scale
|
||||||
|
)
|
||||||
|
points[so.prefix + 'ToIn'] = points[so.prefix + 'To'].shift(
|
||||||
|
so.from.shiftTowards(so.to, 0.1).angle(so.to) + 90,
|
||||||
|
so.margin * scale
|
||||||
|
)
|
||||||
|
paths[so.prefix + 'PleatFrom'] = new Path()
|
||||||
|
.move(points[so.prefix + 'From'])
|
||||||
|
.line(points[so.prefix + 'FromIn'])
|
||||||
|
.attr('class', 'note' + (so.reverse ? ' dashed' : ''))
|
||||||
|
paths[so.prefix + 'PleatTo'] = new Path()
|
||||||
|
.move(points[so.prefix + 'To'])
|
||||||
|
.line(points[so.prefix + 'ToIn'])
|
||||||
|
.attr('class', 'note' + (so.reverse ? '' : ' dashed'))
|
||||||
|
paths[so.prefix + 'PleatArrow'] = new Path()
|
||||||
|
.move(
|
||||||
|
points[so.prefix + (so.reverse ? 'To' : 'From')].shiftFractionTowards(
|
||||||
|
points[so.prefix + (so.reverse ? 'ToIn' : 'FromIn')],
|
||||||
|
0.25
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.line(
|
||||||
|
points[so.prefix + (so.reverse ? 'From' : 'To')].shiftFractionTowards(
|
||||||
|
points[so.prefix + (so.reverse ? 'FromIn' : 'ToIn')],
|
||||||
|
0.25
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.attr('class', 'note')
|
||||||
|
.attr('marker-end', 'url(#pleatTo)')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
|
@ -1,297 +1,282 @@
|
||||||
import { name, version } from '../data.mjs'
|
// Export macros
|
||||||
|
export const scaleboxMacros = {
|
||||||
|
scalebox: function (so, { store, points, paths, scale, Point, Path }) {
|
||||||
|
// Passing `false` will remove the scalebox
|
||||||
|
if (so === false) {
|
||||||
|
for (let id of [
|
||||||
|
'__scaleboxMetricTopLeft',
|
||||||
|
'__scaleboxMetricTopRight',
|
||||||
|
'__scaleboxMetricBottomRight',
|
||||||
|
'__scaleboxMetricBottomLeft',
|
||||||
|
'__scaleboxImperialTopLeft',
|
||||||
|
'__scaleboxImperialTopRight',
|
||||||
|
'__scaleboxImperialBottomRight',
|
||||||
|
'__scaleboxImperialBottomLeft',
|
||||||
|
'__scaleboxLead',
|
||||||
|
'__scaleboxTitle',
|
||||||
|
'__scaleboxText',
|
||||||
|
'__scaleboxLink',
|
||||||
|
'__scaleboxMetric',
|
||||||
|
'__scaleboxImperial',
|
||||||
|
])
|
||||||
|
delete points[id]
|
||||||
|
for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
const markers = `
|
// Convert scale to a value between 0 and 9, inclusive.
|
||||||
<marker id="pleatTo" markerWidth="12" markerHeight="8" orient="auto" refY="4" refX="12">
|
const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1
|
||||||
<path class="note fill-note" d="M 12,4 L 0,0 C 2,2 2,6 0,8 z" />
|
|
||||||
</marker>
|
|
||||||
`
|
|
||||||
|
|
||||||
export const scalebox = {
|
// Metric width and height in mm and display width and height for each scale index.
|
||||||
name,
|
const metricSizes = [
|
||||||
version,
|
[10, 5, '1cm', '0.5cm'],
|
||||||
macros: {
|
[20, 10, '2cm', '1cm'],
|
||||||
scalebox: function (so, { store, points, paths, scale, Point, Path }) {
|
[30, 15, '3cm', '1.5cm'],
|
||||||
// Passing `false` will remove the scalebox
|
[40, 20, '4cm', '2cm'],
|
||||||
if (so === false) {
|
[50, 25, '5cm', '2.5cm'],
|
||||||
for (let id of [
|
[60, 30, '6cm', '3cm'],
|
||||||
'__scaleboxMetricTopLeft',
|
[70, 35, '7cm', '3.5cm'],
|
||||||
'__scaleboxMetricTopRight',
|
[80, 40, '8cm', '4cm'],
|
||||||
'__scaleboxMetricBottomRight',
|
[90, 45, '9cm', '4.5cm'],
|
||||||
'__scaleboxMetricBottomLeft',
|
[100, 50, '10cm', '5cm'],
|
||||||
'__scaleboxImperialTopLeft',
|
]
|
||||||
'__scaleboxImperialTopRight',
|
|
||||||
'__scaleboxImperialBottomRight',
|
|
||||||
'__scaleboxImperialBottomLeft',
|
|
||||||
'__scaleboxLead',
|
|
||||||
'__scaleboxTitle',
|
|
||||||
'__scaleboxText',
|
|
||||||
'__scaleboxLink',
|
|
||||||
'__scaleboxMetric',
|
|
||||||
'__scaleboxImperial',
|
|
||||||
])
|
|
||||||
delete points[id]
|
|
||||||
for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id]
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert scale to a value between 0 and 9, inclusive.
|
const metricWidth = metricSizes[scaleIndex][0]
|
||||||
const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1
|
const metricHeight = metricSizes[scaleIndex][1]
|
||||||
|
const metricDisplayWidth = metricSizes[scaleIndex][2]
|
||||||
|
const metricDisplayHeight = metricSizes[scaleIndex][3]
|
||||||
|
|
||||||
// Metric width and height in mm and display width and height for each scale index.
|
// Imperial width and height in mm and display width and heigth for each scale index.
|
||||||
const metricSizes = [
|
const imperialSizes = [
|
||||||
[10, 5, '1cm', '0.5cm'],
|
[25.4 * 0.5, 25.4 * 0.25, '½″', '¼″'],
|
||||||
[20, 10, '2cm', '1cm'],
|
[25.4 * 0.875, 25.4 * 0.5, '⅞″', '½″'],
|
||||||
[30, 15, '3cm', '1.5cm'],
|
[25.4 * 1.25, 25.4 * 0.625, '1 ¼″', '⅝″'],
|
||||||
[40, 20, '4cm', '2cm'],
|
[25.4 * 1.625, 25.4 * 0.875, '1 ⅝″', '⅞″'],
|
||||||
[50, 25, '5cm', '2.5cm'],
|
[25.4 * 2, 25.4 * 1, '2″', '1″'],
|
||||||
[60, 30, '6cm', '3cm'],
|
[25.4 * 2.375, 25.4 * 1.25, '2 ⅜″', '1 ¼″'],
|
||||||
[70, 35, '7cm', '3.5cm'],
|
[25.4 * 2.875, 25.4 * 1.5, '2 ⅞″', '1 ½″'],
|
||||||
[80, 40, '8cm', '4cm'],
|
[25.4 * 3.25, 25.4 * 1.625, '3 ¼″', '1 ⅝″'],
|
||||||
[90, 45, '9cm', '4.5cm'],
|
[25.4 * 3.625, 25.4 * 1.875, '3 ⅝″', '1 ⅞″'],
|
||||||
[100, 50, '10cm', '5cm'],
|
[25.4 * 4, 25.4 * 2, '4″', '2″'],
|
||||||
|
]
|
||||||
|
|
||||||
|
const imperialWidth = imperialSizes[scaleIndex][0]
|
||||||
|
const imperialHeight = imperialSizes[scaleIndex][1]
|
||||||
|
const imperialDisplayWidth = imperialSizes[scaleIndex][2]
|
||||||
|
const imperialDisplayHeight = imperialSizes[scaleIndex][3]
|
||||||
|
|
||||||
|
// Box points
|
||||||
|
points.__scaleboxMetricTopLeft = new Point(
|
||||||
|
so.at.x - metricWidth / 2,
|
||||||
|
so.at.y - metricHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxMetricTopRight = new Point(
|
||||||
|
so.at.x + metricWidth / 2,
|
||||||
|
so.at.y - metricHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxMetricBottomLeft = new Point(
|
||||||
|
so.at.x - metricWidth / 2,
|
||||||
|
so.at.y + metricHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxMetricBottomRight = new Point(
|
||||||
|
so.at.x + metricWidth / 2,
|
||||||
|
so.at.y + metricHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxImperialTopLeft = new Point(
|
||||||
|
so.at.x - imperialWidth / 2,
|
||||||
|
so.at.y - imperialHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxImperialTopRight = new Point(
|
||||||
|
so.at.x + imperialWidth / 2,
|
||||||
|
so.at.y - imperialHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxImperialBottomLeft = new Point(
|
||||||
|
so.at.x - imperialWidth / 2,
|
||||||
|
so.at.y + imperialHeight / 2
|
||||||
|
)
|
||||||
|
points.__scaleboxImperialBottomRight = new Point(
|
||||||
|
so.at.x + imperialWidth / 2,
|
||||||
|
so.at.y + imperialHeight / 2
|
||||||
|
)
|
||||||
|
// Text anchor points
|
||||||
|
points.__scaleboxLead = new Point(so.at.x - 45 * scale, so.at.y - 15 * scale)
|
||||||
|
points.__scaleboxTitle = points.__scaleboxLead.shift(-90, 10 * scale)
|
||||||
|
points.__scaleboxText = points.__scaleboxTitle.shift(-90, 12 * scale)
|
||||||
|
points.__scaleboxLink = points.__scaleboxText.shift(-90, 5 * scale)
|
||||||
|
points.__scaleboxMetric = new Point(so.at.x, so.at.y + 20 * scale)
|
||||||
|
points.__scaleboxImperial = new Point(so.at.x, so.at.y + 24 * scale)
|
||||||
|
// Rotation
|
||||||
|
if (so.rotate) {
|
||||||
|
so.rotate = Number(so.rotate)
|
||||||
|
let toRotate = [
|
||||||
|
'__scaleboxMetricTopLeft',
|
||||||
|
'__scaleboxMetricTopRight',
|
||||||
|
'__scaleboxMetricBottomLeft',
|
||||||
|
'__scaleboxMetricBottomRight',
|
||||||
|
'__scaleboxImperialTopLeft',
|
||||||
|
'__scaleboxImperialTopRight',
|
||||||
|
'__scaleboxImperialBottomLeft',
|
||||||
|
'__scaleboxImperialBottomRight',
|
||||||
|
'__scaleboxLead',
|
||||||
|
'__scaleboxTitle',
|
||||||
|
'__scaleboxText',
|
||||||
|
'__scaleboxLink',
|
||||||
|
'__scaleboxMetric',
|
||||||
|
'__scaleboxImperial',
|
||||||
]
|
]
|
||||||
|
for (let pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
||||||
|
for (let pid of toRotate.slice(8)) {
|
||||||
|
points[pid].attributes.set(
|
||||||
|
'data-text-transform',
|
||||||
|
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Paths
|
||||||
|
paths.__scaleboxImperial = new Path()
|
||||||
|
.attr('class', 'scalebox imperial fill-current')
|
||||||
|
.move(points.__scaleboxImperialTopLeft)
|
||||||
|
.line(points.__scaleboxImperialBottomLeft)
|
||||||
|
.line(points.__scaleboxImperialBottomRight)
|
||||||
|
.line(points.__scaleboxImperialTopRight)
|
||||||
|
.close()
|
||||||
|
paths.__scaleboxMetric = new Path()
|
||||||
|
.attr('class', 'scalebox metric fill-bg')
|
||||||
|
.move(points.__scaleboxMetricTopLeft)
|
||||||
|
.line(points.__scaleboxMetricBottomLeft)
|
||||||
|
.line(points.__scaleboxMetricBottomRight)
|
||||||
|
.line(points.__scaleboxMetricTopRight)
|
||||||
|
.close()
|
||||||
|
// Lead
|
||||||
|
points.__scaleboxLead = points.__scaleboxLead
|
||||||
|
.attr('data-text', so.lead || 'FreeSewing')
|
||||||
|
.attr('data-text-class', 'text-sm')
|
||||||
|
// Title
|
||||||
|
if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title)
|
||||||
|
else {
|
||||||
|
let name = store.data?.name || 'No Name'
|
||||||
|
if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '')
|
||||||
|
points.__scaleboxTitle = points.__scaleboxTitle
|
||||||
|
.attr('data-text', name)
|
||||||
|
.attr('data-text', 'v' + (store.data?.version || 'No Version'))
|
||||||
|
}
|
||||||
|
points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg')
|
||||||
|
// Text
|
||||||
|
if (typeof so.text === 'string') {
|
||||||
|
points.__scaleboxText.attr('data-text', so.text)
|
||||||
|
} else {
|
||||||
|
points.__scaleboxText.attr('data-text', 'supportFreesewingBecomeAPatron')
|
||||||
|
points.__scaleboxLink = points.__scaleboxLink
|
||||||
|
.attr('data-text', 'freesewing.org/patrons/join')
|
||||||
|
.attr('data-text-class', 'text-sm fill-note')
|
||||||
|
}
|
||||||
|
points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4)
|
||||||
|
// Instructions
|
||||||
|
points.__scaleboxMetric = points.__scaleboxMetric
|
||||||
|
.attr('data-text', 'theWhiteInsideOfThisBoxShouldMeasure')
|
||||||
|
.attr('data-text', `${metricDisplayWidth}`)
|
||||||
|
.attr('data-text', 'x')
|
||||||
|
.attr('data-text', `${metricDisplayHeight}`)
|
||||||
|
.attr('data-text-class', 'text-xs center')
|
||||||
|
points.__scaleboxImperial = points.__scaleboxImperial
|
||||||
|
.attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure')
|
||||||
|
.attr('data-text', `${imperialDisplayWidth}`)
|
||||||
|
.attr('data-text', 'x')
|
||||||
|
.attr('data-text', `${imperialDisplayHeight}`)
|
||||||
|
.attr('data-text-class', 'text-xs center ')
|
||||||
|
},
|
||||||
|
miniscale(so, { store, points, paths, scale, Point, Path }) {
|
||||||
|
// Passing `false` will remove the miniscale
|
||||||
|
if (so === false) {
|
||||||
|
for (const id of [
|
||||||
|
'__miniscaleMetricTopLeft',
|
||||||
|
'__miniscaleMetricTopRight',
|
||||||
|
'__miniscaleMetricBottomRight',
|
||||||
|
'__miniscaleMetricBottomLeft',
|
||||||
|
'__miniscaleImperialTopLeft',
|
||||||
|
'__miniscaleImperialTopRight',
|
||||||
|
'__miniscaleImperialBottomRight',
|
||||||
|
'__miniscaleImperialBottomLeft',
|
||||||
|
'__miniscaleMetric',
|
||||||
|
'__miniscaleImperial',
|
||||||
|
])
|
||||||
|
delete points[id]
|
||||||
|
for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
const metricWidth = metricSizes[scaleIndex][0]
|
// Convert scale to a value between 0 and 5, inclusive.
|
||||||
const metricHeight = metricSizes[scaleIndex][1]
|
const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, scale))) - 1
|
||||||
const metricDisplayWidth = metricSizes[scaleIndex][2]
|
|
||||||
const metricDisplayHeight = metricSizes[scaleIndex][3]
|
|
||||||
|
|
||||||
// Imperial width and height in mm and display width and heigth for each scale index.
|
// Metric size in mm / display value and imperial size in mm / display value for each scale index.
|
||||||
const imperialSizes = [
|
const sizes = [
|
||||||
[25.4 * 0.5, 25.4 * 0.25, '½″', '¼″'],
|
[10, '1cm', 25.4 * 0.375, '⅜″'],
|
||||||
[25.4 * 0.875, 25.4 * 0.5, '⅞″', '½″'],
|
[13, '1.3cm', 25.4 * 0.5, '½″'],
|
||||||
[25.4 * 1.25, 25.4 * 0.625, '1 ¼″', '⅝″'],
|
[16, '1.6cm', 25.4 * 0.625, '⅝″'],
|
||||||
[25.4 * 1.625, 25.4 * 0.875, '1 ⅝″', '⅞″'],
|
[19, '1.9cm', 25.4 * 0.75, '¾″'],
|
||||||
[25.4 * 2, 25.4 * 1, '2″', '1″'],
|
[22, '2.2cm', 25.4 * 0.875, '⅞″'],
|
||||||
[25.4 * 2.375, 25.4 * 1.25, '2 ⅜″', '1 ¼″'],
|
[25, '2.5cm', 25.4 * 1, '1″'],
|
||||||
[25.4 * 2.875, 25.4 * 1.5, '2 ⅞″', '1 ½″'],
|
]
|
||||||
[25.4 * 3.25, 25.4 * 1.625, '3 ¼″', '1 ⅝″'],
|
const m = sizes[scaleIndex][0] / 2
|
||||||
[25.4 * 3.625, 25.4 * 1.875, '3 ⅝″', '1 ⅞″'],
|
const i = sizes[scaleIndex][2] / 2
|
||||||
[25.4 * 4, 25.4 * 2, '4″', '2″'],
|
const metricDisplaySize = sizes[scaleIndex][1]
|
||||||
|
const imperialDisplaySize = sizes[scaleIndex][3]
|
||||||
|
// Box points
|
||||||
|
points.__miniscaleMetricTopLeft = new Point(so.at.x - m, so.at.y - m)
|
||||||
|
points.__miniscaleMetricTopRight = new Point(so.at.x + m, so.at.y - m)
|
||||||
|
points.__miniscaleMetricBottomLeft = new Point(so.at.x - m, so.at.y + m)
|
||||||
|
points.__miniscaleMetricBottomRight = new Point(so.at.x + m, so.at.y + m)
|
||||||
|
points.__miniscaleImperialTopLeft = new Point(so.at.x - i, so.at.y - i)
|
||||||
|
points.__miniscaleImperialTopRight = new Point(so.at.x + i, so.at.y - i)
|
||||||
|
points.__miniscaleImperialBottomLeft = new Point(so.at.x - i, so.at.y + i)
|
||||||
|
points.__miniscaleImperialBottomRight = new Point(so.at.x + i, so.at.y + i)
|
||||||
|
// Text anchor points
|
||||||
|
points.__miniscaleMetric = new Point(so.at.x, so.at.y - 2 * scale)
|
||||||
|
points.__miniscaleImperial = new Point(so.at.x, so.at.y + 8 * scale)
|
||||||
|
// Rotation
|
||||||
|
if (so.rotate) {
|
||||||
|
so.rotate = Number(so.rotate)
|
||||||
|
let toRotate = [
|
||||||
|
'__miniscaleMetricTopLeft',
|
||||||
|
'__miniscaleMetricTopRight',
|
||||||
|
'__miniscaleMetricBottomLeft',
|
||||||
|
'__miniscaleMetricBottomRight',
|
||||||
|
'__miniscaleImperialTopLeft',
|
||||||
|
'__miniscaleImperialTopRight',
|
||||||
|
'__miniscaleImperialBottomLeft',
|
||||||
|
'__miniscaleImperialBottomRight',
|
||||||
|
'__miniscaleMetric',
|
||||||
|
'__miniscaleImperial',
|
||||||
]
|
]
|
||||||
|
for (const pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
||||||
const imperialWidth = imperialSizes[scaleIndex][0]
|
for (const pid of toRotate.slice(8)) {
|
||||||
const imperialHeight = imperialSizes[scaleIndex][1]
|
points[pid].attributes.set(
|
||||||
const imperialDisplayWidth = imperialSizes[scaleIndex][2]
|
'data-text-transform',
|
||||||
const imperialDisplayHeight = imperialSizes[scaleIndex][3]
|
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
||||||
|
)
|
||||||
// Box points
|
|
||||||
points.__scaleboxMetricTopLeft = new Point(
|
|
||||||
so.at.x - metricWidth / 2,
|
|
||||||
so.at.y - metricHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxMetricTopRight = new Point(
|
|
||||||
so.at.x + metricWidth / 2,
|
|
||||||
so.at.y - metricHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxMetricBottomLeft = new Point(
|
|
||||||
so.at.x - metricWidth / 2,
|
|
||||||
so.at.y + metricHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxMetricBottomRight = new Point(
|
|
||||||
so.at.x + metricWidth / 2,
|
|
||||||
so.at.y + metricHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxImperialTopLeft = new Point(
|
|
||||||
so.at.x - imperialWidth / 2,
|
|
||||||
so.at.y - imperialHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxImperialTopRight = new Point(
|
|
||||||
so.at.x + imperialWidth / 2,
|
|
||||||
so.at.y - imperialHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxImperialBottomLeft = new Point(
|
|
||||||
so.at.x - imperialWidth / 2,
|
|
||||||
so.at.y + imperialHeight / 2
|
|
||||||
)
|
|
||||||
points.__scaleboxImperialBottomRight = new Point(
|
|
||||||
so.at.x + imperialWidth / 2,
|
|
||||||
so.at.y + imperialHeight / 2
|
|
||||||
)
|
|
||||||
// Text anchor points
|
|
||||||
points.__scaleboxLead = new Point(so.at.x - 45 * scale, so.at.y - 15 * scale)
|
|
||||||
points.__scaleboxTitle = points.__scaleboxLead.shift(-90, 10 * scale)
|
|
||||||
points.__scaleboxText = points.__scaleboxTitle.shift(-90, 12 * scale)
|
|
||||||
points.__scaleboxLink = points.__scaleboxText.shift(-90, 5 * scale)
|
|
||||||
points.__scaleboxMetric = new Point(so.at.x, so.at.y + 20 * scale)
|
|
||||||
points.__scaleboxImperial = new Point(so.at.x, so.at.y + 24 * scale)
|
|
||||||
// Rotation
|
|
||||||
if (so.rotate) {
|
|
||||||
so.rotate = Number(so.rotate)
|
|
||||||
let toRotate = [
|
|
||||||
'__scaleboxMetricTopLeft',
|
|
||||||
'__scaleboxMetricTopRight',
|
|
||||||
'__scaleboxMetricBottomLeft',
|
|
||||||
'__scaleboxMetricBottomRight',
|
|
||||||
'__scaleboxImperialTopLeft',
|
|
||||||
'__scaleboxImperialTopRight',
|
|
||||||
'__scaleboxImperialBottomLeft',
|
|
||||||
'__scaleboxImperialBottomRight',
|
|
||||||
'__scaleboxLead',
|
|
||||||
'__scaleboxTitle',
|
|
||||||
'__scaleboxText',
|
|
||||||
'__scaleboxLink',
|
|
||||||
'__scaleboxMetric',
|
|
||||||
'__scaleboxImperial',
|
|
||||||
]
|
|
||||||
for (let pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
|
||||||
for (let pid of toRotate.slice(8)) {
|
|
||||||
points[pid].attributes.set(
|
|
||||||
'data-text-transform',
|
|
||||||
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Paths
|
}
|
||||||
paths.__scaleboxImperial = new Path()
|
// Paths
|
||||||
.attr('class', 'scalebox imperial fill-current')
|
paths.__miniscaleImperial = new Path()
|
||||||
.move(points.__scaleboxImperialTopLeft)
|
.attr('class', 'scalebox imperial fill-current')
|
||||||
.line(points.__scaleboxImperialBottomLeft)
|
.move(points.__miniscaleImperialTopLeft)
|
||||||
.line(points.__scaleboxImperialBottomRight)
|
.line(points.__miniscaleImperialBottomLeft)
|
||||||
.line(points.__scaleboxImperialTopRight)
|
.line(points.__miniscaleImperialBottomRight)
|
||||||
.close()
|
.line(points.__miniscaleImperialTopRight)
|
||||||
paths.__scaleboxMetric = new Path()
|
.close()
|
||||||
.attr('class', 'scalebox metric fill-bg')
|
paths.__miniscaleMetric = new Path()
|
||||||
.move(points.__scaleboxMetricTopLeft)
|
.attr('class', 'scalebox metric fill-bg')
|
||||||
.line(points.__scaleboxMetricBottomLeft)
|
.move(points.__miniscaleMetricTopLeft)
|
||||||
.line(points.__scaleboxMetricBottomRight)
|
.line(points.__miniscaleMetricBottomLeft)
|
||||||
.line(points.__scaleboxMetricTopRight)
|
.line(points.__miniscaleMetricBottomRight)
|
||||||
.close()
|
.line(points.__miniscaleMetricTopRight)
|
||||||
// Lead
|
.close()
|
||||||
points.__scaleboxLead = points.__scaleboxLead
|
// Text
|
||||||
.attr('data-text', so.lead || 'FreeSewing')
|
points.__miniscaleMetric = points.__miniscaleMetric
|
||||||
.attr('data-text-class', 'text-sm')
|
.attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`)
|
||||||
// Title
|
.attr('data-text-class', 'text-xs center')
|
||||||
if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title)
|
points.__miniscaleImperial = points.__miniscaleImperial
|
||||||
else {
|
.attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`)
|
||||||
let name = store.data?.name || 'No Name'
|
.attr('data-text-class', 'text-xs center ')
|
||||||
if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '')
|
|
||||||
points.__scaleboxTitle = points.__scaleboxTitle
|
|
||||||
.attr('data-text', name)
|
|
||||||
.attr('data-text', 'v' + (store.data?.version || 'No Version'))
|
|
||||||
}
|
|
||||||
points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg')
|
|
||||||
// Text
|
|
||||||
if (typeof so.text === 'string') {
|
|
||||||
points.__scaleboxText.attr('data-text', so.text)
|
|
||||||
} else {
|
|
||||||
points.__scaleboxText.attr('data-text', 'supportFreesewingBecomeAPatron')
|
|
||||||
points.__scaleboxLink = points.__scaleboxLink
|
|
||||||
.attr('data-text', 'freesewing.org/patrons/join')
|
|
||||||
.attr('data-text-class', 'text-sm fill-note')
|
|
||||||
}
|
|
||||||
points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4)
|
|
||||||
// Instructions
|
|
||||||
points.__scaleboxMetric = points.__scaleboxMetric
|
|
||||||
.attr('data-text', 'theWhiteInsideOfThisBoxShouldMeasure')
|
|
||||||
.attr('data-text', `${metricDisplayWidth}`)
|
|
||||||
.attr('data-text', 'x')
|
|
||||||
.attr('data-text', `${metricDisplayHeight}`)
|
|
||||||
.attr('data-text-class', 'text-xs center')
|
|
||||||
points.__scaleboxImperial = points.__scaleboxImperial
|
|
||||||
.attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure')
|
|
||||||
.attr('data-text', `${imperialDisplayWidth}`)
|
|
||||||
.attr('data-text', 'x')
|
|
||||||
.attr('data-text', `${imperialDisplayHeight}`)
|
|
||||||
.attr('data-text-class', 'text-xs center ')
|
|
||||||
},
|
|
||||||
miniscale(so, { store, points, paths, scale, Point, Path }) {
|
|
||||||
// Passing `false` will remove the miniscale
|
|
||||||
if (so === false) {
|
|
||||||
for (const id of [
|
|
||||||
'__miniscaleMetricTopLeft',
|
|
||||||
'__miniscaleMetricTopRight',
|
|
||||||
'__miniscaleMetricBottomRight',
|
|
||||||
'__miniscaleMetricBottomLeft',
|
|
||||||
'__miniscaleImperialTopLeft',
|
|
||||||
'__miniscaleImperialTopRight',
|
|
||||||
'__miniscaleImperialBottomRight',
|
|
||||||
'__miniscaleImperialBottomLeft',
|
|
||||||
'__miniscaleMetric',
|
|
||||||
'__miniscaleImperial',
|
|
||||||
])
|
|
||||||
delete points[id]
|
|
||||||
for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id]
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert scale to a value between 0 and 5, inclusive.
|
|
||||||
const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, scale))) - 1
|
|
||||||
|
|
||||||
// Metric size in mm / display value and imperial size in mm / display value for each scale index.
|
|
||||||
const sizes = [
|
|
||||||
[10, '1cm', 25.4 * 0.375, '⅜″'],
|
|
||||||
[13, '1.3cm', 25.4 * 0.5, '½″'],
|
|
||||||
[16, '1.6cm', 25.4 * 0.625, '⅝″'],
|
|
||||||
[19, '1.9cm', 25.4 * 0.75, '¾″'],
|
|
||||||
[22, '2.2cm', 25.4 * 0.875, '⅞″'],
|
|
||||||
[25, '2.5cm', 25.4 * 1, '1″'],
|
|
||||||
]
|
|
||||||
const m = sizes[scaleIndex][0] / 2
|
|
||||||
const i = sizes[scaleIndex][2] / 2
|
|
||||||
const metricDisplaySize = sizes[scaleIndex][1]
|
|
||||||
const imperialDisplaySize = sizes[scaleIndex][3]
|
|
||||||
// Box points
|
|
||||||
points.__miniscaleMetricTopLeft = new Point(so.at.x - m, so.at.y - m)
|
|
||||||
points.__miniscaleMetricTopRight = new Point(so.at.x + m, so.at.y - m)
|
|
||||||
points.__miniscaleMetricBottomLeft = new Point(so.at.x - m, so.at.y + m)
|
|
||||||
points.__miniscaleMetricBottomRight = new Point(so.at.x + m, so.at.y + m)
|
|
||||||
points.__miniscaleImperialTopLeft = new Point(so.at.x - i, so.at.y - i)
|
|
||||||
points.__miniscaleImperialTopRight = new Point(so.at.x + i, so.at.y - i)
|
|
||||||
points.__miniscaleImperialBottomLeft = new Point(so.at.x - i, so.at.y + i)
|
|
||||||
points.__miniscaleImperialBottomRight = new Point(so.at.x + i, so.at.y + i)
|
|
||||||
// Text anchor points
|
|
||||||
points.__miniscaleMetric = new Point(so.at.x, so.at.y - 2 * scale)
|
|
||||||
points.__miniscaleImperial = new Point(so.at.x, so.at.y + 8 * scale)
|
|
||||||
// Rotation
|
|
||||||
if (so.rotate) {
|
|
||||||
so.rotate = Number(so.rotate)
|
|
||||||
let toRotate = [
|
|
||||||
'__miniscaleMetricTopLeft',
|
|
||||||
'__miniscaleMetricTopRight',
|
|
||||||
'__miniscaleMetricBottomLeft',
|
|
||||||
'__miniscaleMetricBottomRight',
|
|
||||||
'__miniscaleImperialTopLeft',
|
|
||||||
'__miniscaleImperialTopRight',
|
|
||||||
'__miniscaleImperialBottomLeft',
|
|
||||||
'__miniscaleImperialBottomRight',
|
|
||||||
'__miniscaleMetric',
|
|
||||||
'__miniscaleImperial',
|
|
||||||
]
|
|
||||||
for (const pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
|
|
||||||
for (const pid of toRotate.slice(8)) {
|
|
||||||
points[pid].attributes.set(
|
|
||||||
'data-text-transform',
|
|
||||||
`rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Paths
|
|
||||||
paths.__miniscaleImperial = new Path()
|
|
||||||
.attr('class', 'scalebox imperial fill-current')
|
|
||||||
.move(points.__miniscaleImperialTopLeft)
|
|
||||||
.line(points.__miniscaleImperialBottomLeft)
|
|
||||||
.line(points.__miniscaleImperialBottomRight)
|
|
||||||
.line(points.__miniscaleImperialTopRight)
|
|
||||||
.close()
|
|
||||||
paths.__miniscaleMetric = new Path()
|
|
||||||
.attr('class', 'scalebox metric fill-bg')
|
|
||||||
.move(points.__miniscaleMetricTopLeft)
|
|
||||||
.line(points.__miniscaleMetricBottomLeft)
|
|
||||||
.line(points.__miniscaleMetricBottomRight)
|
|
||||||
.line(points.__miniscaleMetricTopRight)
|
|
||||||
.close()
|
|
||||||
// Text
|
|
||||||
points.__miniscaleMetric = points.__miniscaleMetric
|
|
||||||
.attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`)
|
|
||||||
.attr('data-text-class', 'text-xs center')
|
|
||||||
points.__miniscaleImperial = points.__miniscaleImperial
|
|
||||||
.attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`)
|
|
||||||
.attr('data-text-class', 'text-xs center ')
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
|
||||||
export const scaleboxPlugin = scalebox
|
|
||||||
export const pluginScalebox = scalebox
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { name, version } from '../data.mjs'
|
|
||||||
|
|
||||||
const markers = `
|
const markers = `
|
||||||
<marker id="sewTogetherStart" markerWidth="4" markerHeight="4" orient="auto" refX="0" refY="2">
|
<marker id="sewTogetherStart" markerWidth="4" markerHeight="4" orient="auto" refX="0" refY="2">
|
||||||
<path class="note stroke-sm" d="M4,4 L0,2 4,0" />
|
<path class="note stroke-sm" d="M4,4 L0,2 4,0" />
|
||||||
|
@ -12,83 +10,80 @@ const markers = `
|
||||||
</marker>
|
</marker>
|
||||||
`
|
`
|
||||||
|
|
||||||
export const sewtogether = {
|
// Export hooks
|
||||||
name,
|
export const sewtogetherHooks = {
|
||||||
version,
|
preRender: [
|
||||||
hooks: {
|
function (svg) {
|
||||||
preRender: (svg) => {
|
|
||||||
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
if (svg.defs.indexOf(markers) === -1) svg.defs += markers
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
macros: {
|
|
||||||
sewtogether: function (so, { points, paths, Path, complete, scale, sa }) {
|
|
||||||
if (so === false) {
|
|
||||||
delete points.sewtogetherFrom
|
|
||||||
delete points.sewtogetherFromCp
|
|
||||||
delete points.sewtogetherMiddle
|
|
||||||
delete points.sewtogetherTo
|
|
||||||
delete points.sewtogetherHinge
|
|
||||||
delete points.sewtogetherToCp
|
|
||||||
delete paths.sewtogetherSewTogetherHinge
|
|
||||||
delete paths.sewtogetherSewTogether
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
so = {
|
|
||||||
prefix: 'sewtogether',
|
|
||||||
...so,
|
|
||||||
}
|
|
||||||
if (complete) {
|
|
||||||
if (null == so.middle) {
|
|
||||||
so.middle = so.from.shiftFractionTowards(so.to, 0.5)
|
|
||||||
}
|
|
||||||
points[so.prefix + 'From'] = so.from
|
|
||||||
points[so.prefix + 'Middle'] = so.middle
|
|
||||||
points[so.prefix + 'To'] = so.to
|
|
||||||
|
|
||||||
points[so.prefix + 'FromCp'] = points[so.prefix + 'From'].shift(
|
|
||||||
points[so.prefix + 'From'].angle(points[so.prefix + 'Middle']) + 90,
|
|
||||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) / 1.5
|
|
||||||
)
|
|
||||||
points[so.prefix + 'ToCp'] = points[so.prefix + 'To'].shift(
|
|
||||||
points[so.prefix + 'To'].angle(points[so.prefix + 'Middle']) - 90,
|
|
||||||
points[so.prefix + 'To'].dist(points[so.prefix + 'Middle']) / 1.5
|
|
||||||
)
|
|
||||||
|
|
||||||
if (so.hinge) {
|
|
||||||
points[so.prefix + 'Hinge'] = points[so.prefix + 'Middle'].shift(
|
|
||||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) +
|
|
||||||
Math.abs(
|
|
||||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'From']) -
|
|
||||||
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To'])
|
|
||||||
) /
|
|
||||||
2 +
|
|
||||||
(sa ? 180 : 0),
|
|
||||||
sa
|
|
||||||
? sa
|
|
||||||
: Math.min(
|
|
||||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']),
|
|
||||||
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle'])
|
|
||||||
) / 4
|
|
||||||
)
|
|
||||||
paths[so.prefix + 'SewTogetherHinge'] = new Path()
|
|
||||||
.move(points[so.prefix + 'Middle'])
|
|
||||||
.line(points[so.prefix + 'Hinge'])
|
|
||||||
.attr('marker-start', 'url(#sewTogetherCross)')
|
|
||||||
.attr('class', 'dotted note stroke-sm')
|
|
||||||
}
|
|
||||||
paths[so.prefix + 'SewTogether'] = new Path()
|
|
||||||
.move(points[so.prefix + 'From'])
|
|
||||||
.curve(points[so.prefix + 'FromCp'], points[so.prefix + 'ToCp'], points[so.prefix + 'To'])
|
|
||||||
.attr('class', 'dotted note stroke-sm')
|
|
||||||
.attr('marker-start', 'url(#sewTogetherStart)')
|
|
||||||
.attr('marker-end', 'url(#sewTogetherEnd)')
|
|
||||||
.attr('data-text', 'sewTogether')
|
|
||||||
.attr('data-text-class', 'center fill-note text-xs')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// More specifically named exports
|
// Export macros
|
||||||
export const sewtogetherPlugin = sewtogether
|
export const sewtogetherMacros = {
|
||||||
export const pluginSewtogether = sewtogether
|
sewtogether: function (so, { points, paths, Path, complete, scale, sa }) {
|
||||||
|
if (so === false) {
|
||||||
|
delete points.sewtogetherFrom
|
||||||
|
delete points.sewtogetherFromCp
|
||||||
|
delete points.sewtogetherMiddle
|
||||||
|
delete points.sewtogetherTo
|
||||||
|
delete points.sewtogetherHinge
|
||||||
|
delete points.sewtogetherToCp
|
||||||
|
delete paths.sewtogetherSewTogetherHinge
|
||||||
|
delete paths.sewtogetherSewTogether
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
so = {
|
||||||
|
prefix: 'sewtogether',
|
||||||
|
...so,
|
||||||
|
}
|
||||||
|
if (complete) {
|
||||||
|
if (null == so.middle) {
|
||||||
|
so.middle = so.from.shiftFractionTowards(so.to, 0.5)
|
||||||
|
}
|
||||||
|
points[so.prefix + 'From'] = so.from
|
||||||
|
points[so.prefix + 'Middle'] = so.middle
|
||||||
|
points[so.prefix + 'To'] = so.to
|
||||||
|
|
||||||
|
points[so.prefix + 'FromCp'] = points[so.prefix + 'From'].shift(
|
||||||
|
points[so.prefix + 'From'].angle(points[so.prefix + 'Middle']) + 90,
|
||||||
|
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) / 1.5
|
||||||
|
)
|
||||||
|
points[so.prefix + 'ToCp'] = points[so.prefix + 'To'].shift(
|
||||||
|
points[so.prefix + 'To'].angle(points[so.prefix + 'Middle']) - 90,
|
||||||
|
points[so.prefix + 'To'].dist(points[so.prefix + 'Middle']) / 1.5
|
||||||
|
)
|
||||||
|
|
||||||
|
if (so.hinge) {
|
||||||
|
points[so.prefix + 'Hinge'] = points[so.prefix + 'Middle'].shift(
|
||||||
|
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) +
|
||||||
|
Math.abs(
|
||||||
|
points[so.prefix + 'Middle'].angle(points[so.prefix + 'From']) -
|
||||||
|
points[so.prefix + 'Middle'].angle(points[so.prefix + 'To'])
|
||||||
|
) /
|
||||||
|
2 +
|
||||||
|
(sa ? 180 : 0),
|
||||||
|
sa
|
||||||
|
? sa
|
||||||
|
: Math.min(
|
||||||
|
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']),
|
||||||
|
points[so.prefix + 'From'].dist(points[so.prefix + 'Middle'])
|
||||||
|
) / 4
|
||||||
|
)
|
||||||
|
paths[so.prefix + 'SewTogetherHinge'] = new Path()
|
||||||
|
.move(points[so.prefix + 'Middle'])
|
||||||
|
.line(points[so.prefix + 'Hinge'])
|
||||||
|
.attr('marker-start', 'url(#sewTogetherCross)')
|
||||||
|
.attr('class', 'dotted note stroke-sm')
|
||||||
|
}
|
||||||
|
paths[so.prefix + 'SewTogether'] = new Path()
|
||||||
|
.move(points[so.prefix + 'From'])
|
||||||
|
.curve(points[so.prefix + 'FromCp'], points[so.prefix + 'ToCp'], points[so.prefix + 'To'])
|
||||||
|
.attr('class', 'dotted note stroke-sm')
|
||||||
|
.attr('marker-start', 'url(#sewTogetherStart)')
|
||||||
|
.attr('marker-end', 'url(#sewTogetherEnd)')
|
||||||
|
.attr('data-text', 'sewTogether')
|
||||||
|
.attr('data-text-class', 'center fill-note text-xs')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue